mirror of
https://github.com/Eaglercraft-Archive/Eaglercraftx-1.8.8-src.git
synced 2025-06-27 18:38:14 -05:00
Update #0 - First Release
This commit is contained in:
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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() {
|
||||
//
|
||||
}
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal.lwjgl;
|
||||
|
||||
public class MainClass {
|
||||
|
||||
public static void main(String[] args) {
|
||||
LWJGLEntryPoint.main_(args);
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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) {
|
||||
//
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user