Update #0 - First Release

This commit is contained in:
LAX1DUDE
2022-12-25 01:12:28 -08:00
commit e7179fad45
2154 changed files with 256324 additions and 0 deletions

View File

@ -0,0 +1,152 @@
package net.lax1dude.eaglercraft.v1_8.internal;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
class OpenGLObjects {
static class BufferGL implements IBufferGL {
final int ptr;
BufferGL(int ptr) {
this.ptr = ptr;
}
@Override
public void free() {
PlatformOpenGL._wglDeleteBuffers(this);
}
}
static class BufferArrayGL implements IBufferArrayGL {
final int ptr;
BufferArrayGL(int ptr) {
this.ptr = ptr;
}
@Override
public void free() {
PlatformOpenGL._wglDeleteVertexArrays(this);
}
}
static class TextureGL implements ITextureGL {
final int ptr;
TextureGL(int ptr) {
this.ptr = ptr;
}
@Override
public void free() {
PlatformOpenGL._wglDeleteTextures(this);
}
}
static class ProgramGL implements IProgramGL {
final int ptr;
ProgramGL(int ptr) {
this.ptr = ptr;
}
@Override
public void free() {
PlatformOpenGL._wglDeleteProgram(this);
}
}
static class UniformGL implements IUniformGL {
final int ptr;
UniformGL(int ptr) {
this.ptr = ptr;
}
@Override
public void free() {
}
}
static class ShaderGL implements IShaderGL {
final int ptr;
ShaderGL(int ptr) {
this.ptr = ptr;
}
@Override
public void free() {
PlatformOpenGL._wglDeleteShader(this);
}
}
static class FramebufferGL implements IFramebufferGL {
final int ptr;
FramebufferGL(int ptr) {
this.ptr = ptr;
}
@Override
public void free() {
PlatformOpenGL._wglDeleteFramebuffer(this);
}
}
static class RenderbufferGL implements IRenderbufferGL {
final int ptr;
RenderbufferGL(int ptr) {
this.ptr = ptr;
}
@Override
public void free() {
PlatformOpenGL._wglDeleteRenderbuffer(this);
}
}
static class QueryGL implements IQueryGL {
final int ptr;
QueryGL(int ptr) {
this.ptr = ptr;
}
@Override
public void free() {
PlatformOpenGL._wglDeleteQueries(this);
}
}
}

View File

@ -0,0 +1,195 @@
package net.lax1dude.eaglercraft.v1_8.internal;
import static org.lwjgl.glfw.GLFW.*;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.EventQueue;
import java.awt.HeadlessException;
import java.awt.Toolkit;
import java.awt.Dialog.ModalExclusionType;
import java.awt.Dialog.ModalityType;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class PlatformApplication {
private static long win = 0l;
static void initHooks(long glfwWindow) {
win = glfwWindow;
}
public static void openLink(String url) {
try {
Desktop.getDesktop().browse(new URI(url));
} catch (Throwable var5) {
var5.printStackTrace();
}
}
public static void setClipboard(String text) {
glfwSetClipboardString(win, text);
}
public static String getClipboard() {
return glfwGetClipboardString(win);
}
public static void setLocalStorage(String name, byte[] data) {
try(FileOutputStream f = new FileOutputStream(new File("_eagstorage."+name+".dat"))) {
f.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
public static byte[] getLocalStorage(String data) {
File f = new File("_eagstorage."+data+".dat");
if(!f.isFile()) {
return null;
}
byte[] b = new byte[(int)f.length()];
try(FileInputStream s = new FileInputStream(f)) {
s.read(b);
return b;
} catch (IOException e) {
return null;
}
}
public static String saveScreenshot() {
return "nothing";
}
public static void showPopup(String msg) {
JOptionPane pane = new JOptionPane(msg, JOptionPane.WARNING_MESSAGE, JOptionPane.DEFAULT_OPTION, null,
new Object[] { "OK" }, "OK");
pane.setInitialValue("OK");
JDialog dialog = pane.createDialog("EaglercraftX Runtime");
pane.selectInitialValue();
dialog.setIconImage(Toolkit.getDefaultToolkit().getImage("icon32.png"));
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setAlwaysOnTop(true);
dialog.setModal(true);
dialog.setLocationByPlatform(true);
dialog.setModalExclusionType(ModalExclusionType.TOOLKIT_EXCLUDE);
dialog.setModalityType(ModalityType.TOOLKIT_MODAL);
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
}
private static volatile boolean fileChooserOpen = false;
private static volatile boolean fileChooserHasResult = false;
private static volatile FileChooserResult fileChooserResultObject = null;
public static void displayFileChooser(final String mime, final String ext) {
if(!fileChooserOpen) {
fileChooserOpen = true;
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
runDisplayFileChooser(mime, ext);
}
});
}
}
private static void runDisplayFileChooser(String mime, String ext) {
try {
JFileChooser fc = new FileChooserAlwaysOnTop((new File(".")).getAbsoluteFile());
fc.setDialogTitle("select a file");
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.setMultiSelectionEnabled(false);
fc.setFileFilter(new FileFilterExt(ext));
if(fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
File f = fc.getSelectedFile();
if(f != null) {
String name = f.getName();
byte[] bytes = new byte[(int)f.length()];
try(FileInputStream is = new FileInputStream(f)) {
is.read(bytes);
}
fileChooserResultObject = new FileChooserResult(name, bytes);
}else {
fileChooserResultObject = null;
}
}
}catch(Throwable t) {
fileChooserResultObject = null;
}
fileChooserOpen = false;
fileChooserHasResult = true;
}
private static class FileChooserAlwaysOnTop extends JFileChooser {
private FileChooserAlwaysOnTop(File file) {
super(file);
}
protected JDialog createDialog(Component parent) throws HeadlessException {
JDialog dialog = super.createDialog(parent);
dialog.setAlwaysOnTop(true);
return dialog;
}
}
private static class FileFilterExt extends FileFilter {
private final String extension;
private FileFilterExt(String ext) {
extension = ext;
}
@Override
public boolean accept(File f) {
return f.isDirectory() || f.getName().endsWith("." + extension);
}
@Override
public String getDescription() {
return extension + " files";
}
}
public static boolean fileChooserHasResult() {
return fileChooserHasResult;
}
public static FileChooserResult getFileChooserResult() {
fileChooserHasResult = false;
FileChooserResult res = fileChooserResultObject;
fileChooserResultObject = null;
return res;
}
public static void openCreditsPopup(String text) {
}
}

View File

@ -0,0 +1,82 @@
package net.lax1dude.eaglercraft.v1_8.internal;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import net.lax1dude.eaglercraft.v1_8.EaglerInputStream;
import net.lax1dude.eaglercraft.v1_8.opengl.ImageData;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class PlatformAssets {
static URL getDesktopResourceURL(String path) {
File f = new File("resources", path);
if(f.isFile()) {
try {
return f.toURI().toURL();
} catch (MalformedURLException e) {
return null;
}
}else {
return null;
}
}
public static final byte[] getResourceBytes(String path) {
File loadFile = new File("resources", path);
byte[] ret = new byte[(int) loadFile.length()];
try(FileInputStream is = new FileInputStream(loadFile)) {
is.read(ret);
is.close();
return ret;
}catch(IOException ex) {
return null;
}
}
public static final ImageData loadImageFile(InputStream data) {
try {
BufferedImage img = ImageIO.read(data);
int w = img.getWidth();
int h = img.getHeight();
boolean a = img.getColorModel().hasAlpha();
int[] pixels = new int[w * h];
img.getRGB(0, 0, w, h, pixels, 0, w);
for(int i = 0; i < pixels.length; ++i) {
int j = pixels[i];
if(!a) {
j = j | 0xFF000000;
}
pixels[i] = (j & 0xFF00FF00) | ((j & 0x00FF0000) >> 16) |
((j & 0x000000FF) << 16);
}
return new ImageData(w, h, pixels, a);
}catch(IOException ex) {
return null;
}
}
public static final ImageData loadImageFile(byte[] data) {
return loadImageFile(new EaglerInputStream(data));
}
}

View File

@ -0,0 +1,219 @@
package net.lax1dude.eaglercraft.v1_8.internal;
import java.net.URL;
import net.lax1dude.eaglercraft.v1_8.internal.paulscode.lwjgl3.LibraryLWJGLOpenAL;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.minecraft.util.MathHelper;
import paulscode.sound.SoundSystem;
import paulscode.sound.SoundSystemConfig;
import paulscode.sound.SoundSystemLogger;
import paulscode.sound.codecs.CodecJOrbis;
import paulscode.sound.codecs.CodecWav;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class PlatformAudio {
protected static class PaulscodeAudioResource implements IAudioResource {
protected final URL resourceLoc;
protected PaulscodeAudioResource(URL resourceLoc) {
this.resourceLoc = resourceLoc;
}
}
protected static class PaulscodeAudioHandle implements IAudioHandle {
protected final String sourceName;
protected long stall;
protected PaulscodeAudioHandle(String sourceName) {
this.sourceName = sourceName;
this.stall = System.currentTimeMillis();
}
@Override
public void pause(boolean setPaused) {
if(setPaused) {
if(sndSystem.playing(sourceName)) {
sndSystem.pause(sourceName);
}
}else {
if(!sndSystem.playing(sourceName)) {
sndSystem.play(sourceName);
}
}
}
@Override
public void restart() {
this.stall = System.currentTimeMillis();
sndSystem.rewind(sourceName);
sndSystem.play(sourceName);
}
@Override
public void move(float x, float y, float z) {
sndSystem.setPosition(sourceName, x, y, z);
}
@Override
public void pitch(float f) {
sndSystem.setPitch(sourceName, f);
}
@Override
public void gain(float f) {
sndSystem.setVolume(sourceName, f);
}
@Override
public void end() {
sndSystem.stop(sourceName);
}
@Override
public boolean shouldFree() {
return !sndSystem.playing(sourceName) && System.currentTimeMillis() - this.stall > 250l; //TODO: I hate this hack
}
}
public static IAudioResource loadAudioData(String filename, boolean holdInCache) {
URL ret = PlatformAssets.getDesktopResourceURL(filename);
if(ret != null) {
return new PaulscodeAudioResource(ret);
}else {
return null;
}
}
public static void clearAudioCache() {
// browser only
}
private static final Logger logger = LogManager.getLogger("EaglercraftPlatformAudio");
private static SoundSystem sndSystem = null;
static void platformInitialize() {
logger.info("Eaglercraft still uses Paul Lamb's SoundSystem but with LWJGL3");
logger.info(" \"Author: Paul Lamb, www.paulscode.com\"");
try {
SoundSystemConfig.addLibrary(LibraryLWJGLOpenAL.class);
SoundSystemConfig.setCodec("ogg", CodecJOrbis.class);
SoundSystemConfig.setCodec("wav", CodecWav.class);
SoundSystemConfig.setLogger(new SoundSystemLogger() {
public void message(String parString1, int parInt1) {
if (!parString1.isEmpty()) {
logger.info(parString1);
}
}
public void importantMessage(String parString1, int parInt1) {
if (!parString1.isEmpty()) {
logger.warn(parString1);
}
}
public void errorMessage(String parString1, String parString2, int parInt1) {
if (!parString2.isEmpty()) {
logger.error("Error in class \"{}\"!", parString1);
logger.error(parString2);
}
}
});
sndSystem = new SoundSystem();
}catch(Throwable t) {
logger.error("Could not initialize Paulscode SoundSystem! Is this system's OpenAL installed correctly?");
logger.error(t);
sndSystem = null;
}
}
static void platformShutdown() {
if(sndSystem != null) {
sndSystem.cleanup();
sndSystem = null;
}
}
public static boolean available() {
return sndSystem != null;
}
private static int sourceCounter = 0;
public static IAudioHandle beginPlayback(IAudioResource track, float x, float y, float z,
float volume, float pitch) {
if(sndSystem == null) {
return null;
}
float f1 = 16.0F;
if (volume > 1.0F) {
f1 *= volume;
}
String srcName = "src" + ++sourceCounter;
sndSystem.newSource(false, srcName, ((PaulscodeAudioResource)track).resourceLoc,
((PaulscodeAudioResource)track).resourceLoc.getPath(), false, x, y, z, 2, f1);
sndSystem.setTemporary(srcName, true);
sndSystem.setPitch(srcName, pitch);
sndSystem.setVolume(srcName, volume);
sndSystem.play(srcName);
return new PaulscodeAudioHandle(srcName);
}
public static IAudioHandle beginPlaybackStatic(IAudioResource track, float volume, float pitch) {
if(sndSystem == null) {
return null;
}
String srcName = "src" + ++sourceCounter;
sndSystem.newSource(false, srcName, ((PaulscodeAudioResource)track).resourceLoc,
((PaulscodeAudioResource)track).resourceLoc.getPath(), false, 0.0f, 0.0f, 0.0f, 0, 0.0f);
sndSystem.setTemporary(srcName, true);
sndSystem.setPitch(srcName, pitch);
sndSystem.setVolume(srcName, volume);
sndSystem.play(srcName);
return new PaulscodeAudioHandle(srcName);
}
public static void setListener(float x, float y, float z, float pitchDegrees, float yawDegrees) {
if(sndSystem == null) {
return;
}
float f2 = MathHelper.cos((yawDegrees + 90.0F) * 0.017453292F);
float f3 = MathHelper.sin((yawDegrees + 90.0F) * 0.017453292F);
float f4 = MathHelper.cos(-pitchDegrees * 0.017453292F);
float f5 = MathHelper.sin(-pitchDegrees * 0.017453292F);
float f6 = MathHelper.cos((-pitchDegrees + 90.0F) * 0.017453292F);
float f7 = MathHelper.sin((-pitchDegrees + 90.0F) * 0.017453292F);
float f8 = f2 * f4;
float f9 = f3 * f4;
float f10 = f2 * f6;
float f11 = f3 * f6;
sndSystem.setListenerPosition(x, y, z);
sndSystem.setListenerOrientation(f8, f5, f9, f10, f7, f11);
}
public static void setMicVol(float vol) {
// nope
}
}

View File

@ -0,0 +1,22 @@
package net.lax1dude.eaglercraft.v1_8.internal;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer;
public class PlatformBufferFunctions {
public static void put(ByteBuffer newBuffer, ByteBuffer flip) {
int len = flip.remaining();
for(int i = 0; i < len; ++i) {
newBuffer.put(flip.get());
}
}
public static void put(IntBuffer intBuffer, int index, int[] data) {
int p = intBuffer.position();
intBuffer.position(index);
intBuffer.put(data);
intBuffer.position(p);
}
}

View File

@ -0,0 +1,374 @@
package net.lax1dude.eaglercraft.v1_8.internal;
import static org.lwjgl.glfw.GLFW.*;
import java.util.LinkedList;
import java.util.List;
import org.lwjgl.PointerBuffer;
import org.lwjgl.system.MemoryStack;
import net.lax1dude.eaglercraft.v1_8.EagUtils;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class PlatformInput {
private static long win = 0l;
private static boolean windowFocused = true;
private static boolean windowResized = true;
private static boolean windowCursorEntered = true;
private static boolean windowMouseGrabbed = false;
private static int cursorX = 0;
private static int cursorY = 0;
private static int cursorDX = 0;
private static int cursorDY = 0;
private static int DWheel = 0;
private static int windowWidth = 640;
private static int windowHeight = 480;
private static final List<KeyboardEvent> keyboardEventList = new LinkedList();
private static KeyboardEvent currentKeyboardEvent = null;
private static final char[] keyboardReleaseEventChars = new char[256];
private static boolean enableRepeatEvents = false;
private static int functionKeyModifier = GLFW_KEY_F;
private static final List<Character> keyboardCharList = new LinkedList();
private static class KeyboardEvent {
protected final int key;
protected final boolean pressed;
protected final boolean repeating;
protected char resolvedCharacter = '\0';
protected KeyboardEvent(int key, boolean pressed, boolean repeating) {
this.key = key;
this.pressed = pressed;
this.repeating = repeating;
}
}
private static final List<MouseEvent> mouseEventList = new LinkedList();
private static MouseEvent currentMouseEvent = null;
private static class MouseEvent {
protected final int button;
protected final boolean pressed;
protected final int posX;
protected final int posY;
protected final float wheel;
protected MouseEvent(int button, boolean pressed, int posX, int posY, float wheel) {
this.button = button;
this.pressed = pressed;
this.posX = posX;
this.posY = posY;
this.wheel = wheel;
}
}
static void initHooks(long glfwWindow) {
win = glfwWindow;
glfwSetErrorCallback((arg0, arg1) -> {
String errorString = "<null>";
if(arg1 != 0l) {
try(MemoryStack stack = MemoryStack.stackPush()) {
PointerBuffer pbuffer = stack.mallocPointer(1);
pbuffer.put(0, arg1);
errorString = pbuffer.getStringUTF8(0);
}
}
PlatformRuntime.logger.error("GLFW Error #{}: {}", arg0, errorString);
});
if(!glfwRawMouseMotionSupported()) {
throw new UnsupportedOperationException("Raw mouse movement (cursor lock) is not supported!");
}
int[] v1 = new int[1], v2 = new int[1];
glfwGetFramebufferSize(glfwWindow, v1, v2);
windowWidth = v1[0];
windowHeight = v2[0];
glfwSetFramebufferSizeCallback(glfwWindow, (window, width, height) -> {
windowWidth = width;
windowHeight = height;
windowResized = true;
});
glfwSetWindowFocusCallback(glfwWindow, (window, focused) -> {
windowFocused = focused;
});
glfwSetKeyCallback(glfwWindow, (window, key, scancode, action, mods) -> {
if(glfwGetKey(glfwWindow, functionKeyModifier) == GLFW_PRESS) {
if(key >= GLFW_KEY_1 && key <= GLFW_KEY_9) {
key = key - GLFW_KEY_1 + GLFW_KEY_F1;
}
}
key = KeyboardConstants.getEaglerKeyFromGLFW(key);
keyboardEventList.add(new KeyboardEvent(key, action != GLFW_RELEASE, action == GLFW_REPEAT));
if(keyboardEventList.size() > 64) {
keyboardEventList.remove(0);
}
});
glfwSetCharCallback(glfwWindow, (window, character) -> {
keyboardCharList.add(Character.valueOf((char)character));
if(keyboardCharList.size() > 64) {
keyboardCharList.remove(0);
}
});
glfwSetCursorPosCallback(glfwWindow, (window, posX, posY) -> {
posY = windowHeight - posY;
if(windowMouseGrabbed) {
cursorDX -= (cursorX - (int)posX);
cursorDY -= (cursorY - (int)posY);
cursorX = (int)posX;
cursorY = (int)posY;
}else {
cursorX = (int)posX;
cursorY = (int)posY;
mouseEventList.add(new MouseEvent(-1, false, cursorX, cursorY, 0.0f));
if(mouseEventList.size() > 64) {
mouseEventList.remove(0);
}
}
});
glfwSetMouseButtonCallback(glfwWindow, (window, button, action, mods) -> {
mouseEventList.add(new MouseEvent(button, action != GLFW_RELEASE, cursorX, cursorY, 0.0f));
if(mouseEventList.size() > 64) {
mouseEventList.remove(0);
}
});
glfwSetCursorEnterCallback(glfwWindow, (window, enter) -> {
windowCursorEntered = enter;
});
glfwSetScrollCallback(glfwWindow, (window, scrollX, scrollY) -> {
DWheel += (int)scrollY;
mouseEventList.add(new MouseEvent(-1, false, cursorX, cursorY, (float)scrollY));
if(mouseEventList.size() > 64) {
mouseEventList.remove(0);
}
});
}
public static int getWindowWidth() {
return windowWidth;
}
public static int getWindowHeight() {
return windowHeight;
}
public static boolean getWindowFocused() {
return windowFocused;
}
public static boolean isCloseRequested() {
return glfwWindowShouldClose(win);
}
public static void update() {
glfwPollEvents();
glfwSwapBuffers(win);
}
public static boolean wasResized() {
boolean b = windowResized;
windowResized = false;
return b;
}
public static boolean keyboardNext() {
if(keyboardEventList.size() > 0) {
currentKeyboardEvent = keyboardEventList.remove(0);
if(currentKeyboardEvent.resolvedCharacter == '\0' && KeyboardConstants
.getKeyCharFromEagler(currentKeyboardEvent.key) != '\0') {
if(currentKeyboardEvent.pressed && keyboardCharList.size() > 0) {
currentKeyboardEvent.resolvedCharacter = keyboardCharList.remove(0);
keyboardReleaseEventChars[currentKeyboardEvent.key] =
currentKeyboardEvent.resolvedCharacter;
}else if(!currentKeyboardEvent.pressed) {
currentKeyboardEvent.resolvedCharacter =
keyboardReleaseEventChars[currentKeyboardEvent.key];
keyboardReleaseEventChars[currentKeyboardEvent.key] = '\0';
}
}
if(currentKeyboardEvent.repeating && !enableRepeatEvents) {
return keyboardNext();
}else {
return true;
}
}else {
if(keyboardCharList.size() > 0) {
currentKeyboardEvent = new KeyboardEvent(KeyboardConstants.KEY_SPACE, true, false);
currentKeyboardEvent.resolvedCharacter = keyboardCharList.remove(0);
KeyboardEvent releaseEvent = new KeyboardEvent(KeyboardConstants.KEY_SPACE, false, false);
releaseEvent.resolvedCharacter = currentKeyboardEvent.resolvedCharacter;
keyboardEventList.add(releaseEvent);
return true;
}else {
return false;
}
}
}
public static boolean keyboardGetEventKeyState() {
return currentKeyboardEvent.pressed;
}
public static int keyboardGetEventKey() {
return currentKeyboardEvent.key;
}
public static char keyboardGetEventCharacter() {
return currentKeyboardEvent.resolvedCharacter;
}
public static boolean keyboardIsKeyDown(int key) {
if(glfwGetKey(win, functionKeyModifier) == GLFW_PRESS) {
if(key >= GLFW_KEY_1 && key <= GLFW_KEY_9) {
return false;
}
if(key >= GLFW_KEY_F1 && key <= GLFW_KEY_F9) {
key = key - GLFW_KEY_F1 + GLFW_KEY_1;
}
}
return glfwGetKey(win, KeyboardConstants.getGLFWKeyFromEagler(key)) == GLFW_PRESS;
}
public static boolean keyboardIsRepeatEvent() {
return currentKeyboardEvent.repeating;
}
public static void keyboardEnableRepeatEvents(boolean b) {
enableRepeatEvents = b;
}
public static boolean mouseNext() {
if(mouseEventList.size() > 0) {
currentMouseEvent = mouseEventList.remove(0);
return true;
}else {
return false;
}
}
public static boolean mouseGetEventButtonState() {
return currentMouseEvent.pressed;
}
public static int mouseGetEventButton() {
return currentMouseEvent.button;
}
public static int mouseGetEventX() {
return currentMouseEvent.posX;
}
public static int mouseGetEventY() {
return currentMouseEvent.posY;
}
public static int mouseGetEventDWheel() {
return (int)currentMouseEvent.wheel;
}
public static int mouseGetX() {
return cursorX;
}
public static int mouseGetY() {
return cursorY;
}
public static boolean mouseIsButtonDown(int i) {
return glfwGetMouseButton(win, i) == GLFW_PRESS;
}
public static int mouseGetDWheel() {
int i = DWheel;
DWheel = 0;
return i;
}
public static void mouseSetGrabbed(boolean grab) {
if(grab != windowMouseGrabbed) {
cursorX = windowWidth / 2;
cursorY = windowHeight / 2;
glfwSetCursorPos(win, cursorX, cursorY);
windowMouseGrabbed = grab;
cursorDX = 0;
cursorDY = 0;
glfwSetInputMode(win, GLFW_CURSOR, grab ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL);
glfwSetInputMode(win, GLFW_RAW_MOUSE_MOTION, grab ? GLFW_TRUE : GLFW_FALSE);
}
}
public static boolean isPointerLocked() {
return windowMouseGrabbed;
}
public static boolean isMouseGrabbed() {
return windowMouseGrabbed;
}
public static int mouseGetDX() {
int i = cursorDX;
cursorDX = 0;
return i;
}
public static int mouseGetDY() {
int i = cursorDY;
cursorDY = 0;
return i;
}
public static void mouseSetCursorPosition(int x, int y) {
cursorX = x;
cursorY = y;
glfwSetCursorPos(win, x, y);
}
public static boolean mouseIsInsideWindow() {
return windowCursorEntered;
}
public static boolean contextLost() {
return glfwGetWindowAttrib(win, GLFW_ICONIFIED) == GLFW_TRUE;
}
public static void setFunctionKeyModifier(int key) {
functionKeyModifier = KeyboardConstants.getGLFWKeyFromEagler(key);
}
}

View File

@ -0,0 +1,136 @@
package net.lax1dude.eaglercraft.v1_8.internal;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.LinkedList;
import java.util.List;
import org.java_websocket.enums.ReadyState;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class PlatformNetworking {
static final Logger networkLogger = LogManager.getLogger("PlatformNetworking");
private static WebSocketPlayClient wsPlayClient = null;
static EnumEaglerConnectionState playConnectState = EnumEaglerConnectionState.CLOSED;
static EnumServerRateLimit serverRateLimit = null;
static String currentURI = null;
public static EnumEaglerConnectionState playConnectionState() {
return ((wsPlayClient == null || wsPlayClient.isClosed()) && playConnectState == EnumEaglerConnectionState.CONNECTING) ? EnumEaglerConnectionState.FAILED :
((wsPlayClient != null && wsPlayClient.getReadyState() == ReadyState.NOT_YET_CONNECTED) ? EnumEaglerConnectionState.CONNECTING :
(((wsPlayClient == null || wsPlayClient.isClosed()) && playConnectState != EnumEaglerConnectionState.FAILED) ? EnumEaglerConnectionState.CLOSED : playConnectState));
}
public static void startPlayConnection(String destination) {
if(!playConnectionState().isClosed()) {
networkLogger.warn("Tried connecting to a server while already connected to a different server!");
playDisconnect();
}
currentURI = destination;
synchronized(playPackets) {
playPackets.clear();
}
playConnectState = EnumEaglerConnectionState.CONNECTING;
networkLogger.info("Connecting to server: {}", destination);
URI u;
try {
u = new URI(destination);
}catch(URISyntaxException ex) {
networkLogger.error("Invalid server URI: {}", destination);
playConnectState = EnumEaglerConnectionState.FAILED;
return;
}
wsPlayClient = new WebSocketPlayClient(u);
wsPlayClient.connect();
}
public static void playDisconnect() {
if(!playConnectionState().isClosed() && wsPlayClient != null) {
try {
wsPlayClient.closeBlocking();
} catch (InterruptedException e) {
// :(
}
playConnectState = EnumEaglerConnectionState.CLOSED;
}
}
private static final List<byte[]> playPackets = new LinkedList();
public static byte[] readPlayPacket() {
synchronized(playPackets) {
return playPackets.size() > 0 ? playPackets.remove(0) : null;
}
}
public static int countAvailableReadData() {
int total = 0;
synchronized(playPackets) {
for(int i = 0, l = playPackets.size(); i < l; ++i) {
total += playPackets.get(i).length;
}
}
return total;
}
static void recievedPlayPacket(byte[] arg0) {
synchronized(playPackets) {
playPackets.add(arg0);
}
}
public static void writePlayPacket(byte[] pkt) {
if(wsPlayClient == null || wsPlayClient.isClosed()) {
networkLogger.error("Tried to send {} byte play packet while the socket was closed!", pkt.length);
}else {
wsPlayClient.send(pkt);
}
}
public static IServerQuery sendServerQuery(String uri, String accept) {
URI u;
try {
u = new URI(uri);
}catch(URISyntaxException ex) {
networkLogger.error("Invalid server URI: {}", uri);
playConnectState = EnumEaglerConnectionState.FAILED;
return null;
}
return new WebSocketServerQuery(accept, u);
}
public static EnumServerRateLimit getRateLimit() {
return serverRateLimit == null ? EnumServerRateLimit.OK : serverRateLimit;
}
public static String getCurrentURI() {
return currentURI;
}
}

View File

@ -0,0 +1,456 @@
package net.lax1dude.eaglercraft.v1_8.internal;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.EaglerLWJGLAllocator;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer;
import static org.lwjgl.opengles.GLES30.*;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class PlatformOpenGL {
public static final void _wglEnable(int glEnum) {
glEnable(glEnum);
}
public static final void _wglDisable(int glEnum) {
glDisable(glEnum);
}
public static final void _wglClearColor(float r, float g, float b, float a) {
glClearColor(r, g, b, a);
}
public static final void _wglClearDepth(float f) {
glClearDepthf(f);
}
public static final void _wglClear(int bits) {
glClear(bits);
}
public static final void _wglDepthFunc(int glEnum) {
glDepthFunc(glEnum);
}
public static final void _wglDepthMask(boolean mask) {
glDepthMask(mask);
}
public static final void _wglCullFace(int glEnum) {
glCullFace(glEnum);
}
public static final void _wglViewport(int x, int y, int w, int h) {
glViewport(x, y, w, h);
}
public static final void _wglBlendFunc(int src, int dst) {
glBlendFunc(src, dst);
}
public static final void _wglBlendFuncSeparate(int srcColor, int dstColor, int srcAlpha, int dstAlpha) {
glBlendFuncSeparate(srcColor, dstColor, srcAlpha, dstAlpha);
}
public static final void _wglBlendEquation(int glEnum) {
glBlendEquation(glEnum);
}
public static final void _wglColorMask(boolean r, boolean g, boolean b, boolean a) {
glColorMask(r, g, b, a);
}
public static final void _wglDrawBuffers(int buffer) {
glDrawBuffers(buffer);
}
public static final void _wglDrawBuffers(int[] buffers) {
glDrawBuffers(buffers);
}
public static final void _wglReadBuffer(int buffer) {
glReadBuffer(buffer);
}
public static final void _wglPolygonOffset(float f1, float f2) {
glPolygonOffset(f1, f2);
}
public static final void _wglLineWidth(float width) {
glLineWidth(width);
}
public static final IBufferGL _wglGenBuffers() {
return new OpenGLObjects.BufferGL(glGenBuffers());
}
public static final ITextureGL _wglGenTextures() {
return new OpenGLObjects.TextureGL(glGenTextures());
}
public static final IBufferArrayGL _wglGenVertexArrays() {
return new OpenGLObjects.BufferArrayGL(glGenVertexArrays());
}
public static final IProgramGL _wglCreateProgram() {
return new OpenGLObjects.ProgramGL(glCreateProgram());
}
public static final IShaderGL _wglCreateShader(int type) {
return new OpenGLObjects.ShaderGL(glCreateShader(type));
}
public static final IFramebufferGL _wglCreateFramebuffer() {
return new OpenGLObjects.FramebufferGL(glGenFramebuffers());
}
public static final IRenderbufferGL _wglCreateRenderbuffer() {
return new OpenGLObjects.RenderbufferGL(glGenRenderbuffers());
}
public static final IQueryGL _wglGenQueries() {
return new OpenGLObjects.QueryGL(glGenQueries());
}
public static final void _wglDeleteBuffers(IBufferGL obj) {
glDeleteBuffers(((OpenGLObjects.BufferGL) obj).ptr);
}
public static final void _wglDeleteTextures(ITextureGL obj) {
glDeleteTextures(((OpenGLObjects.TextureGL) obj).ptr);
}
public static final void _wglDeleteVertexArrays(IBufferArrayGL obj) {
glDeleteVertexArrays(((OpenGLObjects.BufferArrayGL) obj).ptr);
}
public static final void _wglDeleteProgram(IProgramGL obj) {
glDeleteProgram(((OpenGLObjects.ProgramGL) obj).ptr);
}
public static final void _wglDeleteShader(IShaderGL obj) {
glDeleteShader(((OpenGLObjects.ShaderGL) obj).ptr);
}
public static final void _wglDeleteFramebuffer(IFramebufferGL obj) {
glDeleteFramebuffers(((OpenGLObjects.FramebufferGL) obj).ptr);
}
public static final void _wglDeleteRenderbuffer(IRenderbufferGL obj) {
glDeleteRenderbuffers(((OpenGLObjects.RenderbufferGL) obj).ptr);
}
public static final void _wglDeleteQueries(IQueryGL obj) {
glDeleteQueries(((OpenGLObjects.QueryGL) obj).ptr);
}
public static final void _wglBindBuffer(int target, IBufferGL obj) {
glBindBuffer(target, obj == null ? 0 : ((OpenGLObjects.BufferGL) obj).ptr);
}
public static final void _wglBufferData(int target, ByteBuffer data, int usage) {
nglBufferData(target, data == null ? 0 : data.remaining(),
data == null ? 0l : EaglerLWJGLAllocator.getAddress(data), usage);
}
public static final void _wglBufferData(int target, IntBuffer data, int usage) {
nglBufferData(target, data == null ? 0 : (data.remaining() << 2),
data == null ? 0l : EaglerLWJGLAllocator.getAddress(data), usage);
}
public static final void _wglBufferData(int target, FloatBuffer data, int usage) {
nglBufferData(target, data == null ? 0 : (data.remaining() << 2),
data == null ? 0l : EaglerLWJGLAllocator.getAddress(data), usage);
}
public static final void _wglBufferData(int target, int size, int usage) {
glBufferData(target, size, usage);
}
public static final void _wglBufferSubData(int target, int offset, ByteBuffer data) {
nglBufferSubData(target, offset, data == null ? 0 : data.remaining(),
data == null ? 0l : EaglerLWJGLAllocator.getAddress(data));
}
public static final void _wglBufferSubData(int target, int offset, IntBuffer data) {
nglBufferSubData(target, offset, data == null ? 0 : (data.remaining() << 2),
data == null ? 0l : EaglerLWJGLAllocator.getAddress(data));
}
public static final void _wglBufferSubData(int target, int offset, FloatBuffer data) {
nglBufferSubData(target, offset, data == null ? 0 : (data.remaining() << 2),
data == null ? 0l : EaglerLWJGLAllocator.getAddress(data));
}
public static final void _wglBindVertexArray(IBufferArrayGL obj) {
glBindVertexArray(obj == null ? 0 : ((OpenGLObjects.BufferArrayGL) obj).ptr);
}
public static final void _wglEnableVertexAttribArray(int index) {
glEnableVertexAttribArray(index);
}
public static final void _wglDisableVertexAttribArray(int index) {
glDisableVertexAttribArray(index);
}
public static final void _wglVertexAttribPointer(int index, int size, int type, boolean normalized, int stride,
int offset) {
glVertexAttribPointer(index, size, type, normalized, stride, offset);
}
public static final void _wglVertexAttribDivisor(int index, int divisor) {
glVertexAttribDivisor(index, divisor);
}
public static final void _wglActiveTexture(int texture) {
glActiveTexture(texture);
}
public static final void _wglBindTexture(int target, ITextureGL obj) {
glBindTexture(target, obj == null ? 0 : ((OpenGLObjects.TextureGL) obj).ptr);
}
public static final void _wglTexParameterf(int target, int param, float value) {
glTexParameterf(target, param, value);
}
public static final void _wglTexParameteri(int target, int param, int value) {
glTexParameteri(target, param, value);
}
public static final void _wglTexImage2D(int target, int level, int internalFormat, int width, int height,
int border, int format, int type, ByteBuffer data) {
nglTexImage2D(target, level, internalFormat, width, height, border, format, type,
data == null ? 0l : EaglerLWJGLAllocator.getAddress(data));
}
public static final void _wglTexImage2D(int target, int level, int internalFormat, int width, int height,
int border, int format, int type, IntBuffer data) {
nglTexImage2D(target, level, internalFormat, width, height, border, format, type,
data == null ? 0l : EaglerLWJGLAllocator.getAddress(data));
}
public static final void _wglTexImage2D(int target, int level, int internalFormat, int width, int height,
int border, int format, int type, FloatBuffer data) {
nglTexImage2D(target, level, internalFormat, width, height, border, format, type,
data == null ? 0l : EaglerLWJGLAllocator.getAddress(data));
}
public static final void _wglTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height,
int format, int type, ByteBuffer data) {
glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
data == null ? 0l : EaglerLWJGLAllocator.getAddress(data));
}
public static final void _wglTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height,
int format, int type, IntBuffer data) {
glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
data == null ? 0l : EaglerLWJGLAllocator.getAddress(data));
}
public static final void _wglTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height,
int format, int type, FloatBuffer data) {
nglTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
data == null ? 0l : EaglerLWJGLAllocator.getAddress(data));
}
public static final void _wglCopyTexSubImage2D(int target, int level, int xoffset, int yoffset, int x, int y,
int width, int height) {
glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
}
public static final void _wglPixelStorei(int pname, int value) {
glPixelStorei(pname, value);
}
public static final void _wglGenerateMipmap(int target) {
glGenerateMipmap(target);
}
public static final void _wglShaderSource(IShaderGL obj, String source) {
glShaderSource(((OpenGLObjects.ShaderGL) obj).ptr, source);
}
public static final void _wglCompileShader(IShaderGL obj) {
glCompileShader(((OpenGLObjects.ShaderGL) obj).ptr);
}
public static final int _wglGetShaderi(IShaderGL obj, int param) {
return glGetShaderi(((OpenGLObjects.ShaderGL) obj).ptr, param);
}
public static final String _wglGetShaderInfoLog(IShaderGL obj) {
return glGetShaderInfoLog(((OpenGLObjects.ShaderGL) obj).ptr);
}
public static final void _wglUseProgram(IProgramGL obj) {
glUseProgram(obj == null ? 0 : ((OpenGLObjects.ProgramGL) obj).ptr);
}
public static final void _wglAttachShader(IProgramGL obj, IShaderGL shader) {
glAttachShader(((OpenGLObjects.ProgramGL) obj).ptr, ((OpenGLObjects.ShaderGL) shader).ptr);
}
public static final void _wglDetachShader(IProgramGL obj, IShaderGL shader) {
glDetachShader(((OpenGLObjects.ProgramGL) obj).ptr, ((OpenGLObjects.ShaderGL) shader).ptr);
}
public static final void _wglLinkProgram(IProgramGL obj) {
glLinkProgram(((OpenGLObjects.ProgramGL) obj).ptr);
}
public static final int _wglGetProgrami(IProgramGL obj, int param) {
return glGetProgrami(((OpenGLObjects.ProgramGL) obj).ptr, param);
}
public static final String _wglGetProgramInfoLog(IProgramGL obj) {
return glGetProgramInfoLog(((OpenGLObjects.ProgramGL) obj).ptr);
}
public static final void _wglBindAttribLocation(IProgramGL obj, int index, String name) {
glBindAttribLocation(((OpenGLObjects.ProgramGL) obj).ptr, index, name);
}
public static final int _wglGetAttribLocation(IProgramGL obj, String name) {
return glGetAttribLocation(((OpenGLObjects.ProgramGL) obj).ptr, name);
}
public static final void _wglDrawArrays(int mode, int first, int count) {
glDrawArrays(mode, first, count);
}
public static final void _wglDrawArraysInstanced(int mode, int first, int count, int instanced) {
glDrawArraysInstanced(mode, first, count, instanced);
}
public static final void _wglDrawElements(int mode, int count, int type, int offset) {
glDrawElements(mode, count, type, offset);
}
public static final void _wglDrawElementsInstanced(int mode, int count, int type, int offset, int instanced) {
glDrawElementsInstanced(mode, count, type, offset, instanced);
}
public static final IUniformGL _wglGetUniformLocation(IProgramGL obj, String name) {
int loc = glGetUniformLocation(((OpenGLObjects.ProgramGL) obj).ptr, name);
return loc < 0 ? null : new OpenGLObjects.UniformGL(loc);
}
public static final void _wglUniform1f(IUniformGL obj, float x) {
if (obj != null)
glUniform1f(((OpenGLObjects.UniformGL) obj).ptr, x);
}
public static final void _wglUniform2f(IUniformGL obj, float x, float y) {
if (obj != null)
glUniform2f(((OpenGLObjects.UniformGL) obj).ptr, x, y);
}
public static final void _wglUniform3f(IUniformGL obj, float x, float y, float z) {
if (obj != null)
glUniform3f(((OpenGLObjects.UniformGL) obj).ptr, x, y, z);
}
public static final void _wglUniform4f(IUniformGL obj, float x, float y, float z, float w) {
if (obj != null)
glUniform4f(((OpenGLObjects.UniformGL) obj).ptr, x, y, z, w);
}
public static final void _wglUniform1i(IUniformGL obj, int x) {
if (obj != null)
glUniform1i(((OpenGLObjects.UniformGL) obj).ptr, x);
}
public static final void _wglUniform2i(IUniformGL obj, int x, int y) {
if (obj != null)
glUniform2i(((OpenGLObjects.UniformGL) obj).ptr, x, y);
}
public static final void _wglUniform3i(IUniformGL obj, int x, int y, int z) {
if (obj != null)
glUniform3i(((OpenGLObjects.UniformGL) obj).ptr, x, y, z);
}
public static final void _wglUniform4i(IUniformGL obj, int x, int y, int z, int w) {
if (obj != null)
glUniform4i(((OpenGLObjects.UniformGL) obj).ptr, x, y, z, w);
}
public static final void _wglUniformMatrix2fv(IUniformGL obj, boolean transpose, FloatBuffer mat) {
if (obj != null)
nglUniformMatrix2fv(((OpenGLObjects.UniformGL) obj).ptr, mat.remaining() >> 2, transpose,
EaglerLWJGLAllocator.getAddress(mat));
}
public static final void _wglUniformMatrix3fv(IUniformGL obj, boolean transpose, FloatBuffer mat) {
if (obj != null)
nglUniformMatrix3fv(((OpenGLObjects.UniformGL) obj).ptr, mat.remaining() / 9, transpose,
EaglerLWJGLAllocator.getAddress(mat));
}
public static final void _wglUniformMatrix4fv(IUniformGL obj, boolean transpose, FloatBuffer mat) {
if (obj != null)
nglUniformMatrix4fv(((OpenGLObjects.UniformGL) obj).ptr, mat.remaining() >> 4, transpose,
EaglerLWJGLAllocator.getAddress(mat));
}
public static final void _wglBindFramebuffer(int target, IFramebufferGL framebuffer) {
glBindFramebuffer(target, framebuffer == null ? 0 : ((OpenGLObjects.FramebufferGL) framebuffer).ptr);
}
public static final int _wglCheckFramebufferStatus(int target) {
return glCheckFramebufferStatus(target);
}
public static final void _wglFramebufferTexture2D(int target, int attachment, int texTarget, ITextureGL texture,
int level) {
glFramebufferTexture2D(target, attachment, texTarget, ((OpenGLObjects.TextureGL) texture).ptr, level);
}
public static final void _wglBlitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0,
int dstX1, int dstY1, int bits, int filter) {
glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, bits, filter);
}
public static final void _wglBindRenderbuffer(int target, IRenderbufferGL renderbuffer) {
glBindRenderbuffer(target, renderbuffer == null ? 0 : ((OpenGLObjects.RenderbufferGL) renderbuffer).ptr);
}
public static final void _wglRenderbufferStorage(int target, int internalformat, int width, int height) {
glRenderbufferStorage(target, internalformat, width, height);
}
public static final void _wglFramebufferRenderbuffer(int target, int attachment, int renderbufferTarget,
IRenderbufferGL renderbuffer) {
glFramebufferRenderbuffer(target, attachment, renderbufferTarget,
((OpenGLObjects.RenderbufferGL) renderbuffer).ptr);
}
public static final String _wglGetString(int param) {
return glGetString(param);
}
public static final int _wglGetInteger(int param) {
return glGetInteger(param);
}
public static final int _wglGetError() {
return glGetError();
}
}

View File

@ -0,0 +1,448 @@
package net.lax1dude.eaglercraft.v1_8.internal;
import static org.lwjgl.egl.EGL10.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.glfw.GLFWNativeEGL.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.function.Consumer;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.InflaterInputStream;
import javax.imageio.ImageIO;
import org.lwjgl.PointerBuffer;
import org.lwjgl.egl.EGL;
import org.lwjgl.glfw.GLFWImage;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengles.GLDebugMessageKHRCallback;
import org.lwjgl.opengles.GLDebugMessageKHRCallbackI;
import org.lwjgl.opengles.GLES;
import org.lwjgl.opengles.GLES30;
import org.lwjgl.opengles.KHRDebug;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.jemalloc.JEmalloc;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.EaglerLWJGLAllocator;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.lwjgl.DesktopClientConfigAdapter;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class PlatformRuntime {
static final Logger logger = LogManager.getLogger("RuntimeLWJGL3");
private static String glVersion = "unknown";
private static String glRenderer = "unknown";
private static EnumPlatformANGLE rendererANGLEPlatform = null;
private static long windowHandle = 0l;
public static void create() {
logger.info("Starting Desktop Runtime...");
if(requestedANGLEPlatform != EnumPlatformANGLE.DEFAULT) {
logger.info("Setting ANGLE Platform: {}", requestedANGLEPlatform.name);
glfwInitHint(GLFW_ANGLE_PLATFORM_TYPE, requestedANGLEPlatform.eglEnum);
}
glfwInit();
logger.info("GLFW Version: {}", glfwGetVersionString());
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_CENTER_CURSOR, GLFW_TRUE);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
PointerBuffer buf = glfwGetMonitors();
GLFWVidMode mon = glfwGetVideoMode(buf.get(0));
int windowWidth = mon.width() - 200;
int windowHeight = mon.height() - 250;
int winX = (mon.width() - windowWidth) / 2;
int winY = (mon.height() - windowHeight - 20) / 2;
windowHandle = glfwCreateWindow(windowWidth, windowHeight, "Eaglercraft Desktop Runtime", 0l, 0l);
glfwSetWindowPos(windowHandle, winX, winY);
int[] x2 = new int[1];
int[] y2 = new int[1];
int[] w2 = new int[1];
int[] h2 = new int[1];
glfwGetWindowFrameSize(windowHandle, x2, y2, w2, h2);
glfwSetWindowSize(windowHandle, windowWidth - x2[0] - w2[0], windowHeight - y2[0] - h2[0]);
ImageIO.setUseCache(false);
BufferedImage[] windowIcons = null;
try {
windowIcons = new BufferedImage[] {
ImageIO.read(new File("icon16.png")),
ImageIO.read(new File("icon32.png"))
};
}catch(IOException t) {
logger.error("Could not load default window icons!");
logger.error(t);
}
if(windowIcons != null) {
try(MemoryStack st = MemoryStack.stackPush()) {
GLFWImage.Buffer windowIconsBuffer = GLFWImage.malloc(windowIcons.length, st);
for(int i = 0; i < windowIcons.length; ++i) {
int w = windowIcons[i].getWidth();
int h = windowIcons[i].getHeight();
int[] px = new int[w * h];
windowIcons[i].getRGB(0, 0, w, h, px, 0, w);
for(int j = 0; j < px.length; ++j) {
px[j] = (px[j] & 0xFF00FF00) | ((px[j] >> 16) & 0xFF) | ((px[j] & 0xFF) << 16); // swap R/B
}
java.nio.ByteBuffer iconBuffer = st.malloc(w * h * 4);
iconBuffer.asIntBuffer().put(px);
iconBuffer.flip();
windowIconsBuffer.position(i);
windowIconsBuffer.width(w);
windowIconsBuffer.height(h);
windowIconsBuffer.pixels(iconBuffer);
}
glfwSetWindowIcon(windowHandle, windowIconsBuffer);
}
}
long glfw_eglHandle = glfwGetEGLDisplay();
logger.info("EGL Version: {}", eglQueryString(glfw_eglHandle, EGL_VERSION));
int[] major = new int[] { 1 };
int[] minor = new int[] { 4 };
if(!eglInitialize(glfw_eglHandle, major, minor)) {
throw new RuntimeException("Could not initialize EGL");
}
EGL.createDisplayCapabilities(glfw_eglHandle, major[0], minor[0]);
glfwMakeContextCurrent(windowHandle);
GLES.createCapabilities();
logger.info("OpenGL Version: {}", (glVersion = GLES30.glGetString(GLES30.GL_VERSION)));
logger.info("OpenGL Renderer: {}", (glRenderer = GLES30.glGetString(GLES30.GL_RENDERER)));
rendererANGLEPlatform = EnumPlatformANGLE.fromGLRendererString(glRenderer);
if(requestedANGLEPlatform != EnumPlatformANGLE.DEFAULT
&& rendererANGLEPlatform != requestedANGLEPlatform) {
logger.warn("Incorrect ANGLE Platform: {}", rendererANGLEPlatform.name);
}
if(requestedANGLEPlatform == EnumPlatformANGLE.DEFAULT) {
logger.info("ANGLE Platform: {}", rendererANGLEPlatform.name);
}
glfwSwapInterval(0);
KHRDebug.glDebugMessageCallbackKHR(new GLDebugMessageKHRCallbackI() {
@Override
public void invoke(int source, int type, int id, int severity, int length, long message, long userParam) {
StringBuilder b = new StringBuilder();
b.append("[KHR DEBUG #"); b.append(id); b.append("] ");
switch(source) {
case KHRDebug.GL_DEBUG_SOURCE_API_KHR: b.append("[API - "); break;
case KHRDebug.GL_DEBUG_SOURCE_APPLICATION_KHR: b.append("[APPLICATION - "); break;
case KHRDebug.GL_DEBUG_SOURCE_SHADER_COMPILER_KHR: b.append("[SHADER COMPILER - "); break;
case KHRDebug.GL_DEBUG_SOURCE_THIRD_PARTY_KHR: b.append("[THIRD PARTY - "); break;
case KHRDebug.GL_DEBUG_SOURCE_OTHER_KHR: default: b.append("[OTHER - "); break;
}
switch(type) {
case KHRDebug.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR: b.append("DEPRECATED BEHAVIOR] "); break;
case KHRDebug.GL_DEBUG_TYPE_ERROR_KHR: b.append("ERROR] "); break;
default:
case KHRDebug.GL_DEBUG_TYPE_OTHER_KHR: b.append("OTHER] "); break;
case KHRDebug.GL_DEBUG_TYPE_PERFORMANCE_KHR: b.append("PERFORMANCE] "); break;
case KHRDebug.GL_DEBUG_TYPE_PORTABILITY_KHR: b.append("PORTABILITY] "); break;
case KHRDebug.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR: b.append("UNDEFINED BEHAVIOR] "); break;
}
switch(severity) {
default:
case KHRDebug.GL_DEBUG_SEVERITY_LOW_KHR: b.append("[LOW Severity] "); break;
case KHRDebug.GL_DEBUG_SEVERITY_MEDIUM_KHR: b.append("[MEDIUM Severity] "); break;
case KHRDebug.GL_DEBUG_SEVERITY_HIGH_KHR: b.append("[SEVERE] "); break;
}
String message2 = GLDebugMessageKHRCallback.getMessage(length, message);
if(message2.contains("GPU stall due to ReadPixels")) return;
b.append(message2);
logger.error(b.toString());
StackTraceElement[] ex = new RuntimeException().getStackTrace();
for(int i = 0; i < ex.length; ++i) {
logger.error(" at {}", ex[i]);
}
}
}, 0l);
GLES30.glEnable(KHRDebug.GL_DEBUG_OUTPUT_KHR);
GLES30.glEnable(KHRDebug.GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR);
logger.info("Initializing Audio...");
PlatformAudio.platformInitialize();
logger.info("Initializing Hooks...");
PlatformInput.initHooks(windowHandle);
}
public static void destroy() {
PlatformAudio.platformShutdown();
GLES.destroy();
EGL.destroy();
glfwDestroyWindow(windowHandle);
glfwTerminate();
}
public static EnumPlatformType getPlatformType() {
return EnumPlatformType.DESKTOP;
}
public static EnumPlatformAgent getPlatformAgent() {
return EnumPlatformAgent.DESKTOP;
}
public static String getUserAgentString() {
return "Desktop/" + System.getProperty("os.name");
}
private static EnumPlatformOS currentPlatformOS = null;
public static EnumPlatformOS getPlatformOS() {
if(currentPlatformOS == null) {
currentPlatformOS = EnumPlatformOS.getFromJVM(System.getProperty("os.name"));
}
return currentPlatformOS;
}
private static EnumPlatformANGLE requestedANGLEPlatform = EnumPlatformANGLE.DEFAULT;
public static void requestANGLE(EnumPlatformANGLE plaf) {
requestedANGLEPlatform = plaf;
}
public static EnumPlatformANGLE getPlatformANGLE() {
return rendererANGLEPlatform;
}
public static String getGLVersion() {
return glVersion;
}
public static String getGLRenderer() {
return glRenderer;
}
public static ByteBuffer allocateByteBuffer(int length) {
return EaglerLWJGLAllocator.allocByteBuffer(length);
}
public static IntBuffer allocateIntBuffer(int length) {
return EaglerLWJGLAllocator.allocIntBuffer(length);
}
public static FloatBuffer allocateFloatBuffer(int length) {
return EaglerLWJGLAllocator.allocFloatBuffer(length);
}
public static void freeByteBuffer(ByteBuffer byteBuffer) {
EaglerLWJGLAllocator.freeByteBuffer(byteBuffer);
}
public static void freeIntBuffer(IntBuffer intBuffer) {
EaglerLWJGLAllocator.freeIntBuffer(intBuffer);
}
public static void freeFloatBuffer(FloatBuffer floatBuffer) {
EaglerLWJGLAllocator.freeFloatBuffer(floatBuffer);
}
public static class NativeNIO {
public static java.nio.ByteBuffer allocateByteBuffer(int length) {
return MemoryUtil.memByteBuffer(JEmalloc.nje_malloc(length), length);
}
public static java.nio.IntBuffer allocateIntBuffer(int length) {
return MemoryUtil.memIntBuffer(JEmalloc.nje_malloc(length << 2), length);
}
public static java.nio.FloatBuffer allocateFloatBuffer(int length) {
return MemoryUtil.memFloatBuffer(JEmalloc.nje_malloc(length << 2), length);
}
public static java.nio.IntBuffer getIntBuffer(java.nio.ByteBuffer byteBuffer) {
return MemoryUtil.memIntBuffer(MemoryUtil.memAddress(byteBuffer), byteBuffer.capacity() >> 2);
}
public static java.nio.FloatBuffer getFloatBuffer(java.nio.ByteBuffer byteBuffer) {
return MemoryUtil.memFloatBuffer(MemoryUtil.memAddress(byteBuffer), byteBuffer.capacity() >> 2);
}
public static java.nio.ByteBuffer getAsByteBuffer(java.nio.IntBuffer intBuffer) {
return MemoryUtil.memByteBuffer(MemoryUtil.memAddress(intBuffer), intBuffer.capacity() << 2);
}
public static java.nio.ByteBuffer getAsByteBuffer(java.nio.FloatBuffer floatBuffer) {
return MemoryUtil.memByteBuffer(MemoryUtil.memAddress(floatBuffer), floatBuffer.capacity() << 2);
}
public static void freeByteBuffer(java.nio.ByteBuffer byteBuffer) {
JEmalloc.nje_free(MemoryUtil.memAddress(byteBuffer));
}
public static void freeIntBuffer(java.nio.IntBuffer intBuffer) {
JEmalloc.nje_free(MemoryUtil.memAddress(intBuffer));
}
public static void freeFloatBuffer(java.nio.FloatBuffer floatBuffer) {
JEmalloc.nje_free(MemoryUtil.memAddress(floatBuffer));
}
}
public static boolean isDebugRuntime() {
return true;
}
public static void writeCrashReport(String crashDump) {
File file1 = new File("./crash-reports");
if(!file1.exists()) {
if(!file1.mkdirs()) {
PlatformRuntime.logger.fatal("Could not create crash report directory: {}", file1.getAbsolutePath());
return;
}
}
File file2 = new File(file1,
"crash-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + "-client.txt");
try(FileOutputStream os = new FileOutputStream(file2)) {
os.write(crashDump.getBytes(StandardCharsets.UTF_8));
}catch(IOException ex) {
PlatformRuntime.logger.fatal("Could not write crash report: {}", file2.getAbsolutePath());
PlatformRuntime.logger.fatal(ex);
return;
}
PlatformRuntime.logger.fatal("Crash report was written to: {}", file2.getAbsolutePath());
}
public static void getStackTrace(Throwable t, Consumer<String> ret) {
StackTraceElement[] stackTrace = t.getStackTrace();
for(int i = 0; i < stackTrace.length; ++i) {
ret.accept(stackTrace[i].toString());
}
}
public static boolean printJSExceptionIfBrowser(Throwable t) {
return false;
}
public static void exit() {
System.exit(0);
}
public static void setThreadName(String string) {
Thread.currentThread().setName(string);
}
public static long maxMemory() {
return Runtime.getRuntime().maxMemory();
}
public static long totalMemory() {
return Runtime.getRuntime().totalMemory();
}
public static long freeMemory() {
return Runtime.getRuntime().freeMemory();
}
public static String getCallingClass(int backTrace) {
StackTraceElement[] astacktraceelement = Thread.currentThread().getStackTrace();
StackTraceElement stacktraceelement = astacktraceelement[Math.min(backTrace + 1, astacktraceelement.length)];
return "" + stacktraceelement.getFileName() + ":" + stacktraceelement.getLineNumber();
}
public static OutputStream newDeflaterOutputStream(OutputStream os) throws IOException {
return new DeflaterOutputStream(os);
}
public static OutputStream newGZIPOutputStream(OutputStream os) throws IOException {
return new GZIPOutputStream(os);
}
public static InputStream newInflaterInputStream(InputStream is) throws IOException {
return new InflaterInputStream(is);
}
public static InputStream newGZIPInputStream(InputStream is) throws IOException {
return new GZIPInputStream(is);
}
public static boolean requireSSL() {
return false;
}
public static IClientConfigAdapter getClientConfigAdapter() {
return DesktopClientConfigAdapter.instance;
}
public static String getRecText() {
return "recording.unsupported";
}
public static boolean recSupported() {
return false;
}
public static void toggleRec() {
//
}
}

View File

@ -0,0 +1,70 @@
package net.lax1dude.eaglercraft.v1_8.internal;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
class WebSocketPlayClient extends WebSocketClient {
public static final Logger logger = LogManager.getLogger("WebSocket");
WebSocketPlayClient(URI serverUri) {
super(serverUri);
this.setConnectionLostTimeout(15);
}
@Override
public void onOpen(ServerHandshake arg0) {
PlatformNetworking.playConnectState = EnumEaglerConnectionState.CONNECTED;
PlatformNetworking.serverRateLimit = EnumServerRateLimit.OK;
logger.info("Connection opened: {}", this.uri.toString());
}
@Override
public void onClose(int arg0, String arg1, boolean arg2) {
logger.info("Connection closed: {}", this.uri.toString());
}
@Override
public void onError(Exception arg0) {
logger.error("Exception thrown by websocket \"" + this.getURI().toString() + "\"!");
logger.error(arg0);
PlatformNetworking.playConnectState = EnumEaglerConnectionState.FAILED;
}
@Override
public void onMessage(String arg0) {
if(arg0.equalsIgnoreCase("BLOCKED")) {
logger.error("Reached full IP ratelimit!");
PlatformNetworking.serverRateLimit = EnumServerRateLimit.BLOCKED;
}else if(arg0.equalsIgnoreCase("LOCKED")) {
logger.error("Reached full IP ratelimit lockout!");
PlatformNetworking.serverRateLimit = EnumServerRateLimit.LOCKED_OUT;
}
}
@Override
public void onMessage(ByteBuffer arg0) {
PlatformNetworking.recievedPlayPacket(arg0.array());
}
}

View File

@ -0,0 +1,166 @@
package net.lax1dude.eaglercraft.v1_8.internal;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.json.JSONObject;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
class WebSocketServerQuery extends WebSocketClient implements IServerQuery {
public static final Logger logger = LogManager.getLogger("WebSocketQuery");
private final List<QueryResponse> queryResponses = new LinkedList();
private final List<byte[]> queryResponsesBytes = new LinkedList();
private final String type;
private boolean open = true;
private boolean alive = false;
private long pingStart = -1l;
private long pingTimer = -1l;
private EnumServerRateLimit rateLimit = EnumServerRateLimit.OK;
WebSocketServerQuery(String type, URI serverUri) {
super(serverUri);
this.type = type;
this.setConnectionLostTimeout(5);
this.setTcpNoDelay(true);
this.connect();
}
@Override
public int responsesAvailable() {
synchronized(queryResponses) {
return queryResponses.size();
}
}
@Override
public QueryResponse getResponse() {
synchronized(queryResponses) {
if(queryResponses.size() > 0) {
return queryResponses.remove(0);
}else {
return null;
}
}
}
@Override
public int binaryResponsesAvailable() {
synchronized(queryResponsesBytes) {
return queryResponsesBytes.size();
}
}
@Override
public byte[] getBinaryResponse() {
synchronized(queryResponsesBytes) {
if(queryResponsesBytes.size() > 0) {
return queryResponsesBytes.remove(0);
}else {
return null;
}
}
}
@Override
public QueryReadyState readyState() {
return open ? (alive ? QueryReadyState.OPEN : QueryReadyState.CONNECTING)
: (alive ? QueryReadyState.CLOSED : QueryReadyState.FAILED);
}
@Override
public EnumServerRateLimit getRateLimit() {
return rateLimit;
}
@Override
public void onClose(int arg0, String arg1, boolean arg2) {
open = false;
}
@Override
public void onError(Exception arg0) {
logger.error("Exception thrown by websocket query \"" + this.getURI().toString() + "\"!");
logger.error(arg0);
}
@Override
public void onMessage(String arg0) {
alive = true;
if(pingTimer == -1) {
pingTimer = System.currentTimeMillis() - pingStart;
if(pingTimer < 1) {
pingTimer = 1;
}
}
if(arg0.equalsIgnoreCase("BLOCKED")) {
logger.error("Reached full IP ratelimit for {}!", this.uri.toString());
rateLimit = EnumServerRateLimit.BLOCKED;
return;
}
if(arg0.equalsIgnoreCase("LOCKED")) {
logger.error("Reached full IP ratelimit lockout for {}!", this.uri.toString());
rateLimit = EnumServerRateLimit.LOCKED_OUT;
return;
}
try {
JSONObject obj = new JSONObject(arg0);
if("blocked".equalsIgnoreCase(obj.optString("type", null))) {
logger.error("Reached query ratelimit for {}!", this.uri.toString());
rateLimit = EnumServerRateLimit.BLOCKED;
}else if("locked".equalsIgnoreCase(obj.optString("type", null))) {
logger.error("Reached query ratelimit lockout for {}!", this.uri.toString());
rateLimit = EnumServerRateLimit.LOCKED_OUT;
}else {
QueryResponse response = new QueryResponse(obj, pingTimer);
synchronized(queryResponses) {
queryResponses.add(response);
}
}
}catch(Throwable t) {
logger.error("Exception thrown parsing websocket query response from \"" + this.getURI().toString() + "\"!");
logger.error(t);
}
}
@Override
public void onMessage(ByteBuffer arg0) {
alive = true;
if(pingTimer == -1) {
pingTimer = System.currentTimeMillis() - pingStart;
if(pingTimer < 1) {
pingTimer = 1;
}
}
synchronized(queryResponsesBytes) {
queryResponsesBytes.add(arg0.array());
}
}
@Override
public void onOpen(ServerHandshake arg0) {
pingStart = System.currentTimeMillis();
send("Accept: " + type);
}
}

View File

@ -0,0 +1,146 @@
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
import org.lwjgl.system.jemalloc.JEmalloc;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class EaglerLWJGLAllocator {
public static class WrongBufferClassType extends RuntimeException {
public WrongBufferClassType(String msg) {
super(msg);
}
}
public static ByteBuffer allocByteBuffer(int len) {
return new EaglerLWJGLByteBuffer(JEmalloc.nje_malloc(len), len, true);
}
public static ShortBuffer allocShortBuffer(int len) {
return new EaglerLWJGLShortBuffer(JEmalloc.nje_malloc(len << 1), len, true);
}
public static IntBuffer allocIntBuffer(int len) {
return new EaglerLWJGLIntBuffer(JEmalloc.nje_malloc(len << 2), len, true);
}
public static FloatBuffer allocFloatBuffer(int len) {
return new EaglerLWJGLFloatBuffer(JEmalloc.nje_malloc(len << 2), len, true);
}
public static void freeByteBuffer(ByteBuffer buffer) {
if(buffer instanceof EaglerLWJGLByteBuffer) {
EaglerLWJGLByteBuffer buf = (EaglerLWJGLByteBuffer)buffer;
if(buf.original) {
JEmalloc.nje_free(buf.address);
}else {
throwNotOriginal(buffer);
}
}else {
throwNotEagler(buffer);
}
}
public static long getAddress(ByteBuffer buffer) {
if(buffer instanceof EaglerLWJGLByteBuffer) {
EaglerLWJGLByteBuffer b = (EaglerLWJGLByteBuffer)buffer;
return b.address + b.position();
}else {
throw notEagler(buffer);
}
}
public static void freeShortBuffer(ShortBuffer buffer) {
if(buffer instanceof EaglerLWJGLShortBuffer) {
EaglerLWJGLShortBuffer buf = (EaglerLWJGLShortBuffer)buffer;
if(buf.original) {
JEmalloc.nje_free(buf.address);
}else {
throwNotOriginal(buffer);
}
}else {
throwNotEagler(buffer);
}
}
public static long getAddress(ShortBuffer buffer) {
if(buffer instanceof EaglerLWJGLShortBuffer) {
EaglerLWJGLShortBuffer b = (EaglerLWJGLShortBuffer)buffer;
return b.address + (b.position() << 1);
}else {
throw notEagler(buffer);
}
}
public static void freeIntBuffer(IntBuffer buffer) {
if(buffer instanceof EaglerLWJGLIntBuffer) {
EaglerLWJGLIntBuffer buf = (EaglerLWJGLIntBuffer)buffer;
if(buf.original) {
JEmalloc.nje_free(buf.address);
}else {
throwNotOriginal(buffer);
}
}else {
throwNotEagler(buffer);
}
}
public static long getAddress(IntBuffer buffer) {
if(buffer instanceof EaglerLWJGLIntBuffer) {
EaglerLWJGLIntBuffer b = (EaglerLWJGLIntBuffer)buffer;
return b.address + (b.position() << 2);
}else {
throw notEagler(buffer);
}
}
public static void freeFloatBuffer(FloatBuffer buffer) {
if(buffer instanceof EaglerLWJGLFloatBuffer) {
EaglerLWJGLFloatBuffer buf = (EaglerLWJGLFloatBuffer)buffer;
if(buf.original) {
JEmalloc.nje_free(buf.address);
}else {
throwNotOriginal(buffer);
}
}else {
throwNotEagler(buffer);
}
}
public static long getAddress(FloatBuffer buffer) {
if(buffer instanceof EaglerLWJGLFloatBuffer) {
EaglerLWJGLFloatBuffer b = (EaglerLWJGLFloatBuffer)buffer;
return b.address + (b.position() << 2);
}else {
throw notEagler(buffer);
}
}
private static void throwNotOriginal(Object clazz) {
throw notOriginal(clazz);
}
private static WrongBufferClassType notOriginal(Object clazz) {
return new WrongBufferClassType("Tried to pass a " + clazz.getClass().getSimpleName() + " which was not the original buffer");
}
private static void throwNotEagler(Object clazz) {
throw notEagler(clazz);
}
private static WrongBufferClassType notEagler(Object clazz) {
return new WrongBufferClassType("Tried to pass a " + clazz.getClass().getSimpleName() + " which is not a native eagler buffer");
}
}

View File

@ -0,0 +1,420 @@
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.jemalloc.JEmalloc;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class EaglerLWJGLByteBuffer implements ByteBuffer {
final long address;
final boolean original;
private final int capacity;
private int position;
private int limit;
private int mark;
EaglerLWJGLByteBuffer(long address, int capacity, boolean original) {
this(address, capacity, 0, capacity, -1, original);
}
EaglerLWJGLByteBuffer(long address, int capacity, int position, int limit, int mark, boolean original) {
this.address = address;
this.capacity = capacity;
this.position = position;
this.limit = limit;
this.mark = mark;
this.original = original;
}
@Override
public int capacity() {
return capacity;
}
@Override
public int position() {
return position;
}
@Override
public int limit() {
return limit;
}
@Override
public int remaining() {
return limit - position;
}
@Override
public boolean hasRemaining() {
return position < limit;
}
@Override
public boolean isReadOnly() {
return false;
}
@Override
public boolean hasArray() {
return false;
}
@Override
public Object array() {
throw new UnsupportedOperationException();
}
@Override
public boolean isDirect() {
return true;
}
@Override
public ByteBuffer slice() {
return new EaglerLWJGLByteBuffer(address + position, limit - position, false);
}
@Override
public ByteBuffer duplicate() {
return new EaglerLWJGLByteBuffer(address, capacity, position, limit, mark, false);
}
@Override
public ByteBuffer asReadOnlyBuffer() {
return new EaglerLWJGLByteBuffer(address, capacity, position, limit, mark, false);
}
@Override
public byte get() {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
return MemoryUtil.memGetByte(address + position++);
}
@Override
public ByteBuffer put(byte b) {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutByte(address + position++, b);
return this;
}
@Override
public byte get(int index) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetByte(address + index);
}
@Override
public ByteBuffer put(int index, byte b) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutByte(address + index, b);
return this;
}
@Override
public ByteBuffer get(byte[] dst, int offset, int length) {
if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1);
for(int i = 0; i < length; ++i) {
dst[offset + i] = MemoryUtil.memGetByte(address + position + i);
}
position += length;
return this;
}
@Override
public ByteBuffer get(byte[] dst) {
if(position + dst.length > limit) throw new ArrayIndexOutOfBoundsException(position + dst.length - 1);
for(int i = 0; i < dst.length; ++i) {
dst[position + i] = MemoryUtil.memGetByte(address + position + i);
}
position += dst.length;
return this;
}
@Override
public ByteBuffer put(ByteBuffer src) {
if(src instanceof EaglerLWJGLByteBuffer) {
EaglerLWJGLByteBuffer c = (EaglerLWJGLByteBuffer)src;
int l = c.limit - c.position;
if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1);
MemoryUtil.memCopy(c.address + c.position, address + position, l);
position += l;
c.position += l;
}else {
int l = src.remaining();
if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1);
for(int i = 0; i < l; ++i) {
MemoryUtil.memPutByte(address + position + l, src.get());
}
position += l;
}
return this;
}
@Override
public ByteBuffer put(byte[] src, int offset, int length) {
if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1);
for(int i = 0; i < length; ++i) {
MemoryUtil.memPutByte(address + position + i, src[offset + i]);
}
position += length;
return this;
}
@Override
public ByteBuffer put(byte[] src) {
if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1);
for(int i = 0; i < src.length; ++i) {
MemoryUtil.memPutByte(address + position + i, src[i]);
}
position += src.length;
return this;
}
@Override
public int arrayOffset() {
return position;
}
@Override
public ByteBuffer compact() {
if(limit > capacity) throw new ArrayIndexOutOfBoundsException(limit);
if(position > limit) throw new ArrayIndexOutOfBoundsException(position);
if(position == limit) {
return new EaglerLWJGLByteBuffer(0l, 0, false);
}
int newLen = limit - position;
long newAlloc = JEmalloc.nje_malloc(newLen);
MemoryUtil.memCopy(address + position, newAlloc, newLen);
return new EaglerLWJGLByteBuffer(newAlloc, newLen, true);
}
@Override
public char getChar() {
if(position + 2 > limit) throw new ArrayIndexOutOfBoundsException(position);
char c = (char)MemoryUtil.memGetShort(address + position);
position += 2;
return c;
}
@Override
public ByteBuffer putChar(char value) {
if(position + 2 > limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutShort(address + position, (short)value);
position += 2;
return this;
}
@Override
public char getChar(int index) {
if(index + 2 > limit) throw new ArrayIndexOutOfBoundsException(index);
return (char)MemoryUtil.memGetShort(address + index);
}
@Override
public ByteBuffer putChar(int index, char value) {
if(index + 2 > limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutShort(address + index, (short)value);
return this;
}
@Override
public short getShort() {
if(position + 2 > limit) throw new ArrayIndexOutOfBoundsException(position);
short s = MemoryUtil.memGetShort(address + position);
position += 2;
return s;
}
@Override
public ByteBuffer putShort(short value) {
if(position + 2 > limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutShort(address + position, value);
position += 2;
return this;
}
@Override
public short getShort(int index) {
if(index + 2 > limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetShort(address + index);
}
@Override
public ByteBuffer putShort(int index, short value) {
if(index + 2 > limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutShort(address + index, value);
return this;
}
@Override
public ShortBuffer asShortBuffer() {
return new EaglerLWJGLShortBuffer(address, capacity >> 1, false);
}
@Override
public int getInt() {
if(position + 4 > limit) throw new ArrayIndexOutOfBoundsException(position);
int i = MemoryUtil.memGetInt(address + position);
position += 4;
return i;
}
@Override
public ByteBuffer putInt(int value) {
if(position + 4 > limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutInt(address + position, value);
position += 4;
return this;
}
@Override
public int getInt(int index) {
if(index + 4 > limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetInt(address + index);
}
@Override
public ByteBuffer putInt(int index, int value) {
if(index + 4 > limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutInt(address + index, value);
return this;
}
@Override
public IntBuffer asIntBuffer() {
return new EaglerLWJGLIntBuffer(address, capacity >> 2, false);
}
@Override
public long getLong() {
if(position + 8 > limit) throw new ArrayIndexOutOfBoundsException(position);
long l = MemoryUtil.memGetLong(address + position);
position += 8;
return l;
}
@Override
public ByteBuffer putLong(long value) {
if(position + 8 > limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutLong(address + position, value);
position += 8;
return this;
}
@Override
public long getLong(int index) {
if(index + 8 > limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetLong(address + index);
}
@Override
public ByteBuffer putLong(int index, long value) {
if(index + 8 > limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutLong(address + index, value);
return this;
}
@Override
public float getFloat() {
if(position + 4 > limit) throw new ArrayIndexOutOfBoundsException(position);
float f = MemoryUtil.memGetFloat(address + position);
position += 4;
return f;
}
@Override
public ByteBuffer putFloat(float value) {
if(position + 4 > limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutFloat(address + position, value);
position += 4;
return this;
}
@Override
public float getFloat(int index) {
if(index + 4 > limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetFloat(address + index);
}
@Override
public ByteBuffer putFloat(int index, float value) {
if(index + 4 > limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutFloat(address + index, value);
return this;
}
@Override
public FloatBuffer asFloatBuffer() {
return new EaglerLWJGLFloatBuffer(address, capacity >> 2, false);
}
@Override
public ByteBuffer mark() {
mark = position;
return this;
}
@Override
public ByteBuffer reset() {
int m = mark;
if(m < 0) throw new ArrayIndexOutOfBoundsException("Invalid mark: " + m);
position = m;
return this;
}
@Override
public ByteBuffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
@Override
public ByteBuffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
@Override
public ByteBuffer rewind() {
position = 0;
mark = -1;
return this;
}
@Override
public ByteBuffer limit(int newLimit) {
if(newLimit < 0 || newLimit > capacity) throw new ArrayIndexOutOfBoundsException(newLimit);
limit = newLimit;
return this;
}
@Override
public ByteBuffer position(int newPosition) {
if(newPosition < 0 || newPosition > limit) throw new ArrayIndexOutOfBoundsException(newPosition);
position = newPosition;
return this;
}
}

View File

@ -0,0 +1,279 @@
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.jemalloc.JEmalloc;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class EaglerLWJGLFloatBuffer implements FloatBuffer {
final long address;
final boolean original;
private final int capacity;
private int position;
private int limit;
private int mark;
private static final int SHIFT = 2;
EaglerLWJGLFloatBuffer(long address, int capacity, boolean original) {
this(address, capacity, 0, capacity, -1, original);
}
EaglerLWJGLFloatBuffer(long address, int capacity, int position, int limit, int mark, boolean original) {
this.address = address;
this.capacity = capacity;
this.position = position;
this.limit = limit;
this.mark = mark;
this.original = original;
}
@Override
public int capacity() {
return capacity;
}
@Override
public int position() {
return position;
}
@Override
public int limit() {
return limit;
}
@Override
public int remaining() {
return limit - position;
}
@Override
public boolean hasRemaining() {
return position < limit;
}
@Override
public boolean isReadOnly() {
return false;
}
@Override
public boolean hasArray() {
return false;
}
@Override
public Object array() {
throw new UnsupportedOperationException();
}
@Override
public int arrayOffset() {
return position;
}
@Override
public FloatBuffer slice() {
return new EaglerLWJGLFloatBuffer(address + (position << SHIFT), limit - position, false);
}
@Override
public FloatBuffer duplicate() {
return new EaglerLWJGLFloatBuffer(address, capacity, position, limit, mark, false);
}
@Override
public FloatBuffer asReadOnlyBuffer() {
return new EaglerLWJGLFloatBuffer(address, capacity, position, limit, mark, false);
}
@Override
public float get() {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
return MemoryUtil.memGetFloat(address + ((position++) << SHIFT));
}
@Override
public FloatBuffer put(float b) {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutFloat(address + ((position++) << SHIFT), b);
return this;
}
@Override
public float get(int index) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetFloat(address + (index << SHIFT));
}
@Override
public FloatBuffer put(int index, float b) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutFloat(address + (index << SHIFT), b);
return this;
}
@Override
public float getElement(int index) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetFloat(address + (index << SHIFT));
}
@Override
public void putElement(int index, float value) {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutFloat(address + ((position++) << SHIFT), value);
}
@Override
public FloatBuffer get(float[] dst, int offset, int length) {
if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1);
for(int i = 0; i < length; ++i) {
dst[offset + i] = MemoryUtil.memGetFloat(address + ((position + i) << SHIFT));
}
position += length;
return this;
}
@Override
public FloatBuffer get(float[] dst) {
if(position + dst.length > limit) throw new ArrayIndexOutOfBoundsException(position + dst.length - 1);
for(int i = 0; i < dst.length; ++i) {
dst[i] = MemoryUtil.memGetFloat(address + ((position + i) << SHIFT));
}
position += dst.length;
return this;
}
@Override
public FloatBuffer put(FloatBuffer src) {
if(src instanceof EaglerLWJGLFloatBuffer) {
EaglerLWJGLFloatBuffer c = (EaglerLWJGLFloatBuffer)src;
int l = c.limit - c.position;
if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1);
MemoryUtil.memCopy(c.address + (c.position << SHIFT), address + (position << SHIFT), l << SHIFT);
position += l;
c.position += l;
}else {
int l = src.remaining();
if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1);
for(int i = 0; i < l; ++i) {
MemoryUtil.memPutFloat(address + ((position + l) << SHIFT), src.get());
}
position += l;
}
return this;
}
@Override
public FloatBuffer put(float[] src, int offset, int length) {
if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1);
for(int i = 0; i < length; ++i) {
MemoryUtil.memPutFloat(address + ((position + i) << SHIFT), src[offset + i]);
}
position += length;
return this;
}
@Override
public FloatBuffer put(float[] src) {
if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1);
for(int i = 0; i < src.length; ++i) {
MemoryUtil.memPutFloat(address + ((position + i) << SHIFT), src[i]);
}
position += src.length;
return this;
}
@Override
public int getArrayOffset() {
return position;
}
@Override
public FloatBuffer compact() {
if(limit > capacity) throw new ArrayIndexOutOfBoundsException(limit);
if(position > limit) throw new ArrayIndexOutOfBoundsException(position);
if(position == limit) {
return new EaglerLWJGLFloatBuffer(0l, 0, false);
}
int newLen = limit - position;
long newAlloc = JEmalloc.nje_malloc(newLen);
MemoryUtil.memCopy(address + (position << SHIFT), newAlloc, newLen << SHIFT);
return new EaglerLWJGLFloatBuffer(newAlloc, newLen, true);
}
@Override
public boolean isDirect() {
return true;
}
@Override
public FloatBuffer mark() {
mark = position;
return this;
}
@Override
public FloatBuffer reset() {
int m = mark;
if(m < 0) throw new ArrayIndexOutOfBoundsException("Invalid mark: " + m);
position = m;
return this;
}
@Override
public FloatBuffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
@Override
public FloatBuffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
@Override
public FloatBuffer rewind() {
position = 0;
mark = -1;
return this;
}
@Override
public FloatBuffer limit(int newLimit) {
if(newLimit < 0 || newLimit > capacity) throw new ArrayIndexOutOfBoundsException(newLimit);
limit = newLimit;
return this;
}
@Override
public FloatBuffer position(int newPosition) {
if(newPosition < 0 || newPosition > limit) throw new ArrayIndexOutOfBoundsException(newPosition);
position = newPosition;
return this;
}
}

View File

@ -0,0 +1,279 @@
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.jemalloc.JEmalloc;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class EaglerLWJGLIntBuffer implements IntBuffer {
final long address;
final boolean original;
private final int capacity;
private int position;
private int limit;
private int mark;
private static final int SHIFT = 2;
EaglerLWJGLIntBuffer(long address, int capacity, boolean original) {
this(address, capacity, 0, capacity, -1, original);
}
EaglerLWJGLIntBuffer(long address, int capacity, int position, int limit, int mark, boolean original) {
this.address = address;
this.capacity = capacity;
this.position = position;
this.limit = limit;
this.mark = mark;
this.original = original;
}
@Override
public int capacity() {
return capacity;
}
@Override
public int position() {
return position;
}
@Override
public int limit() {
return limit;
}
@Override
public int remaining() {
return limit - position;
}
@Override
public boolean hasRemaining() {
return position < limit;
}
@Override
public boolean isReadOnly() {
return false;
}
@Override
public boolean hasArray() {
return false;
}
@Override
public Object array() {
throw new UnsupportedOperationException();
}
@Override
public int arrayOffset() {
return position;
}
@Override
public IntBuffer slice() {
return new EaglerLWJGLIntBuffer(address + (position << SHIFT), limit - position, false);
}
@Override
public IntBuffer duplicate() {
return new EaglerLWJGLIntBuffer(address, capacity, position, limit, mark, false);
}
@Override
public IntBuffer asReadOnlyBuffer() {
return new EaglerLWJGLIntBuffer(address, capacity, position, limit, mark, false);
}
@Override
public int get() {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
return MemoryUtil.memGetInt(address + ((position++) << SHIFT));
}
@Override
public IntBuffer put(int b) {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutInt(address + ((position++) << SHIFT), b);
return this;
}
@Override
public int get(int index) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetInt(address + (index << SHIFT));
}
@Override
public IntBuffer put(int index, int b) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutInt(address + (index << SHIFT), b);
return this;
}
@Override
public int getElement(int index) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetInt(address + (index << SHIFT));
}
@Override
public void putElement(int index, int value) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutInt(address + (index << SHIFT), value);
}
@Override
public IntBuffer get(int[] dst, int offset, int length) {
if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1);
for(int i = 0; i < length; ++i) {
dst[offset + i] = MemoryUtil.memGetInt(address + ((position + i) << SHIFT));
}
position += length;
return this;
}
@Override
public IntBuffer get(int[] dst) {
if(position + dst.length > limit) throw new ArrayIndexOutOfBoundsException(position + dst.length - 1);
for(int i = 0; i < dst.length; ++i) {
dst[i] = MemoryUtil.memGetInt(address + ((position + i) << SHIFT));
}
position += dst.length;
return this;
}
@Override
public IntBuffer put(IntBuffer src) {
if(src instanceof EaglerLWJGLIntBuffer) {
EaglerLWJGLIntBuffer c = (EaglerLWJGLIntBuffer)src;
int l = c.limit - c.position;
if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1);
MemoryUtil.memCopy(c.address + (c.position << SHIFT), address + (position << SHIFT), l << SHIFT);
position += l;
c.position += l;
}else {
int l = src.remaining();
if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1);
for(int i = 0; i < l; ++i) {
MemoryUtil.memPutInt(address + ((position + l) << SHIFT), src.get());
}
position += l;
}
return this;
}
@Override
public IntBuffer put(int[] src, int offset, int length) {
if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1);
for(int i = 0; i < length; ++i) {
MemoryUtil.memPutInt(address + ((position + i) << SHIFT), src[offset + i]);
}
position += length;
return this;
}
@Override
public IntBuffer put(int[] src) {
if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1);
for(int i = 0; i < src.length; ++i) {
MemoryUtil.memPutInt(address + ((position + i) << SHIFT), src[i]);
}
position += src.length;
return this;
}
@Override
public int getArrayOffset() {
return position;
}
@Override
public IntBuffer compact() {
if(limit > capacity) throw new ArrayIndexOutOfBoundsException(limit);
if(position > limit) throw new ArrayIndexOutOfBoundsException(position);
if(position == limit) {
return new EaglerLWJGLIntBuffer(0l, 0, false);
}
int newLen = limit - position;
long newAlloc = JEmalloc.nje_malloc(newLen);
MemoryUtil.memCopy(address + (position << SHIFT), newAlloc, newLen << SHIFT);
return new EaglerLWJGLIntBuffer(newAlloc, newLen, true);
}
@Override
public boolean isDirect() {
return true;
}
@Override
public IntBuffer mark() {
mark = position;
return this;
}
@Override
public IntBuffer reset() {
int m = mark;
if(m < 0) throw new ArrayIndexOutOfBoundsException("Invalid mark: " + m);
position = m;
return this;
}
@Override
public IntBuffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
@Override
public IntBuffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
@Override
public IntBuffer rewind() {
position = 0;
mark = -1;
return this;
}
@Override
public IntBuffer limit(int newLimit) {
if(newLimit < 0 || newLimit > capacity) throw new ArrayIndexOutOfBoundsException(newLimit);
limit = newLimit;
return this;
}
@Override
public IntBuffer position(int newPosition) {
if(newPosition < 0 || newPosition > limit) throw new ArrayIndexOutOfBoundsException(newPosition);
position = newPosition;
return this;
}
}

View File

@ -0,0 +1,279 @@
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.jemalloc.JEmalloc;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class EaglerLWJGLShortBuffer implements ShortBuffer {
final long address;
final boolean original;
private final int capacity;
private int position;
private int limit;
private int mark;
private static final int SHIFT = 1;
EaglerLWJGLShortBuffer(long address, int capacity, boolean original) {
this(address, capacity, 0, capacity, -1, original);
}
EaglerLWJGLShortBuffer(long address, int capacity, int position, int limit, int mark, boolean original) {
this.address = address;
this.capacity = capacity;
this.position = position;
this.limit = limit;
this.mark = mark;
this.original = original;
}
@Override
public int capacity() {
return capacity;
}
@Override
public int position() {
return position;
}
@Override
public int limit() {
return limit;
}
@Override
public int remaining() {
return limit - position;
}
@Override
public boolean hasRemaining() {
return position < limit;
}
@Override
public boolean isReadOnly() {
return false;
}
@Override
public boolean hasArray() {
return false;
}
@Override
public Object array() {
throw new UnsupportedOperationException();
}
@Override
public int arrayOffset() {
return position;
}
@Override
public ShortBuffer slice() {
return new EaglerLWJGLShortBuffer(address + (position << SHIFT), limit - position, false);
}
@Override
public ShortBuffer duplicate() {
return new EaglerLWJGLShortBuffer(address, capacity, position, limit, mark, false);
}
@Override
public ShortBuffer asReadOnlyBuffer() {
return new EaglerLWJGLShortBuffer(address, capacity, position, limit, mark, false);
}
@Override
public short get() {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
return MemoryUtil.memGetShort(address + ((position++) << SHIFT));
}
@Override
public ShortBuffer put(short b) {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutShort(address + ((position++) << SHIFT), b);
return this;
}
@Override
public short get(int index) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetShort(address + (index << SHIFT));
}
@Override
public ShortBuffer put(int index, short b) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutShort(address + (index << SHIFT), b);
return this;
}
@Override
public short getElement(int index) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetShort(address + (index << SHIFT));
}
@Override
public void putElement(int index, short value) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutShort(address + (index << SHIFT), value);
}
@Override
public ShortBuffer get(short[] dst, int offset, int length) {
if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1);
for(int i = 0; i < length; ++i) {
dst[offset + i] = MemoryUtil.memGetShort(address + ((position + i) << SHIFT));
}
position += length;
return this;
}
@Override
public ShortBuffer get(short[] dst) {
if(position + dst.length > limit) throw new ArrayIndexOutOfBoundsException(position + dst.length - 1);
for(int i = 0; i < dst.length; ++i) {
dst[i] = MemoryUtil.memGetShort(address + ((position + i) << SHIFT));
}
position += dst.length;
return this;
}
@Override
public ShortBuffer put(ShortBuffer src) {
if(src instanceof EaglerLWJGLShortBuffer) {
EaglerLWJGLShortBuffer c = (EaglerLWJGLShortBuffer)src;
int l = c.limit - c.position;
if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1);
MemoryUtil.memCopy(c.address + (c.position << SHIFT), address + (position << SHIFT), l << SHIFT);
position += l;
c.position += l;
}else {
int l = src.remaining();
if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1);
for(int i = 0; i < l; ++i) {
MemoryUtil.memPutShort(address + ((position + l) << SHIFT), src.get());
}
position += l;
}
return this;
}
@Override
public ShortBuffer put(short[] src, int offset, int length) {
if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1);
for(int i = 0; i < length; ++i) {
MemoryUtil.memPutShort(address + ((position + i) << SHIFT), src[offset + i]);
}
position += length;
return this;
}
@Override
public ShortBuffer put(short[] src) {
if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1);
for(int i = 0; i < src.length; ++i) {
MemoryUtil.memPutShort(address + ((position + i) << SHIFT), src[i]);
}
position += src.length;
return this;
}
@Override
public int getArrayOffset() {
return position;
}
@Override
public ShortBuffer compact() {
if(limit > capacity) throw new ArrayIndexOutOfBoundsException(limit);
if(position > limit) throw new ArrayIndexOutOfBoundsException(position);
if(position == limit) {
return new EaglerLWJGLShortBuffer(0l, 0, false);
}
int newLen = limit - position;
long newAlloc = JEmalloc.nje_malloc(newLen);
MemoryUtil.memCopy(address + (position << SHIFT), newAlloc, newLen << SHIFT);
return new EaglerLWJGLShortBuffer(newAlloc, newLen, true);
}
@Override
public boolean isDirect() {
return true;
}
@Override
public ShortBuffer mark() {
mark = position;
return this;
}
@Override
public ShortBuffer reset() {
int m = mark;
if(m < 0) throw new ArrayIndexOutOfBoundsException("Invalid mark: " + m);
position = m;
return this;
}
@Override
public ShortBuffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
@Override
public ShortBuffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
@Override
public ShortBuffer rewind() {
position = 0;
mark = -1;
return this;
}
@Override
public ShortBuffer limit(int newLimit) {
if(newLimit < 0 || newLimit > capacity) throw new ArrayIndexOutOfBoundsException(newLimit);
limit = newLimit;
return this;
}
@Override
public ShortBuffer position(int newPosition) {
if(newPosition < 0 || newPosition > limit) throw new ArrayIndexOutOfBoundsException(newPosition);
position = newPosition;
return this;
}
}

View File

@ -0,0 +1,42 @@
package net.lax1dude.eaglercraft.v1_8.internal.lwjgl;
import java.util.ArrayList;
import java.util.List;
import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapter;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class DesktopClientConfigAdapter implements IClientConfigAdapter {
public static final IClientConfigAdapter instance = new DesktopClientConfigAdapter();
public final List<DefaultServer> defaultServers = new ArrayList();
@Override
public String getDefaultLocale() {
return "en_US";
}
@Override
public List<DefaultServer> getDefaultServerList() {
return defaultServers;
}
@Override
public String getServerToJoin() {
return null;
}
}

View File

@ -0,0 +1,64 @@
package net.lax1dude.eaglercraft.v1_8.internal.lwjgl;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.EagUtils;
import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformANGLE;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
import net.minecraft.client.main.Main;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class LWJGLEntryPoint {
public static void main_(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
| UnsupportedLookAndFeelException e) {
System.err.println("Could not set system look and feel: " + e.toString());
}
LaunchRenderDocDialog lr = new LaunchRenderDocDialog();
lr.setLocationRelativeTo(null);
lr.setVisible(true);
while(lr.isVisible()) {
EagUtils.sleep(100l);
}
lr.dispose();
getANGLEPlatformFromArgs(args);
EagRuntime.create();
Main.appMain(new String[0]);
}
private static void getANGLEPlatformFromArgs(String[] args) {
for(int i = 0; i < args.length; ++i) {
EnumPlatformANGLE angle = EnumPlatformANGLE.fromId(args[i]);
if(angle != EnumPlatformANGLE.DEFAULT) {
PlatformRuntime.requestANGLE(angle);
break;
}
}
}
}

View File

@ -0,0 +1,111 @@
package net.lax1dude.eaglercraft.v1_8.internal.lwjgl;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.management.ManagementFactory;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JSeparator;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class LaunchRenderDocDialog extends JDialog {
private static final long serialVersionUID = 8312760039213612790L;
private final JPanel contentPanel = new JPanel();
/**
* Create the dialog.
*/
public LaunchRenderDocDialog() {
setIconImage(Toolkit.getDefaultToolkit().getImage("icon32.png"));
setBounds(100, 100, 291, 103);
setModal(true);
setLocationByPlatform(true);
setModalExclusionType(ModalExclusionType.TOOLKIT_EXCLUDE);
setModalityType(ModalityType.TOOLKIT_MODAL);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setAlwaysOnTop(true);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setTitle("EaglercraftX: " + ManagementFactory.getRuntimeMXBean().getName());
setResizable(false);
getContentPane().setLayout(new BorderLayout());
contentPanel.setBackground(Color.WHITE);
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER);
contentPanel.setLayout(null);
{
JLabel lblNewLabel = new JLabel("Launch RenderDoc and press ok to continue...");
lblNewLabel.setBounds(10, 11, 265, 14);
contentPanel.add(lblNewLabel);
}
{
JPanel buttonPane = new JPanel();
buttonPane.setBackground(Color.WHITE);
FlowLayout fl_buttonPane = new FlowLayout(FlowLayout.RIGHT);
fl_buttonPane.setVgap(10);
fl_buttonPane.setHgap(10);
buttonPane.setLayout(fl_buttonPane);
getContentPane().add(buttonPane, BorderLayout.SOUTH);
{
JButton okButton = new JButton("OK");
okButton.setPreferredSize(new Dimension(60, 20));
okButton.setMargin(new Insets(0, 0, 0, 0));
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
LaunchRenderDocDialog.this.setVisible(false);
}
});
okButton.setActionCommand("OK");
buttonPane.add(okButton);
getRootPane().setDefaultButton(okButton);
}
{
JButton cancelButton = new JButton("Cancel");
cancelButton.setPreferredSize(new Dimension(60, 20));
cancelButton.setMargin(new Insets(0, 0, 0, 0));
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
cancelButton.setActionCommand("Cancel");
buttonPane.add(cancelButton);
}
}
JSeparator separator = new JSeparator();
getContentPane().add(separator, BorderLayout.NORTH);
}
}

View File

@ -0,0 +1,9 @@
package net.lax1dude.eaglercraft.v1_8.internal.lwjgl;
public class MainClass {
public static void main(String[] args) {
LWJGLEntryPoint.main_(args);
}
}

View File

@ -0,0 +1,37 @@
package net.lax1dude.eaglercraft.v1_8.internal.lwjgl;
import net.lax1dude.eaglercraft.v1_8.Display;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.EagUtils;
import net.lax1dude.eaglercraft.v1_8.Keyboard;
import net.lax1dude.eaglercraft.v1_8.Mouse;
import net.lax1dude.eaglercraft.v1_8.internal.KeyboardConstants;
public class TestProgram {
private static boolean grab = false;
public static void main_(String[] args) {
while(!Display.isCloseRequested()) {
Keyboard.enableRepeatEvents(true);
Display.update();
while(Keyboard.next()) {
if(Keyboard.getEventKey() == KeyboardConstants.KEY_E && Keyboard.getEventKeyState()) {
grab = !grab;
Mouse.setGrabbed(grab);
}
}
System.out.println("" + Mouse.getDX() + ", " + Mouse.getDY());
EagUtils.sleep(100l);
}
EagRuntime.destroy();
}
}

View File

@ -0,0 +1,602 @@
package net.lax1dude.eaglercraft.v1_8.internal.paulscode.lwjgl3;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.LinkedList;
import javax.sound.sampled.AudioFormat;
// From the lwjgl library, http://www.lwjgl.org
import org.lwjgl.BufferUtils;
import org.lwjgl.openal.AL10;
import org.lwjgl.openal.AL11;
import paulscode.sound.Channel;
import paulscode.sound.SoundSystemConfig;
/**
* The ChannelLWJGLOpenAL class is used to reserve a sound-card voice using the
* lwjgl binding of OpenAL. Channels can be either normal or streaming channels.
* <b><br>
* <br>
* This software is based on or using the LWJGL Lightweight Java Gaming Library
* available from http://www.lwjgl.org/. </b><br>
* <br>
* LWJGL License: <br>
* <i> Copyright (c) 2002-2008 Lightweight Java Game Library Project All rights
* reserved. <br>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* <br>
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer. <br>
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. <br>
* * Neither the name of 'Light Weight Java Game Library' nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission. <br>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. <br>
* <br>
* <br>
* </i> <b><i> SoundSystem LibraryLWJGLOpenAL License:</b></i><br>
* <b><br>
* <b> You are free to use this library for any purpose, commercial or
* otherwise. You may modify this library or source code, and distribute it any
* way you like, provided the following conditions are met: <br>
* 1) You must abide by the conditions of the aforementioned LWJGL License. <br>
* 2) You may not falsely claim to be the author of this library or any
* unmodified portion of it. <br>
* 3) You may not copyright this library or a modified version of it and then
* sue me for copyright infringement. <br>
* 4) If you modify the source code, you must clearly document the changes made
* before redistributing the modified source code, so other users know it is not
* the original code. <br>
* 5) You are not required to give me credit for this library in any derived
* work, but if you do, you must also mention my website:
* http://www.paulscode.com <br>
* 6) I the author will not be responsible for any damages (physical, financial,
* or otherwise) caused by the use if this library or any part of it. <br>
* 7) I the author do not guarantee, warrant, or make any representations,
* either expressed or implied, regarding the use of this library or any part of
* it. <br>
* <br>
* Author: Paul Lamb <br>
* http://www.paulscode.com </b>
*/
public class ChannelLWJGLOpenAL extends Channel {
/**
* OpenAL's IntBuffer identifier for this channel.
*/
public IntBuffer ALSource;
/**
* OpenAL data format to use when playing back the assigned source.
*/
public int ALformat; // OpenAL data format
/**
* Sample rate (speed) to use for play-back.
*/
public int sampleRate; // sample rate
/**
* Miliseconds of buffers previously played (streaming sources).
*/
public float millisPreviouslyPlayed = 0;
/**
* Constructor: takes channelType identifier and a handle to the OpenAL
* IntBuffer identifier to use for this channel. Possible values for channel
* type can be found in the {@link paulscode.sound.SoundSystemConfig
* SoundSystemConfig} class.
*
* @param type Type of channel (normal or streaming).
* @param src Handle to the OpenAL source identifier.
*/
public ChannelLWJGLOpenAL(int type, IntBuffer src) {
super(type);
libraryType = LibraryLWJGLOpenAL.class;
ALSource = src;
}
/**
* Empties the streamBuffers list, stops and deletes the ALSource, shuts the
* channel down, and removes references to all instantiated objects.
*/
@Override
public void cleanup() {
if (ALSource != null) {
try {
// Stop playing the source:
AL10.alSourceStop(ALSource.get(0));
AL10.alGetError();
} catch (Exception e) {
}
try {
// Delete the source:
AL10.alDeleteSources(ALSource);
AL10.alGetError();
} catch (Exception e) {
}
ALSource.clear();
}
ALSource = null;
super.cleanup();
}
/**
* Attaches an OpenAL sound-buffer identifier for the sound data to be played
* back for a normal source.
*
* @param buf Intbuffer identifier for the sound data to play.
* @return False if an error occurred.
*/
public boolean attachBuffer(IntBuffer buf) {
// A sound buffer can only be attached to a normal source:
if (errorCheck(channelType != SoundSystemConfig.TYPE_NORMAL,
"Sound buffers may only be attached to normal " + "sources."))
return false;
// send the sound buffer to the channel:
AL10.alSourcei(ALSource.get(0), AL10.AL_BUFFER, buf.get(0));
// save the format for later, for determining milliseconds played
if (attachedSource != null && attachedSource.soundBuffer != null
&& attachedSource.soundBuffer.audioFormat != null)
setAudioFormat(attachedSource.soundBuffer.audioFormat);
// Check for errors and return:
return checkALError();
}
/**
* Sets the channel up to receive the specified audio format.
*
* @param audioFormat Format to use when playing the stream data.
*/
@Override
public void setAudioFormat(AudioFormat audioFormat) {
int soundFormat = 0;
if (audioFormat.getChannels() == 1) {
if (audioFormat.getSampleSizeInBits() == 8) {
soundFormat = AL10.AL_FORMAT_MONO8;
} else if (audioFormat.getSampleSizeInBits() == 16) {
soundFormat = AL10.AL_FORMAT_MONO16;
} else {
errorMessage("Illegal sample size in method " + "'setAudioFormat'");
return;
}
} else if (audioFormat.getChannels() == 2) {
if (audioFormat.getSampleSizeInBits() == 8) {
soundFormat = AL10.AL_FORMAT_STEREO8;
} else if (audioFormat.getSampleSizeInBits() == 16) {
soundFormat = AL10.AL_FORMAT_STEREO16;
} else {
errorMessage("Illegal sample size in method " + "'setAudioFormat'");
return;
}
} else {
errorMessage("Audio data neither mono nor stereo in " + "method 'setAudioFormat'");
return;
}
ALformat = soundFormat;
sampleRate = (int) audioFormat.getSampleRate();
}
/**
* Sets the channel up to receive the specified OpenAL audio format and sample
* rate.
*
* @param format Format to use.
* @param rate Sample rate (speed) to use.
*/
public void setFormat(int format, int rate) {
ALformat = format;
sampleRate = rate;
}
/**
* Queues up the initial byte[] buffers of data to be streamed.
*
* @param bufferList List of the first buffers to be played for a streaming
* source.
* @return False if problem occurred or if end of stream was reached.
*/
@Override
public boolean preLoadBuffers(LinkedList<byte[]> bufferList) {
// Stream buffers can only be queued for streaming sources:
if (errorCheck(channelType != SoundSystemConfig.TYPE_STREAMING,
"Buffers may only be queued for streaming sources."))
return false;
if (errorCheck(bufferList == null, "Buffer List null in method 'preLoadBuffers'"))
return false;
IntBuffer streamBuffers;
// Remember if the channel was playing:
boolean playing = playing();
// stop the channel if it is playing:
if (playing) {
AL10.alSourceStop(ALSource.get(0));
checkALError();
}
// Clear out any previously queued buffers:
int processed = AL10.alGetSourcei(ALSource.get(0), AL10.AL_BUFFERS_PROCESSED);
if (processed > 0) {
streamBuffers = BufferUtils.createIntBuffer(processed);
AL10.alGenBuffers(streamBuffers);
if (errorCheck(checkALError(), "Error clearing stream buffers in method 'preLoadBuffers'"))
return false;
AL10.alSourceUnqueueBuffers(ALSource.get(0), streamBuffers);
if (errorCheck(checkALError(), "Error unqueuing stream buffers in method 'preLoadBuffers'"))
return false;
}
// restart the channel if it was previously playing:
if (playing) {
AL10.alSourcePlay(ALSource.get(0));
checkALError();
}
streamBuffers = BufferUtils.createIntBuffer(bufferList.size());
AL10.alGenBuffers(streamBuffers);
if (errorCheck(checkALError(), "Error generating stream buffers in method 'preLoadBuffers'"))
return false;
ByteBuffer byteBuffer = null;
for (int i = 0; i < bufferList.size(); i++) {
// byteBuffer = ByteBuffer.wrap( bufferList.get(i), 0,
// bufferList.get(i).length );
byteBuffer = (ByteBuffer) BufferUtils.createByteBuffer(bufferList.get(i).length).put(bufferList.get(i))
.flip();
try {
AL10.alBufferData(streamBuffers.get(i), ALformat, byteBuffer, sampleRate);
} catch (Exception e) {
errorMessage("Error creating buffers in method " + "'preLoadBuffers'");
printStackTrace(e);
return false;
}
if (errorCheck(checkALError(), "Error creating buffers in method 'preLoadBuffers'"))
return false;
}
try {
AL10.alSourceQueueBuffers(ALSource.get(0), streamBuffers);
} catch (Exception e) {
errorMessage("Error queuing buffers in method 'preLoadBuffers'");
printStackTrace(e);
return false;
}
if (errorCheck(checkALError(), "Error queuing buffers in method 'preLoadBuffers'"))
return false;
AL10.alSourcePlay(ALSource.get(0));
if (errorCheck(checkALError(), "Error playing source in method 'preLoadBuffers'"))
return false;
// Success:
return true;
}
/**
* Queues up a byte[] buffer of data to be streamed.
*
* @param buffer The next buffer to be played for a streaming source.
* @return False if an error occurred or if the channel is shutting down.
*/
@Override
public boolean queueBuffer(byte[] buffer) {
// Stream buffers can only be queued for streaming sources:
if (errorCheck(channelType != SoundSystemConfig.TYPE_STREAMING,
"Buffers may only be queued for streaming sources."))
return false;
// ByteBuffer byteBuffer = ByteBuffer.wrap( buffer, 0, buffer.length );
ByteBuffer byteBuffer = (ByteBuffer) BufferUtils.createByteBuffer(buffer.length).put(buffer).flip();
IntBuffer intBuffer = BufferUtils.createIntBuffer(1);
AL10.alSourceUnqueueBuffers(ALSource.get(0), intBuffer);
if (checkALError())
return false;
if (AL10.alIsBuffer(intBuffer.get(0)))
millisPreviouslyPlayed += millisInBuffer(intBuffer.get(0));
checkALError();
AL10.alBufferData(intBuffer.get(0), ALformat, byteBuffer, sampleRate);
if (checkALError())
return false;
AL10.alSourceQueueBuffers(ALSource.get(0), intBuffer);
if (checkALError())
return false;
return true;
}
/**
* Feeds raw data to the stream.
*
* @param buffer Buffer containing raw audio data to stream.
* @return Number of prior buffers that have been processed., or -1 if error.
*/
@Override
public int feedRawAudioData(byte[] buffer) {
// Stream buffers can only be queued for streaming sources:
if (errorCheck(channelType != SoundSystemConfig.TYPE_STREAMING,
"Raw audio data can only be fed to streaming sources."))
return -1;
// ByteBuffer byteBuffer = ByteBuffer.wrap( buffer, 0, buffer.length );
ByteBuffer byteBuffer = (ByteBuffer) BufferUtils.createByteBuffer(buffer.length).put(buffer).flip();
IntBuffer intBuffer;
// Clear out any previously queued buffers:
int processed = AL10.alGetSourcei(ALSource.get(0), AL10.AL_BUFFERS_PROCESSED);
if (processed > 0) {
intBuffer = BufferUtils.createIntBuffer(processed);
AL10.alGenBuffers(intBuffer);
if (errorCheck(checkALError(), "Error clearing stream buffers in method 'feedRawAudioData'"))
return -1;
AL10.alSourceUnqueueBuffers(ALSource.get(0), intBuffer);
if (errorCheck(checkALError(), "Error unqueuing stream buffers in method 'feedRawAudioData'"))
return -1;
int i;
intBuffer.rewind();
while (intBuffer.hasRemaining()) {
i = intBuffer.get();
if (AL10.alIsBuffer(i)) {
millisPreviouslyPlayed += millisInBuffer(i);
}
checkALError();
}
AL10.alDeleteBuffers(intBuffer);
checkALError();
}
intBuffer = BufferUtils.createIntBuffer(1);
AL10.alGenBuffers(intBuffer);
if (errorCheck(checkALError(), "Error generating stream buffers in method 'preLoadBuffers'"))
return -1;
AL10.alBufferData(intBuffer.get(0), ALformat, byteBuffer, sampleRate);
if (checkALError())
return -1;
AL10.alSourceQueueBuffers(ALSource.get(0), intBuffer);
if (checkALError())
return -1;
if (attachedSource != null && attachedSource.channel == this && attachedSource.active()) {
// restart the channel if it was previously playing:
if (!playing()) {
AL10.alSourcePlay(ALSource.get(0));
checkALError();
}
}
return processed;
}
/**
* Returns the number of milliseconds of audio contained in specified buffer.
*
* @return milliseconds, or 0 if unable to calculate.
*/
public float millisInBuffer(int alBufferi) {
return (((float) AL10.alGetBufferi(alBufferi, AL10.AL_SIZE)
/ (float) AL10.alGetBufferi(alBufferi, AL10.AL_CHANNELS)
/ ((float) AL10.alGetBufferi(alBufferi, AL10.AL_BITS) / 8.0f) / (float) sampleRate) * 1000);
}
/**
* Calculates the number of milliseconds since the channel began playing.
*
* @return Milliseconds, or -1 if unable to calculate.
*/
@Override
public float millisecondsPlayed() {
// get number of samples played in current buffer
float offset = (float) AL10.alGetSourcei(ALSource.get(0), AL11.AL_BYTE_OFFSET);
float bytesPerFrame = 1f;
switch (ALformat) {
case AL10.AL_FORMAT_MONO8:
bytesPerFrame = 1f;
break;
case AL10.AL_FORMAT_MONO16:
bytesPerFrame = 2f;
break;
case AL10.AL_FORMAT_STEREO8:
bytesPerFrame = 2f;
break;
case AL10.AL_FORMAT_STEREO16:
bytesPerFrame = 4f;
break;
default:
break;
}
offset = (((float) offset / bytesPerFrame) / (float) sampleRate) * 1000;
// add the milliseconds from stream-buffers that played previously
if (channelType == SoundSystemConfig.TYPE_STREAMING)
offset += millisPreviouslyPlayed;
// Return millis played:
return (offset);
}
/**
* Returns the number of queued byte[] buffers that have finished playing.
*
* @return Number of buffers processed.
*/
@Override
public int buffersProcessed() {
// Only streaming sources process buffers:
if (channelType != SoundSystemConfig.TYPE_STREAMING)
return 0;
// determine how many have been processed:
int processed = AL10.alGetSourcei(ALSource.get(0), AL10.AL_BUFFERS_PROCESSED);
// Check for errors:
if (checkALError())
return 0;
// Return how many were processed:
return processed;
}
/**
* Dequeues all previously queued data.
*/
@Override
public void flush() {
// Only a streaming source can be flushed, because only streaming
// sources have queued buffers:
if (channelType != SoundSystemConfig.TYPE_STREAMING)
return;
// determine how many buffers have been queued:
int queued = AL10.alGetSourcei(ALSource.get(0), AL10.AL_BUFFERS_QUEUED);
// Check for errors:
if (checkALError())
return;
IntBuffer intBuffer = BufferUtils.createIntBuffer(1);
while (queued > 0) {
try {
AL10.alSourceUnqueueBuffers(ALSource.get(0), intBuffer);
} catch (Exception e) {
return;
}
if (checkALError())
return;
queued--;
}
millisPreviouslyPlayed = 0;
}
/**
* Stops the channel, dequeues any queued data, and closes the channel.
*/
@Override
public void close() {
try {
AL10.alSourceStop(ALSource.get(0));
AL10.alGetError();
} catch (Exception e) {
}
if (channelType == SoundSystemConfig.TYPE_STREAMING)
flush();
}
/**
* Plays the currently attached normal source, opens this channel up for
* streaming, or resumes playback if this channel was paused.
*/
@Override
public void play() {
AL10.alSourcePlay(ALSource.get(0));
checkALError();
}
/**
* Temporarily stops playback for this channel.
*/
@Override
public void pause() {
AL10.alSourcePause(ALSource.get(0));
checkALError();
}
/**
* Stops playback for this channel and rewinds the attached source to the
* beginning.
*/
@Override
public void stop() {
AL10.alSourceStop(ALSource.get(0));
if (!checkALError())
millisPreviouslyPlayed = 0;
}
/**
* Rewinds the attached source to the beginning. Stops the source if it was
* paused.
*/
@Override
public void rewind() {
// rewinding for streaming sources is handled elsewhere
if (channelType == SoundSystemConfig.TYPE_STREAMING)
return;
AL10.alSourceRewind(ALSource.get(0));
if (!checkALError())
millisPreviouslyPlayed = 0;
}
/**
* Used to determine if a channel is actively playing a source. This method will
* return false if the channel is paused or stopped and when no data is queued
* to be streamed.
*
* @return True if this channel is playing a source.
*/
@Override
public boolean playing() {
int state = AL10.alGetSourcei(ALSource.get(0), AL10.AL_SOURCE_STATE);
if (checkALError())
return false;
return (state == AL10.AL_PLAYING);
}
/**
* Checks for OpenAL errors, and prints a message if there is an error.
*
* @return True if there was an error, False if not.
*/
private boolean checkALError() {
switch (AL10.alGetError()) {
case AL10.AL_NO_ERROR:
return false;
case AL10.AL_INVALID_NAME:
errorMessage("Invalid name parameter.");
return true;
case AL10.AL_INVALID_ENUM:
errorMessage("Invalid parameter.");
return true;
case AL10.AL_INVALID_VALUE:
errorMessage("Invalid enumerated parameter value.");
return true;
case AL10.AL_INVALID_OPERATION:
errorMessage("Illegal call.");
return true;
case AL10.AL_OUT_OF_MEMORY:
errorMessage("Unable to allocate memory.");
return true;
default:
errorMessage("An unrecognized error occurred.");
return true;
}
}
}

View File

@ -0,0 +1,984 @@
package net.lax1dude.eaglercraft.v1_8.internal.paulscode.lwjgl3;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.FloatBuffer;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import javax.sound.sampled.AudioFormat;
import org.lwjgl.BufferUtils;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.AL10;
import org.lwjgl.openal.ALC;
import org.lwjgl.openal.ALC11;
import org.lwjgl.openal.ALCCapabilities;
import org.lwjgl.openal.SOFTHRTF;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import paulscode.sound.Channel;
import paulscode.sound.FilenameURL;
import paulscode.sound.ICodec;
import paulscode.sound.Library;
import paulscode.sound.ListenerData;
import paulscode.sound.SoundBuffer;
import paulscode.sound.SoundSystemConfig;
import paulscode.sound.SoundSystemException;
import paulscode.sound.Source;
/**
* The LibraryLWJGLOpenAL class interfaces the lwjgl binding of OpenAL. <b><br>
* <br>
* This software is based on or using the LWJGL Lightweight Java Gaming Library
* available from http://www.lwjgl.org/. </b><br>
* <br>
* LWJGL License: <br>
* <i> Copyright (c) 2002-2008 Lightweight Java Game Library Project All rights
* reserved. <br>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* <br>
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer. <br>
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. <br>
* * Neither the name of 'Light Weight Java Game Library' nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission. <br>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. <br>
* <br>
* <br>
* </i> <b><i> SoundSystem LibraryLWJGLOpenAL License:</b></i><br>
* <b><br>
* <b> You are free to use this library for any purpose, commercial or
* otherwise. You may modify this library or source code, and distribute it any
* way you like, provided the following conditions are met: <br>
* 1) You must abide by the conditions of the aforementioned LWJGL License. <br>
* 2) You may not falsely claim to be the author of this library or any
* unmodified portion of it. <br>
* 3) You may not copyright this library or a modified version of it and then
* sue me for copyright infringement. <br>
* 4) If you modify the source code, you must clearly document the changes made
* before redistributing the modified source code, so other users know it is not
* the original code. <br>
* 5) You are not required to give me credit for this library in any derived
* work, but if you do, you must also mention my website:
* http://www.paulscode.com <br>
* 6) I the author will not be responsible for any damages (physical, financial,
* or otherwise) caused by the use if this library or any part of it. <br>
* 7) I the author do not guarantee, warrant, or make any representations,
* either expressed or implied, regarding the use of this library or any part of
* it. <br>
* <br>
* Author: Paul Lamb <br>
* http://www.paulscode.com </b>
*/
public class LibraryLWJGLOpenAL extends Library {
/**
* Used to return a current value from one of the synchronized boolean-interface
* methods.
*/
private static final boolean GET = false;
/**
* Used to set the value in one of the synchronized boolean-interface methods.
*/
private static final boolean SET = true;
/**
* Used when a parameter for one of the synchronized boolean-interface methods
* is not aplicable.
*/
private static final boolean XXX = false;
/**
* Position of the listener in 3D space.
*/
private FloatBuffer listenerPositionAL = null;
/**
* Information about the listener's orientation.
*/
private FloatBuffer listenerOrientation = null;
/**
* Velocity of the listener.
*/
private FloatBuffer listenerVelocity = null;
/**
* Map containing OpenAL identifiers for sound buffers.
*/
private HashMap<String, IntBuffer> ALBufferMap = null;
/**
* Whether or not the AL_PITCH control is supported.
*/
private static boolean alPitchSupported = true;
/**
* Constructor: Instantiates the source map, buffer map and listener
* information. Also sets the library type to SoundSystemConfig.LIBRARY_OPENAL
*/
public LibraryLWJGLOpenAL() throws SoundSystemException {
super();
ALBufferMap = new HashMap<String, IntBuffer>();
reverseByteOrder = true;
}
private long openALDevice = 0l;
private long openALContext = 0l;
private static final Logger logger = LogManager.getLogger("SoundSystem");
/**
* Initializes OpenAL, creates the listener, and grabs up audio channels.
*/
@Override
public void init() throws SoundSystemException {
boolean errors = false; // set to 'true' if error(s) occur:
//TODO: eaglercraft
openALDevice = ALC11.alcOpenDevice((String)null);
ALCCapabilities caps;
if (openALDevice == 0l) {
logger.error("Unable to initialize OpenAL!");
throw new LibraryLWJGLOpenAL.Exception("Unable to initialize OpenAL", LibraryLWJGLOpenAL.Exception.CREATE);
}else {
caps = ALC.createCapabilities(openALDevice);
logger.info("Device opened: {}", openALDevice);
}
openALContext = ALC11.alcCreateContext(openALDevice, new int[] { SOFTHRTF.ALC_HRTF_SOFT, 1, 0 });
if(!ALC11.alcMakeContextCurrent(openALContext)) {
ALC11.alcCloseDevice(openALDevice);
logger.error("Unable to initialize AL context!");
throw new LibraryLWJGLOpenAL.Exception("Unable to initialize OpenAL", LibraryLWJGLOpenAL.Exception.CREATE);
}
AL.createCapabilities(caps);
// Let user know if the library loaded properly
if (errors)
importantMessage("OpenAL did not initialize properly!");
else
message("OpenAL initialized.");
// Listener is at the origin, facing along the z axis, no velocity:
listenerPositionAL = BufferUtils.createFloatBuffer(3)
.put(new float[] { listener.position.x, listener.position.y, listener.position.z });
listenerOrientation = BufferUtils.createFloatBuffer(6).put(new float[] { listener.lookAt.x, listener.lookAt.y,
listener.lookAt.z, listener.up.x, listener.up.y, listener.up.z });
listenerVelocity = BufferUtils.createFloatBuffer(3).put(new float[] { 0.0f, 0.0f, 0.0f });
// Flip the buffers, so they can be used:
listenerPositionAL.flip();
listenerOrientation.flip();
listenerVelocity.flip();
// Pass the buffers to the sound system, and check for potential errors:
AL10.alListenerfv(AL10.AL_POSITION, listenerPositionAL);
errors = checkALError() || errors;
AL10.alListenerfv(AL10.AL_ORIENTATION, listenerOrientation);
errors = checkALError() || errors;
AL10.alListenerfv(AL10.AL_VELOCITY, listenerVelocity);
errors = checkALError() || errors;
AL10.alDopplerFactor(SoundSystemConfig.getDopplerFactor());
errors = checkALError() || errors;
AL10.alDopplerVelocity(SoundSystemConfig.getDopplerVelocity());
errors = checkALError() || errors;
// Let user know what caused the above error messages:
if (errors) {
importantMessage("OpenAL did not initialize properly!");
throw new LibraryLWJGLOpenAL.Exception("Problem encountered " + "while loading OpenAL or "
+ "creating the listener. " + "Probable cause: OpenAL not " + "supported",
LibraryLWJGLOpenAL.Exception.CREATE);
}
super.init();
// Check if we can use the AL_PITCH control:
ChannelLWJGLOpenAL channel = (ChannelLWJGLOpenAL) normalChannels.get(1);
try {
AL10.alSourcef(channel.ALSource.get(0), AL10.AL_PITCH, 1.0f);
if (checkALError()) {
alPitchSupported(SET, false);
throw new LibraryLWJGLOpenAL.Exception("OpenAL: AL_PITCH not " + "supported.",
LibraryLWJGLOpenAL.Exception.NO_AL_PITCH);
} else {
alPitchSupported(SET, true);
}
} catch (java.lang.Exception e) {
alPitchSupported(SET, false);
throw new LibraryLWJGLOpenAL.Exception("OpenAL: AL_PITCH not " + "supported.",
LibraryLWJGLOpenAL.Exception.NO_AL_PITCH);
}
}
/**
* Checks if the OpenAL library type is compatible.
*
* @return True or false.
*/
public static boolean libraryCompatible() {
return true;
}
/**
* Creates a new channel of the specified type (normal or streaming). Possible
* values for channel type can be found in the
* {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} class.
*
* @param type Type of channel.
*/
@Override
protected Channel createChannel(int type) {
ChannelLWJGLOpenAL channel;
IntBuffer ALSource;
ALSource = BufferUtils.createIntBuffer(1);
try {
AL10.alGenSources(ALSource);
} catch (java.lang.Exception e) {
AL10.alGetError();
return null; // no more voices left
}
if (AL10.alGetError() != AL10.AL_NO_ERROR)
return null;
channel = new ChannelLWJGLOpenAL(type, ALSource);
return channel;
}
/**
* Stops all sources, shuts down OpenAL, and removes references to all
* instantiated objects.
*/
@Override
public void cleanup() {
super.cleanup();
Set<String> keys = bufferMap.keySet();
Iterator<String> iter = keys.iterator();
String filename;
IntBuffer buffer;
// loop through and clear all sound buffers:
while (iter.hasNext()) {
filename = iter.next();
buffer = ALBufferMap.get(filename);
if (buffer != null) {
AL10.alDeleteBuffers(buffer);
checkALError();
buffer.clear();
}
}
bufferMap.clear();
ALC11.alcMakeContextCurrent(0l);
ALC11.alcDestroyContext(openALContext);
ALC11.alcCloseDevice(openALDevice);
ALC.destroy();
bufferMap = null;
listenerPositionAL = null;
listenerOrientation = null;
listenerVelocity = null;
}
/**
* Pre-loads a sound into memory.
*
* @param filenameURL Filename/URL of the sound file to load.
* @return True if the sound loaded properly.
*/
@Override
public boolean loadSound(FilenameURL filenameURL) {
// Make sure the buffer map exists:
if (bufferMap == null) {
bufferMap = new HashMap<String, SoundBuffer>();
importantMessage("Buffer Map was null in method 'loadSound'");
}
// Make sure the OpenAL buffer map exists:
if (ALBufferMap == null) {
ALBufferMap = new HashMap<String, IntBuffer>();
importantMessage("Open AL Buffer Map was null in method" + "'loadSound'");
}
// make sure they gave us a filename:
if (errorCheck(filenameURL == null, "Filename/URL not specified in method 'loadSound'"))
return false;
// check if it is already loaded:
if (bufferMap.get(filenameURL.getFilename()) != null)
return true;
ICodec codec = SoundSystemConfig.getCodec(filenameURL.getFilename());
if (errorCheck(codec == null,
"No codec found for file '" + filenameURL.getFilename() + "' in method 'loadSound'"))
return false;
codec.reverseByteOrder(true);
URL url = filenameURL.getURL();
if (errorCheck(url == null, "Unable to open file '" + filenameURL.getFilename() + "' in method 'loadSound'"))
return false;
codec.initialize(url);
SoundBuffer buffer = codec.readAll();
codec.cleanup();
codec = null;
if (errorCheck(buffer == null, "Sound buffer null in method 'loadSound'"))
return false;
bufferMap.put(filenameURL.getFilename(), buffer);
AudioFormat audioFormat = buffer.audioFormat;
int soundFormat = 0;
if (audioFormat.getChannels() == 1) {
if (audioFormat.getSampleSizeInBits() == 8) {
soundFormat = AL10.AL_FORMAT_MONO8;
} else if (audioFormat.getSampleSizeInBits() == 16) {
soundFormat = AL10.AL_FORMAT_MONO16;
} else {
errorMessage("Illegal sample size in method 'loadSound'");
return false;
}
} else if (audioFormat.getChannels() == 2) {
if (audioFormat.getSampleSizeInBits() == 8) {
soundFormat = AL10.AL_FORMAT_STEREO8;
} else if (audioFormat.getSampleSizeInBits() == 16) {
soundFormat = AL10.AL_FORMAT_STEREO16;
} else {
errorMessage("Illegal sample size in method 'loadSound'");
return false;
}
} else {
errorMessage("File neither mono nor stereo in method " + "'loadSound'");
return false;
}
IntBuffer intBuffer = BufferUtils.createIntBuffer(1);
AL10.alGenBuffers(intBuffer);
if (errorCheck(AL10.alGetError() != AL10.AL_NO_ERROR,
"alGenBuffers error when loading " + filenameURL.getFilename()))
return false;
// AL10.alBufferData( intBuffer.get( 0 ), soundFormat,
// ByteBuffer.wrap( buffer.audioData ),
// (int) audioFormat.getSampleRate() );
AL10.alBufferData(intBuffer.get(0), soundFormat,
(ByteBuffer) BufferUtils.createByteBuffer(buffer.audioData.length).put(buffer.audioData).flip(),
(int) audioFormat.getSampleRate());
if (errorCheck(AL10.alGetError() != AL10.AL_NO_ERROR,
"alBufferData error when loading " + filenameURL.getFilename()))
if (errorCheck(intBuffer == null, "Sound buffer was not created for " + filenameURL.getFilename()))
return false;
ALBufferMap.put(filenameURL.getFilename(), intBuffer);
return true;
}
/**
* Saves the specified sample data, under the specified identifier. This
* identifier can be later used in place of 'filename' parameters to reference
* the sample data.
*
* @param buffer the sample data and audio format to save.
* @param identifier What to call the sample.
* @return True if there weren't any problems.
*/
@Override
public boolean loadSound(SoundBuffer buffer, String identifier) {
// Make sure the buffer map exists:
if (bufferMap == null) {
bufferMap = new HashMap<String, SoundBuffer>();
importantMessage("Buffer Map was null in method 'loadSound'");
}
// Make sure the OpenAL buffer map exists:
if (ALBufferMap == null) {
ALBufferMap = new HashMap<String, IntBuffer>();
importantMessage("Open AL Buffer Map was null in method" + "'loadSound'");
}
// make sure they gave us an identifier:
if (errorCheck(identifier == null, "Identifier not specified in method 'loadSound'"))
return false;
// check if it is already loaded:
if (bufferMap.get(identifier) != null)
return true;
if (errorCheck(buffer == null, "Sound buffer null in method 'loadSound'"))
return false;
bufferMap.put(identifier, buffer);
AudioFormat audioFormat = buffer.audioFormat;
int soundFormat = 0;
if (audioFormat.getChannels() == 1) {
if (audioFormat.getSampleSizeInBits() == 8) {
soundFormat = AL10.AL_FORMAT_MONO8;
} else if (audioFormat.getSampleSizeInBits() == 16) {
soundFormat = AL10.AL_FORMAT_MONO16;
} else {
errorMessage("Illegal sample size in method 'loadSound'");
return false;
}
} else if (audioFormat.getChannels() == 2) {
if (audioFormat.getSampleSizeInBits() == 8) {
soundFormat = AL10.AL_FORMAT_STEREO8;
} else if (audioFormat.getSampleSizeInBits() == 16) {
soundFormat = AL10.AL_FORMAT_STEREO16;
} else {
errorMessage("Illegal sample size in method 'loadSound'");
return false;
}
} else {
errorMessage("File neither mono nor stereo in method " + "'loadSound'");
return false;
}
IntBuffer intBuffer = BufferUtils.createIntBuffer(1);
AL10.alGenBuffers(intBuffer);
if (errorCheck(AL10.alGetError() != AL10.AL_NO_ERROR, "alGenBuffers error when saving " + identifier))
return false;
// AL10.alBufferData( intBuffer.get( 0 ), soundFormat,
// ByteBuffer.wrap( buffer.audioData ),
// (int) audioFormat.getSampleRate() );
AL10.alBufferData(intBuffer.get(0), soundFormat,
(ByteBuffer) BufferUtils.createByteBuffer(buffer.audioData.length).put(buffer.audioData).flip(),
(int) audioFormat.getSampleRate());
if (errorCheck(AL10.alGetError() != AL10.AL_NO_ERROR, "alBufferData error when saving " + identifier))
if (errorCheck(intBuffer == null, "Sound buffer was not created for " + identifier))
return false;
ALBufferMap.put(identifier, intBuffer);
return true;
}
/**
* Removes a pre-loaded sound from memory. This is a good method to use for
* freeing up memory after a large sound file is no longer needed. NOTE: the
* source will remain in memory after this method has been called, for as long
* as the sound is attached to an existing source.
*
* @param filename Filename/identifier of the sound file to unload.
*/
@Override
public void unloadSound(String filename) {
ALBufferMap.remove(filename);
super.unloadSound(filename);
}
/**
* Sets the overall volume to the specified value, affecting all sources.
*
* @param value New volume, float value ( 0.0f - 1.0f ).
*/
@Override
public void setMasterVolume(float value) {
super.setMasterVolume(value);
AL10.alListenerf(AL10.AL_GAIN, value);
checkALError();
}
/**
* Creates a new source and places it into the source map.
*
* @param priority Setting this to true will prevent other sounds from
* overriding this one.
* @param toStream Setting this to true will load the sound in pieces rather
* than all at once.
* @param toLoop Should this source loop, or play only once.
* @param sourcename A unique identifier for this source. Two sources may not
* use the same sourcename.
* @param filenameURL Filename/URL of the sound file to play at this source.
* @param x X position for this source.
* @param y Y position for this source.
* @param z Z position for this source.
* @param attModel Attenuation model to use.
* @param distOrRoll Either the fading distance or rolloff factor, depending on
* the value of "attmodel".
*/
@Override
public void newSource(boolean priority, boolean toStream, boolean toLoop, String sourcename,
FilenameURL filenameURL, float x, float y, float z, int attModel, float distOrRoll) {
IntBuffer myBuffer = null;
if (!toStream) {
// Grab the sound buffer for this file:
myBuffer = ALBufferMap.get(filenameURL.getFilename());
// if not found, try loading it:
if (myBuffer == null) {
if (!loadSound(filenameURL)) {
errorMessage("Source '" + sourcename + "' was not created "
+ "because an error occurred while loading " + filenameURL.getFilename());
return;
}
}
// try and grab the sound buffer again:
myBuffer = ALBufferMap.get(filenameURL.getFilename());
// see if it was there this time:
if (myBuffer == null) {
errorMessage("Source '" + sourcename + "' was not created "
+ "because a sound buffer was not found for " + filenameURL.getFilename());
return;
}
}
SoundBuffer buffer = null;
if (!toStream) {
// Grab the audio data for this file:
buffer = bufferMap.get(filenameURL.getFilename());
// if not found, try loading it:
if (buffer == null) {
if (!loadSound(filenameURL)) {
errorMessage("Source '" + sourcename + "' was not created "
+ "because an error occurred while loading " + filenameURL.getFilename());
return;
}
}
// try and grab the sound buffer again:
buffer = bufferMap.get(filenameURL.getFilename());
// see if it was there this time:
if (buffer == null) {
errorMessage("Source '" + sourcename + "' was not created " + "because audio data was not found for "
+ filenameURL.getFilename());
return;
}
}
sourceMap.put(sourcename, new SourceLWJGLOpenAL(listenerPositionAL, myBuffer, priority, toStream, toLoop,
sourcename, filenameURL, buffer, x, y, z, attModel, distOrRoll, false));
}
/**
* Opens a direct line for streaming audio data.
*
* @param audioFormat Format that the data will be in.
* @param priority Setting this to true will prevent other sounds from
* overriding this one.
* @param sourcename A unique identifier for this source. Two sources may not
* use the same sourcename.
* @param x X position for this source.
* @param y Y position for this source.
* @param z Z position for this source.
* @param attModel Attenuation model to use.
* @param distOrRoll Either the fading distance or rolloff factor, depending on
* the value of "attmodel".
*/
@Override
public void rawDataStream(AudioFormat audioFormat, boolean priority, String sourcename, float x, float y, float z,
int attModel, float distOrRoll) {
sourceMap.put(sourcename, new SourceLWJGLOpenAL(listenerPositionAL, audioFormat, priority, sourcename, x, y, z,
attModel, distOrRoll));
}
/**
* Creates and immediately plays a new source.
*
* @param priority Setting this to true will prevent other sounds from
* overriding this one.
* @param toStream Setting this to true will load the sound in pieces rather
* than all at once.
* @param toLoop Should this source loop, or play only once.
* @param sourcename A unique identifier for this source. Two sources may not
* use the same sourcename.
* @param filenameURL Filename/URL of the sound file to play at this source.
* @param x X position for this source.
* @param y Y position for this source.
* @param z Z position for this source.
* @param attModel Attenuation model to use.
* @param distOrRoll Either the fading distance or rolloff factor, depending on
* the value of "attmodel".
* @param temporary Whether or not this source should be removed after it
* finishes playing.
*/
@Override
public void quickPlay(boolean priority, boolean toStream, boolean toLoop, String sourcename,
FilenameURL filenameURL, float x, float y, float z, int attModel, float distOrRoll, boolean temporary) {
IntBuffer myBuffer = null;
if (!toStream) {
// Grab the sound buffer for this file:
myBuffer = ALBufferMap.get(filenameURL.getFilename());
// if not found, try loading it:
if (myBuffer == null)
loadSound(filenameURL);
// try and grab the sound buffer again:
myBuffer = ALBufferMap.get(filenameURL.getFilename());
// see if it was there this time:
if (myBuffer == null) {
errorMessage("Sound buffer was not created for " + filenameURL.getFilename());
return;
}
}
SoundBuffer buffer = null;
if (!toStream) {
// Grab the sound buffer for this file:
buffer = bufferMap.get(filenameURL.getFilename());
// if not found, try loading it:
if (buffer == null) {
if (!loadSound(filenameURL)) {
errorMessage("Source '" + sourcename + "' was not created "
+ "because an error occurred while loading " + filenameURL.getFilename());
return;
}
}
// try and grab the sound buffer again:
buffer = bufferMap.get(filenameURL.getFilename());
// see if it was there this time:
if (buffer == null) {
errorMessage("Source '" + sourcename + "' was not created " + "because audio data was not found for "
+ filenameURL.getFilename());
return;
}
}
SourceLWJGLOpenAL s = new SourceLWJGLOpenAL(listenerPositionAL, myBuffer, priority, toStream, toLoop,
sourcename, filenameURL, buffer, x, y, z, attModel, distOrRoll, false);
sourceMap.put(sourcename, s);
play(s);
if (temporary)
s.setTemporary(true);
}
/**
* Creates sources based on the source map provided.
*
* @param srcMap Sources to copy.
*/
@Override
public void copySources(HashMap<String, Source> srcMap) {
if (srcMap == null)
return;
Set<String> keys = srcMap.keySet();
Iterator<String> iter = keys.iterator();
String sourcename;
Source source;
// Make sure the buffer map exists:
if (bufferMap == null) {
bufferMap = new HashMap<String, SoundBuffer>();
importantMessage("Buffer Map was null in method 'copySources'");
}
// Make sure the OpenAL buffer map exists:
if (ALBufferMap == null) {
ALBufferMap = new HashMap<String, IntBuffer>();
importantMessage("Open AL Buffer Map was null in method" + "'copySources'");
}
// remove any existing sources before starting:
sourceMap.clear();
SoundBuffer buffer;
// loop through and copy all the sources:
while (iter.hasNext()) {
sourcename = iter.next();
source = srcMap.get(sourcename);
if (source != null) {
buffer = null;
if (!source.toStream) {
loadSound(source.filenameURL);
buffer = bufferMap.get(source.filenameURL.getFilename());
}
if (source.toStream || buffer != null)
sourceMap.put(sourcename, new SourceLWJGLOpenAL(listenerPositionAL,
ALBufferMap.get(source.filenameURL.getFilename()), source, buffer));
}
}
}
/**
* Changes the listener's position.
*
* @param x Destination X coordinate.
* @param y Destination Y coordinate.
* @param z Destination Z coordinate.
*/
@Override
public void setListenerPosition(float x, float y, float z) {
super.setListenerPosition(x, y, z);
listenerPositionAL.put(0, x);
listenerPositionAL.put(1, y);
listenerPositionAL.put(2, z);
// Update OpenAL listener position:
AL10.alListenerfv(AL10.AL_POSITION, listenerPositionAL);
// Check for errors:
checkALError();
}
/**
* Changes the listeners orientation to the specified 'angle' radians
* counterclockwise around the y-Axis.
*
* @param angle Radians.
*/
@Override
public void setListenerAngle(float angle) {
super.setListenerAngle(angle);
listenerOrientation.put(0, listener.lookAt.x);
listenerOrientation.put(2, listener.lookAt.z);
// Update OpenAL listener orientation:
AL10.alListenerfv(AL10.AL_ORIENTATION, listenerOrientation);
// Check for errors:
checkALError();
}
/**
* Changes the listeners orientation using the specified coordinates.
*
* @param lookX X element of the look-at direction.
* @param lookY Y element of the look-at direction.
* @param lookZ Z element of the look-at direction.
* @param upX X element of the up direction.
* @param upY Y element of the up direction.
* @param upZ Z element of the up direction.
*/
@Override
public void setListenerOrientation(float lookX, float lookY, float lookZ, float upX, float upY, float upZ) {
super.setListenerOrientation(lookX, lookY, lookZ, upX, upY, upZ);
listenerOrientation.put(0, lookX);
listenerOrientation.put(1, lookY);
listenerOrientation.put(2, lookZ);
listenerOrientation.put(3, upX);
listenerOrientation.put(4, upY);
listenerOrientation.put(5, upZ);
AL10.alListenerfv(AL10.AL_ORIENTATION, listenerOrientation);
checkALError();
}
/**
* Changes the listeners position and orientation using the specified listener
* data.
*
* @param l Listener data to use.
*/
@Override
public void setListenerData(ListenerData l) {
super.setListenerData(l);
listenerPositionAL.put(0, l.position.x);
listenerPositionAL.put(1, l.position.y);
listenerPositionAL.put(2, l.position.z);
AL10.alListenerfv(AL10.AL_POSITION, listenerPositionAL);
checkALError();
listenerOrientation.put(0, l.lookAt.x);
listenerOrientation.put(1, l.lookAt.y);
listenerOrientation.put(2, l.lookAt.z);
listenerOrientation.put(3, l.up.x);
listenerOrientation.put(4, l.up.y);
listenerOrientation.put(5, l.up.z);
AL10.alListenerfv(AL10.AL_ORIENTATION, listenerOrientation);
checkALError();
listenerVelocity.put(0, l.velocity.x);
listenerVelocity.put(1, l.velocity.y);
listenerVelocity.put(2, l.velocity.z);
AL10.alListenerfv(AL10.AL_VELOCITY, listenerVelocity);
checkALError();
}
/**
* Sets the listener's velocity, for use in Doppler effect.
*
* @param x Velocity along world x-axis.
* @param y Velocity along world y-axis.
* @param z Velocity along world z-axis.
*/
@Override
public void setListenerVelocity(float x, float y, float z) {
super.setListenerVelocity(x, y, z);
listenerVelocity.put(0, listener.velocity.x);
listenerVelocity.put(1, listener.velocity.y);
listenerVelocity.put(2, listener.velocity.z);
AL10.alListenerfv(AL10.AL_VELOCITY, listenerVelocity);
}
/**
* The Doppler parameters have changed.
*/
@Override
public void dopplerChanged() {
super.dopplerChanged();
AL10.alDopplerFactor(SoundSystemConfig.getDopplerFactor());
checkALError();
AL10.alDopplerVelocity(SoundSystemConfig.getDopplerVelocity());
checkALError();
}
/**
* Checks for OpenAL errors, and prints a message if there is an error.
*
* @return True if there was an error, False if not.
*/
private boolean checkALError() {
switch (AL10.alGetError()) {
case AL10.AL_NO_ERROR:
return false;
case AL10.AL_INVALID_NAME:
errorMessage("Invalid name parameter.");
return true;
case AL10.AL_INVALID_ENUM:
errorMessage("Invalid parameter.");
return true;
case AL10.AL_INVALID_VALUE:
errorMessage("Invalid enumerated parameter value.");
return true;
case AL10.AL_INVALID_OPERATION:
errorMessage("Illegal call.");
return true;
case AL10.AL_OUT_OF_MEMORY:
errorMessage("Unable to allocate memory.");
return true;
default:
errorMessage("An unrecognized error occurred.");
return true;
}
}
/**
* Whether or not the AL_PITCH control is supported.
*
* @return True if AL_PITCH is supported.
*/
public static boolean alPitchSupported() {
return alPitchSupported(GET, XXX);
}
/**
* Sets or returns the value of boolean 'alPitchSupported'.
*
* @param action Action to perform (GET or SET).
* @param value New value if action is SET, otherwise XXX.
* @return value of boolean 'alPitchSupported'.
*/
private static synchronized boolean alPitchSupported(boolean action, boolean value) {
if (action == SET)
alPitchSupported = value;
return alPitchSupported;
}
/**
* Returns the short title of this library type.
*
* @return A short title.
*/
public static String getTitle() {
return "LWJGL OpenAL (Eaglercraft)";
}
/**
* Returns a longer description of this library type.
*
* @return A longer description.
*/
public static String getDescription() {
return "The Eaglercraft LWJGL3 binding of OpenAL";
}
/**
* Returns the name of the class.
*
* @return "Library" + library title.
*/
@Override
public String getClassName() {
return "LibraryLWJGLOpenAL";
}
/**
* The LibraryLWJGLOpenAL.Exception class provides library-specific error
* information.
*/
public static class Exception extends SoundSystemException {
private static final long serialVersionUID = -7502452059037798035L;
/**
* Global identifier for an exception during AL.create(). Probably means that
* OpenAL is not supported.
*/
public static final int CREATE = 101;
/**
* Global identifier for an invalid name parameter in OpenAL.
*/
public static final int INVALID_NAME = 102;
/**
* Global identifier for an invalid parameter in OpenAL.
*/
public static final int INVALID_ENUM = 103;
/**
* Global identifier for an invalid enumerated parameter value in OpenAL.
*/
public static final int INVALID_VALUE = 104;
/**
* Global identifier for an illegal call in OpenAL.
*/
public static final int INVALID_OPERATION = 105;
/**
* Global identifier for OpenAL out of memory.
*/
public static final int OUT_OF_MEMORY = 106;
/**
* Global identifier for an exception while creating the OpenAL Listener.
*/
public static final int LISTENER = 107;
/**
* Global identifier for OpenAL AL_PITCH not supported.
*/
public static final int NO_AL_PITCH = 108;
/**
* Constructor: Generates a standard "unknown error" exception with the
* specified message.
*
* @param message A brief description of the problem that occurred.
*/
public Exception(String message) {
super(message);
}
/**
* Constructor: Generates an exception of the specified type, with the specified
* message.
*
* @param message A brief description of the problem that occurred.
* @param type Identifier indicating they type of error.
*/
public Exception(String message, int type) {
super(message, type);
}
}
}

View File

@ -0,0 +1,703 @@
package net.lax1dude.eaglercraft.v1_8.internal.paulscode.lwjgl3;
import java.nio.IntBuffer;
import java.nio.FloatBuffer;
import java.util.LinkedList;
import javax.sound.sampled.AudioFormat;
// From the lwjgl library, http://www.lwjgl.org
import org.lwjgl.BufferUtils;
import org.lwjgl.openal.AL10;
import paulscode.sound.Channel;
import paulscode.sound.FilenameURL;
import paulscode.sound.Source;
import paulscode.sound.SoundBuffer;
import paulscode.sound.SoundSystemConfig;
/**
* The SourceLWJGLOpenAL class provides an interface to the lwjgl binding of
* OpenAL. <b><br>
* <br>
* This software is based on or using the LWJGL Lightweight Java Gaming Library
* available from http://www.lwjgl.org/. </b><br>
* <br>
* LWJGL License: <br>
* <i> Copyright (c) 2002-2008 Lightweight Java Game Library Project All rights
* reserved. <br>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* <br>
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer. <br>
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. <br>
* * Neither the name of 'Light Weight Java Game Library' nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission. <br>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. <br>
* <br>
* <br>
* </i> <b><i> SoundSystem LibraryLWJGLOpenAL License:</b></i><br>
* <b><br>
* <b> You are free to use this library for any purpose, commercial or
* otherwise. You may modify this library or source code, and distribute it any
* way you like, provided the following conditions are met: <br>
* 1) You must abide by the conditions of the aforementioned LWJGL License. <br>
* 2) You may not falsely claim to be the author of this library or any
* unmodified portion of it. <br>
* 3) You may not copyright this library or a modified version of it and then
* sue me for copyright infringement. <br>
* 4) If you modify the source code, you must clearly document the changes made
* before redistributing the modified source code, so other users know it is not
* the original code. <br>
* 5) You are not required to give me credit for this library in any derived
* work, but if you do, you must also mention my website:
* http://www.paulscode.com <br>
* 6) I the author will not be responsible for any damages (physical, financial,
* or otherwise) caused by the use if this library or any part of it. <br>
* 7) I the author do not guarantee, warrant, or make any representations,
* either expressed or implied, regarding the use of this library or any part of
* it. <br>
* <br>
* Author: Paul Lamb <br>
* http://www.paulscode.com </b>
*/
public class SourceLWJGLOpenAL extends Source {
/**
* The source's basic Channel type-cast to a ChannelLWJGLOpenAL.
*/
private ChannelLWJGLOpenAL channelOpenAL = (ChannelLWJGLOpenAL) channel;
/**
* OpenAL IntBuffer sound-buffer identifier for this source if it is a normal
* source.
*/
private IntBuffer myBuffer;
/**
* FloatBuffer containing the listener's 3D coordinates.
*/
private FloatBuffer listenerPosition;
/**
* FloatBuffer containing the source's 3D coordinates.
*/
private FloatBuffer sourcePosition;
/**
* FloatBuffer containing the source's velocity vector.
*/
private FloatBuffer sourceVelocity;
/**
* Constructor: Creates a new source using the specified parameters.
*
* @param listenerPosition FloatBuffer containing the listener's 3D coordinates.
* @param myBuffer OpenAL IntBuffer sound-buffer identifier to use for a
* new normal source.
* @param priority Setting this to true will prevent other sounds from
* overriding this one.
* @param toStream Setting this to true will create a streaming source.
* @param toLoop Should this source loop, or play only once.
* @param sourcename A unique identifier for this source. Two sources may
* not use the same sourcename.
* @param filenameURL Filename/URL of the sound file to play at this
* source.
* @param soundBuffer Buffer containing audio data, or null if not loaded
* yet.
* @param x X position for this source.
* @param y Y position for this source.
* @param z Z position for this source.
* @param attModel Attenuation model to use.
* @param distOrRoll Either the fading distance or rolloff factor,
* depending on the value of 'att'.
* @param temporary Whether or not to remove this source after it
* finishes playing.
*/
public SourceLWJGLOpenAL(FloatBuffer listenerPosition, IntBuffer myBuffer, boolean priority, boolean toStream,
boolean toLoop, String sourcename, FilenameURL filenameURL, SoundBuffer soundBuffer, float x, float y,
float z, int attModel, float distOrRoll, boolean temporary) {
super(priority, toStream, toLoop, sourcename, filenameURL, soundBuffer, x, y, z, attModel, distOrRoll,
temporary);
if (codec != null)
codec.reverseByteOrder(true);
this.listenerPosition = listenerPosition;
this.myBuffer = myBuffer;
libraryType = LibraryLWJGLOpenAL.class;
pitch = 1.0f;
resetALInformation();
}
/**
* Constructor: Creates a new source matching the specified source.
*
* @param listenerPosition FloatBuffer containing the listener's 3D coordinates.
* @param myBuffer OpenAL IntBuffer sound-buffer identifier to use for a
* new normal source.
* @param old Source to copy information from.
* @param soundBuffer Buffer containing audio data, or null if not loaded
* yet.
*/
public SourceLWJGLOpenAL(FloatBuffer listenerPosition, IntBuffer myBuffer, Source old, SoundBuffer soundBuffer) {
super(old, soundBuffer);
if (codec != null)
codec.reverseByteOrder(true);
this.listenerPosition = listenerPosition;
this.myBuffer = myBuffer;
libraryType = LibraryLWJGLOpenAL.class;
pitch = 1.0f;
resetALInformation();
}
/**
* Constructor: Creates a new streaming source that will be directly fed with
* raw audio data.
*
* @param listenerPosition FloatBuffer containing the listener's 3D coordinates.
* @param audioFormat Format that the data will be in.
* @param priority Setting this to true will prevent other sounds from
* overriding this one.
* @param sourcename A unique identifier for this source. Two sources may
* not use the same sourcename.
* @param x X position for this source.
* @param y Y position for this source.
* @param z Z position for this source.
* @param attModel Attenuation model to use.
* @param distOrRoll Either the fading distance or rolloff factor,
* depending on the value of 'att'.
*/
public SourceLWJGLOpenAL(FloatBuffer listenerPosition, AudioFormat audioFormat, boolean priority, String sourcename,
float x, float y, float z, int attModel, float distOrRoll) {
super(audioFormat, priority, sourcename, x, y, z, attModel, distOrRoll);
this.listenerPosition = listenerPosition;
libraryType = LibraryLWJGLOpenAL.class;
pitch = 1.0f;
resetALInformation();
}
/**
* Shuts the source down and removes references to all instantiated objects.
*/
@Override
public void cleanup() {
super.cleanup();
}
/**
* Changes the peripheral information about the source using the specified
* parameters.
*
* @param listenerPosition FloatBuffer containing the listener's 3D coordinates.
* @param myBuffer OpenAL IntBuffer sound-buffer identifier to use for a
* new normal source.
* @param priority Setting this to true will prevent other sounds from
* overriding this one.
* @param toStream Setting this to true will create a streaming source.
* @param toLoop Should this source loop, or play only once.
* @param sourcename A unique identifier for this source. Two sources may
* not use the same sourcename.
* @param filenameURL Filename/URL of the sound file to play at this
* source.
* @param soundBuffer Buffer containing audio data, or null if not loaded
* yet.
* @param x X position for this source.
* @param y Y position for this source.
* @param z Z position for this source.
* @param attModel Attenuation model to use.
* @param distOrRoll Either the fading distance or rolloff factor,
* depending on the value of 'att'.
* @param temporary Whether or not to remove this source after it
* finishes playing.
*/
public void changeSource(FloatBuffer listenerPosition, IntBuffer myBuffer, boolean priority, boolean toStream,
boolean toLoop, String sourcename, FilenameURL filenameURL, SoundBuffer soundBuffer, float x, float y,
float z, int attModel, float distOrRoll, boolean temporary) {
super.changeSource(priority, toStream, toLoop, sourcename, filenameURL, soundBuffer, x, y, z, attModel,
distOrRoll, temporary);
this.listenerPosition = listenerPosition;
this.myBuffer = myBuffer;
pitch = 1.0f;
resetALInformation();
}
/**
* Removes the next filename from the sound sequence queue and assigns it to
* this source. This method has no effect on non-streaming sources. This method
* is used internally by SoundSystem, and it is unlikely that the user will ever
* need to use it.
*
* @return True if there was something in the queue.
*/
@Override
public boolean incrementSoundSequence() {
if (!toStream) {
errorMessage("Method 'incrementSoundSequence' may only be used " + "for streaming sources.");
return false;
}
synchronized (soundSequenceLock) {
if (soundSequenceQueue != null && soundSequenceQueue.size() > 0) {
filenameURL = soundSequenceQueue.remove(0);
if (codec != null)
codec.cleanup();
codec = SoundSystemConfig.getCodec(filenameURL.getFilename());
if (codec != null) {
codec.reverseByteOrder(true);
if (codec.getAudioFormat() == null)
codec.initialize(filenameURL.getURL());
AudioFormat audioFormat = codec.getAudioFormat();
if (audioFormat == null) {
errorMessage("Audio Format null in method " + "'incrementSoundSequence'");
return false;
}
int soundFormat = 0;
if (audioFormat.getChannels() == 1) {
if (audioFormat.getSampleSizeInBits() == 8) {
soundFormat = AL10.AL_FORMAT_MONO8;
} else if (audioFormat.getSampleSizeInBits() == 16) {
soundFormat = AL10.AL_FORMAT_MONO16;
} else {
errorMessage("Illegal sample size in method " + "'incrementSoundSequence'");
return false;
}
} else if (audioFormat.getChannels() == 2) {
if (audioFormat.getSampleSizeInBits() == 8) {
soundFormat = AL10.AL_FORMAT_STEREO8;
} else if (audioFormat.getSampleSizeInBits() == 16) {
soundFormat = AL10.AL_FORMAT_STEREO16;
} else {
errorMessage("Illegal sample size in method " + "'incrementSoundSequence'");
return false;
}
} else {
errorMessage("Audio data neither mono nor stereo in " + "method 'incrementSoundSequence'");
return false;
}
// Let the channel know what format and sample rate to use:
channelOpenAL.setFormat(soundFormat, (int) audioFormat.getSampleRate());
preLoad = true;
}
return true;
}
}
return false;
}
/**
* Called every time the listener's position or orientation changes.
*/
@Override
public void listenerMoved() {
positionChanged();
}
/**
* Moves the source to the specified position.
*
* @param x X coordinate to move to.
* @param y Y coordinate to move to.
* @param z Z coordinate to move to.
*/
@Override
public void setPosition(float x, float y, float z) {
super.setPosition(x, y, z);
// Make sure OpenAL information has been created
if (sourcePosition == null)
resetALInformation();
else
positionChanged();
// put the new position information into the buffer:
sourcePosition.put(0, x);
sourcePosition.put(1, y);
sourcePosition.put(2, z);
// make sure we are assigned to a channel:
if (channel != null && channel.attachedSource == this && channelOpenAL != null
&& channelOpenAL.ALSource != null) {
// move the source:
AL10.alSourcefv(channelOpenAL.ALSource.get(0), AL10.AL_POSITION, sourcePosition);
checkALError();
}
}
/**
* Recalculates the distance from the listner and the gain.
*/
@Override
public void positionChanged() {
calculateDistance();
calculateGain();
if (channel != null && channel.attachedSource == this && channelOpenAL != null
&& channelOpenAL.ALSource != null) {
AL10.alSourcef(channelOpenAL.ALSource.get(0), AL10.AL_GAIN,
(gain * sourceVolume * (float) Math.abs(fadeOutGain) * fadeInGain));
checkALError();
}
checkPitch();
}
/**
* Checks the source's pitch.
*/
private void checkPitch() {
if (channel != null && channel.attachedSource == this && LibraryLWJGLOpenAL.alPitchSupported()
&& channelOpenAL != null && channelOpenAL.ALSource != null) {
AL10.alSourcef(channelOpenAL.ALSource.get(0), AL10.AL_PITCH, pitch);
checkALError();
}
}
/**
* Sets whether this source should loop or only play once.
*
* @param lp True or false.
*/
@Override
public void setLooping(boolean lp) {
super.setLooping(lp);
// make sure we are assigned to a channel:
if (channel != null && channel.attachedSource == this && channelOpenAL != null
&& channelOpenAL.ALSource != null) {
if (lp)
AL10.alSourcei(channelOpenAL.ALSource.get(0), AL10.AL_LOOPING, AL10.AL_TRUE);
else
AL10.alSourcei(channelOpenAL.ALSource.get(0), AL10.AL_LOOPING, AL10.AL_FALSE);
checkALError();
}
}
/**
* Sets this source's attenuation model.
*
* @param model Attenuation model to use.
*/
@Override
public void setAttenuation(int model) {
super.setAttenuation(model);
// make sure we are assigned to a channel:
if (channel != null && channel.attachedSource == this && channelOpenAL != null
&& channelOpenAL.ALSource != null) {
// attenuation changed, so update the rolloff factor accordingly
if (model == SoundSystemConfig.ATTENUATION_ROLLOFF)
AL10.alSourcef(channelOpenAL.ALSource.get(0), AL10.AL_ROLLOFF_FACTOR, distOrRoll);
else
AL10.alSourcef(channelOpenAL.ALSource.get(0), AL10.AL_ROLLOFF_FACTOR, 0.0f);
checkALError();
if (model == SoundSystemConfig.ATTENUATION_NONE)
AL10.alSourcei(channelOpenAL.ALSource.get(0), AL10.AL_SOURCE_RELATIVE, 1);
else
AL10.alSourcei(channelOpenAL.ALSource.get(0), AL10.AL_SOURCE_RELATIVE, 0);
checkALError();
}
}
/**
* Sets this source's fade distance or rolloff factor, depending on the
* attenuation model.
*
* @param dr New value for fade distance or rolloff factor.
*/
@Override
public void setDistOrRoll(float dr) {
super.setDistOrRoll(dr);
// make sure we are assigned to a channel:
if (channel != null && channel.attachedSource == this && channelOpenAL != null
&& channelOpenAL.ALSource != null) {
// if we are using rolloff attenuation, then dr is a rolloff factor:
if (attModel == SoundSystemConfig.ATTENUATION_ROLLOFF)
AL10.alSourcef(channelOpenAL.ALSource.get(0), AL10.AL_ROLLOFF_FACTOR, dr);
else
AL10.alSourcef(channelOpenAL.ALSource.get(0), AL10.AL_ROLLOFF_FACTOR, 0.0f);
checkALError();
}
}
/**
* Sets this source's velocity, for use in Doppler effect.
*
* @param x Velocity along world x-axis.
* @param y Velocity along world y-axis.
* @param z Velocity along world z-axis.
*/
@Override
public void setVelocity(float x, float y, float z) {
super.setVelocity(x, y, z);
sourceVelocity = BufferUtils.createFloatBuffer(3).put(new float[] { x, y, z });
sourceVelocity.flip();
// make sure we are assigned to a channel:
if (channel != null && channel.attachedSource == this && channelOpenAL != null
&& channelOpenAL.ALSource != null) {
AL10.alSourcefv(channelOpenAL.ALSource.get(0), AL10.AL_VELOCITY, sourceVelocity);
checkALError();
}
}
/**
* Manually sets this source's pitch.
*
* @param value A float value ( 0.5f - 2.0f ).
*/
@Override
public void setPitch(float value) {
super.setPitch(value);
checkPitch();
}
/**
* Plays the source on the specified channel.
*
* @param c Channel to play on.
*/
@Override
public void play(Channel c) {
if (!active()) {
if (toLoop)
toPlay = true;
return;
}
if (c == null) {
errorMessage("Unable to play source, because channel was null");
return;
}
boolean newChannel = (channel != c);
if (channel != null && channel.attachedSource != this)
newChannel = true;
boolean wasPaused = paused();
super.play(c);
channelOpenAL = (ChannelLWJGLOpenAL) channel;
// Make sure the channel exists:
// check if we are already on this channel:
if (newChannel) {
setPosition(position.x, position.y, position.z);
checkPitch();
// Send the source's attributes to the channel:
if (channelOpenAL != null && channelOpenAL.ALSource != null) {
if (LibraryLWJGLOpenAL.alPitchSupported()) {
AL10.alSourcef(channelOpenAL.ALSource.get(0), AL10.AL_PITCH, pitch);
checkALError();
}
AL10.alSourcefv(channelOpenAL.ALSource.get(0), AL10.AL_POSITION, sourcePosition);
checkALError();
AL10.alSourcefv(channelOpenAL.ALSource.get(0), AL10.AL_VELOCITY, sourceVelocity);
checkALError();
if (attModel == SoundSystemConfig.ATTENUATION_ROLLOFF)
AL10.alSourcef(channelOpenAL.ALSource.get(0), AL10.AL_ROLLOFF_FACTOR, distOrRoll);
else
AL10.alSourcef(channelOpenAL.ALSource.get(0), AL10.AL_ROLLOFF_FACTOR, 0.0f);
checkALError();
if (attModel == SoundSystemConfig.ATTENUATION_NONE)
AL10.alSourcei(channelOpenAL.ALSource.get(0), AL10.AL_SOURCE_RELATIVE, 1);
else
AL10.alSourcei(channelOpenAL.ALSource.get(0), AL10.AL_SOURCE_RELATIVE, 0);
checkALError();
if (toLoop && (!toStream))
AL10.alSourcei(channelOpenAL.ALSource.get(0), AL10.AL_LOOPING, AL10.AL_TRUE);
else
AL10.alSourcei(channelOpenAL.ALSource.get(0), AL10.AL_LOOPING, AL10.AL_FALSE);
checkALError();
}
if (!toStream) {
// This is not a streaming source, so make sure there is
// a sound buffer loaded to play:
if (myBuffer == null) {
errorMessage("No sound buffer to play");
return;
}
channelOpenAL.attachBuffer(myBuffer);
}
}
// See if we are already playing:
if (!playing()) {
if (toStream && !wasPaused) {
if (codec == null) {
errorMessage("Decoder null in method 'play'");
return;
}
if (codec.getAudioFormat() == null)
codec.initialize(filenameURL.getURL());
AudioFormat audioFormat = codec.getAudioFormat();
if (audioFormat == null) {
errorMessage("Audio Format null in method 'play'");
return;
}
int soundFormat = 0;
if (audioFormat.getChannels() == 1) {
if (audioFormat.getSampleSizeInBits() == 8) {
soundFormat = AL10.AL_FORMAT_MONO8;
} else if (audioFormat.getSampleSizeInBits() == 16) {
soundFormat = AL10.AL_FORMAT_MONO16;
} else {
errorMessage("Illegal sample size in method 'play'");
return;
}
} else if (audioFormat.getChannels() == 2) {
if (audioFormat.getSampleSizeInBits() == 8) {
soundFormat = AL10.AL_FORMAT_STEREO8;
} else if (audioFormat.getSampleSizeInBits() == 16) {
soundFormat = AL10.AL_FORMAT_STEREO16;
} else {
errorMessage("Illegal sample size in method 'play'");
return;
}
} else {
errorMessage("Audio data neither mono nor stereo in " + "method 'play'");
return;
}
// Let the channel know what format and sample rate to use:
channelOpenAL.setFormat(soundFormat, (int) audioFormat.getSampleRate());
preLoad = true;
}
channel.play();
if (pitch != 1.0f)
checkPitch();
}
}
/**
* Queues up the initial stream-buffers for the stream.
*
* @return False if the end of the stream was reached.
*/
@Override
public boolean preLoad() {
if (codec == null)
return false;
codec.initialize(filenameURL.getURL());
LinkedList<byte[]> preLoadBuffers = new LinkedList<byte[]>();
for (int i = 0; i < SoundSystemConfig.getNumberStreamingBuffers(); i++) {
soundBuffer = codec.read();
if (soundBuffer == null || soundBuffer.audioData == null)
break;
preLoadBuffers.add(soundBuffer.audioData);
}
positionChanged();
channel.preLoadBuffers(preLoadBuffers);
preLoad = false;
return true;
}
/**
* Resets all the information OpenAL uses to play this source.
*/
private void resetALInformation() {
// Create buffers for the source's position and velocity
sourcePosition = BufferUtils.createFloatBuffer(3).put(new float[] { position.x, position.y, position.z });
sourceVelocity = BufferUtils.createFloatBuffer(3).put(new float[] { velocity.x, velocity.y, velocity.z });
// flip the buffers, so they can be used:
sourcePosition.flip();
sourceVelocity.flip();
positionChanged();
}
/**
* Calculates this source's distance from the listener.
*/
private void calculateDistance() {
if (listenerPosition != null) {
// Calculate the source's distance from the listener:
double dX = position.x - listenerPosition.get(0);
double dY = position.y - listenerPosition.get(1);
double dZ = position.z - listenerPosition.get(2);
distanceFromListener = (float) Math.sqrt(dX * dX + dY * dY + dZ * dZ);
}
}
/**
* If using linear attenuation, calculates the gain for this source based on its
* distance from the listener.
*/
private void calculateGain() {
// If using linear attenuation, calculate the source's gain:
if (attModel == SoundSystemConfig.ATTENUATION_LINEAR) {
if (distanceFromListener <= 0) {
gain = 1.0f;
} else if (distanceFromListener >= distOrRoll) {
gain = 0.0f;
} else {
gain = 1.0f - (distanceFromListener / distOrRoll);
}
if (gain > 1.0f)
gain = 1.0f;
if (gain < 0.0f)
gain = 0.0f;
} else {
gain = 1.0f;
}
}
/**
* Checks for OpenAL errors, and prints a message if there is an error.
*
* @return True if there was an error, False if not.
*/
private boolean checkALError() {
switch (AL10.alGetError()) {
case AL10.AL_NO_ERROR:
return false;
case AL10.AL_INVALID_NAME:
errorMessage("Invalid name parameter.");
return true;
case AL10.AL_INVALID_ENUM:
errorMessage("Invalid parameter.");
return true;
case AL10.AL_INVALID_VALUE:
errorMessage("Invalid enumerated parameter value.");
return true;
case AL10.AL_INVALID_OPERATION:
errorMessage("Illegal call.");
return true;
case AL10.AL_OUT_OF_MEMORY:
errorMessage("Unable to allocate memory.");
return true;
default:
errorMessage("An unrecognized error occurred.");
return true;
}
}
}

View File

@ -0,0 +1,41 @@
package net.lax1dude.eaglercraft.v1_8.internal.vfs;
import com.google.common.collect.Sets;
import net.minecraft.client.resources.AbstractResourcePack;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Set;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class FolderResourcePack extends AbstractResourcePack {
public FolderResourcePack(String resourcePackFileIn, String prefix) {
super(resourcePackFileIn);
}
protected InputStream getInputStreamByName(String name) {
return new BufferedInputStream(new ByteArrayInputStream(new byte[0]));
}
protected boolean hasResourceName(String name) {
return false;
}
public Set<String> getResourceDomains() {
return Sets.<String>newHashSet();
}
}

View File

@ -0,0 +1,41 @@
package net.lax1dude.eaglercraft.v1_8.internal.vfs;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class SYS {
public static final Object VFS = null;
public static final void loadRemoteResourcePack(String url, String hash, Consumer<String> cb, Consumer<Runnable> ast, Runnable loading) {
return;
}
public static final boolean loadResourcePack(String name, InputStream data, String hash) {
return false;
}
public static final List<String> getResourcePackNames() {
return new ArrayList<>();
}
public static final void deleteResourcePack(String packName) {
//
}
}