mirror of
https://github.com/Eaglercraft-Archive/Eaglercraftx-1.8.8-src.git
synced 2025-06-28 10:58:15 -05:00
Update #28 - Added capes, voice chat, FNAW skins, and fixes
This commit is contained in:
@ -46,8 +46,8 @@ public class PlatformAudio {
|
||||
|
||||
static final Logger logger = LogManager.getLogger("BrowserAudio");
|
||||
|
||||
private static AudioContext audioctx = null;
|
||||
private static MediaStreamAudioDestinationNode recDest = null;
|
||||
static AudioContext audioctx = null;
|
||||
static MediaStreamAudioDestinationNode recDest = null;
|
||||
private static final Map<String, BrowserAudioResource> soundCache = new HashMap();
|
||||
|
||||
private static long cacheFreeTimer = 0l;
|
||||
|
@ -21,10 +21,7 @@ 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());
|
||||
}
|
||||
newBuffer.put(flip);
|
||||
}
|
||||
|
||||
public static void put(IntBuffer intBuffer, int index, int[] data) {
|
||||
|
@ -18,7 +18,7 @@ import org.teavm.jso.indexeddb.IDBRequest;
|
||||
import org.teavm.jso.indexeddb.IDBTransaction;
|
||||
import org.teavm.jso.indexeddb.IDBVersionChangeEvent;
|
||||
import org.teavm.jso.typedarrays.ArrayBuffer;
|
||||
import org.teavm.jso.typedarrays.DataView;
|
||||
import org.teavm.jso.typedarrays.Int8Array;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.EaglerArrayBufferAllocator;
|
||||
@ -85,11 +85,11 @@ public class PlatformFilesystem {
|
||||
if(ar == null) {
|
||||
return null;
|
||||
}
|
||||
return EaglerArrayBufferAllocator.wrapByteBufferTeaVM(DataView.create(ar));
|
||||
return EaglerArrayBufferAllocator.wrapByteBufferTeaVM(Int8Array.create(ar));
|
||||
}
|
||||
|
||||
public static void eaglerWrite(String pathName, ByteBuffer data) {
|
||||
if(!AsyncHandlers.writeWholeFile(database, pathName, EaglerArrayBufferAllocator.getDataViewStupid(data).getBuffer()).bool) {
|
||||
if(!AsyncHandlers.writeWholeFile(database, pathName, EaglerArrayBufferAllocator.getDataView8Unsigned(data).getBuffer()).bool) {
|
||||
throw new RuntimeException("Failed to write " + data.remaining() + " byte file to indexeddb table: " + pathName);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,9 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils;
|
||||
|
||||
import org.teavm.interop.Async;
|
||||
import org.teavm.interop.AsyncCallback;
|
||||
import org.teavm.jso.JSBody;
|
||||
import org.teavm.jso.JSObject;
|
||||
import org.teavm.jso.browser.TimerHandler;
|
||||
@ -100,6 +103,8 @@ public class PlatformInput {
|
||||
public static boolean keyboardLockSupported = false;
|
||||
public static boolean lockKeys = false;
|
||||
|
||||
private static boolean vsync = true;
|
||||
|
||||
@JSBody(params = { }, script = "window.onbeforeunload = () => {return false;};")
|
||||
private static native void onBeforeCloseRegister();
|
||||
|
||||
@ -291,6 +296,10 @@ public class PlatformInput {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void setVSync(boolean enable) {
|
||||
vsync = enable;
|
||||
}
|
||||
|
||||
public static void update() {
|
||||
double r = win.getDevicePixelRatio();
|
||||
int w = PlatformRuntime.parent.getClientWidth();
|
||||
@ -304,9 +313,41 @@ public class PlatformInput {
|
||||
canvas.setHeight(h2);
|
||||
}
|
||||
flipBuffer();
|
||||
EagUtils.sleep(1l);
|
||||
if (PlatformRuntime.recording) {
|
||||
long t = System.currentTimeMillis();
|
||||
if(t - PlatformRuntime.lastFrame > (1000 / 30)) {
|
||||
PlatformRuntime.recFrame();
|
||||
PlatformRuntime.lastFrame = t;
|
||||
}
|
||||
}
|
||||
if(vsync) {
|
||||
asyncRequestAnimationFrame();
|
||||
}else {
|
||||
EagUtils.sleep(0l);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Async
|
||||
private static native void asyncRequestAnimationFrame();
|
||||
|
||||
private static void asyncRequestAnimationFrame(AsyncCallback<Void> cb) {
|
||||
final boolean[] hasCompleted = new boolean[1];
|
||||
final int[] timeout = new int[] { -1 };
|
||||
Window.requestAnimationFrame((d) -> {
|
||||
if(!hasCompleted[0]) {
|
||||
hasCompleted[0] = true;
|
||||
Window.clearTimeout(timeout[0]);
|
||||
cb.complete(null);
|
||||
}
|
||||
});
|
||||
timeout[0] = Window.setTimeout(() -> {
|
||||
if(!hasCompleted[0]) {
|
||||
hasCompleted[0] = true;
|
||||
cb.complete(null);
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
|
||||
static void initFramebuffer(WebGL2RenderingContext ctx, WebGLFramebuffer fbo, int sw, int sh) {
|
||||
context = ctx;
|
||||
mainFramebuffer = fbo;
|
||||
@ -590,7 +631,7 @@ public class PlatformInput {
|
||||
@JSBody(params = { }, script = "window.navigator.keyboard.unlock();")
|
||||
private static native void unlockKeys();
|
||||
|
||||
@JSBody(params = { }, script = "return 'keyboard' in window.navigator && 'lock' in window.navigator.keyboard;")
|
||||
@JSBody(params = { }, script = "return !!(window.navigator.keyboard && window.navigator.keyboard.lock);")
|
||||
private static native boolean checkKeyboardLockSupported();
|
||||
|
||||
@JSBody(params = { }, script = "document.exitFullscreen();")
|
||||
|
@ -36,12 +36,14 @@ public class PlatformOpenGL {
|
||||
static boolean hasDebugRenderInfoExt = false;
|
||||
static boolean hasFramebufferHDR16FSupport = false;
|
||||
static boolean hasFramebufferHDR32FSupport = false;
|
||||
static boolean hasLinearHDR32FSupport = false;
|
||||
|
||||
static void setCurrentContext(WebGL2RenderingContext context) {
|
||||
ctx = context;
|
||||
hasDebugRenderInfoExt = ctx.getExtension("WEBGL_debug_renderer_info") != null;
|
||||
hasFramebufferHDR16FSupport = ctx.getExtension("EXT_color_buffer_half_float") != null;
|
||||
hasFramebufferHDR32FSupport = ctx.getExtension("EXT_color_buffer_float") != null;
|
||||
hasLinearHDR32FSupport = ctx.getExtension("OES_texture_float_linear") != null;
|
||||
_wglClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
@ -191,15 +193,15 @@ public class PlatformOpenGL {
|
||||
}
|
||||
|
||||
public static final void _wglBufferData(int target, ByteBuffer data, int usage) {
|
||||
ctx.bufferData(target, data == null ? null : EaglerArrayBufferAllocator.getDataView(data), usage);
|
||||
ctx.bufferData(target, data == null ? null : EaglerArrayBufferAllocator.getDataView8(data), usage);
|
||||
}
|
||||
|
||||
public static final void _wglBufferData(int target, IntBuffer data, int usage) {
|
||||
ctx.bufferData(target, data == null ? null : EaglerArrayBufferAllocator.getDataView(data), usage);
|
||||
ctx.bufferData(target, data == null ? null : EaglerArrayBufferAllocator.getDataView32(data), usage);
|
||||
}
|
||||
|
||||
public static final void _wglBufferData(int target, FloatBuffer data, int usage) {
|
||||
ctx.bufferData(target, data == null ? null : EaglerArrayBufferAllocator.getDataView(data), usage);
|
||||
ctx.bufferData(target, data == null ? null : EaglerArrayBufferAllocator.getDataView32F(data), usage);
|
||||
}
|
||||
|
||||
public static final void _wglBufferData(int target, int size, int usage) {
|
||||
@ -207,15 +209,15 @@ public class PlatformOpenGL {
|
||||
}
|
||||
|
||||
public static final void _wglBufferSubData(int target, int offset, ByteBuffer data) {
|
||||
ctx.bufferSubData(target, offset, data == null ? null : EaglerArrayBufferAllocator.getDataView(data));
|
||||
ctx.bufferSubData(target, offset, data == null ? null : EaglerArrayBufferAllocator.getDataView8(data));
|
||||
}
|
||||
|
||||
public static final void _wglBufferSubData(int target, int offset, IntBuffer data) {
|
||||
ctx.bufferSubData(target, offset, data == null ? null : EaglerArrayBufferAllocator.getDataView(data));
|
||||
ctx.bufferSubData(target, offset, data == null ? null : EaglerArrayBufferAllocator.getDataView32(data));
|
||||
}
|
||||
|
||||
public static final void _wglBufferSubData(int target, int offset, FloatBuffer data) {
|
||||
ctx.bufferSubData(target, offset, data == null ? null : EaglerArrayBufferAllocator.getDataView(data));
|
||||
ctx.bufferSubData(target, offset, data == null ? null : EaglerArrayBufferAllocator.getDataView32F(data));
|
||||
}
|
||||
|
||||
public static final void _wglBindVertexArray(IBufferArrayGL obj) {
|
||||
@ -258,55 +260,61 @@ public class PlatformOpenGL {
|
||||
public static final void _wglTexImage3D(int target, int level, int internalFormat, int width, int height, int depth,
|
||||
int border, int format, int type, ByteBuffer data) {
|
||||
ctx.texImage3D(target, level, internalFormat, width, height, depth, border, format, type,
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data));
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataView8Unsigned(data));
|
||||
}
|
||||
|
||||
public static final void _wglTexImage2D(int target, int level, int internalFormat, int width,
|
||||
int height, int border, int format, int type, ByteBuffer data) {
|
||||
ctx.texImage2D(target, level, internalFormat, width, height, border, format, type,
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data));
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataView8Unsigned(data));
|
||||
}
|
||||
|
||||
public static final void _wglTexImage2Du16(int target, int level, int internalFormat, int width,
|
||||
int height, int border, int format, int type, ByteBuffer data) {
|
||||
ctx.texImage2D(target, level, internalFormat, width, height, border, format, type,
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid16(data));
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataView16Unsigned(data));
|
||||
}
|
||||
|
||||
public static final void _wglTexImage2Df32(int target, int level, int internalFormat, int width,
|
||||
int height, int border, int format, int type, ByteBuffer data) {
|
||||
ctx.texImage2D(target, level, internalFormat, width, height, border, format, type,
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataView32F(data));
|
||||
}
|
||||
|
||||
public static final void _wglTexImage2D(int target, int level, int internalFormat, int width,
|
||||
int height, int border, int format, int type, IntBuffer data) {
|
||||
ctx.texImage2D(target, level, internalFormat, width, height, border, format, type,
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data));
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataView8Unsigned(data));
|
||||
}
|
||||
|
||||
public static final void _wglTexImage2D(int target, int level, int internalFormat, int width,
|
||||
int height, int border, int format, int type, FloatBuffer data) {
|
||||
ctx.texImage2D(target, level, internalFormat, width, height, border, format, type,
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data));
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataView8Unsigned(data));
|
||||
}
|
||||
|
||||
public static final void _wglTexSubImage2D(int target, int level, int xoffset, int yoffset,
|
||||
int width, int height, int format, int type, ByteBuffer data) {
|
||||
ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data));
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataView8Unsigned(data));
|
||||
}
|
||||
|
||||
public static final void _wglTexSubImage2Du16(int target, int level, int xoffset, int yoffset,
|
||||
int width, int height, int format, int type, ByteBuffer data) {
|
||||
ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid16(data));
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataView16Unsigned(data));
|
||||
}
|
||||
|
||||
public static final void _wglTexSubImage2D(int target, int level, int xoffset, int yoffset,
|
||||
int width, int height, int format, int type, IntBuffer data) {
|
||||
ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data));
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataView8Unsigned(data));
|
||||
}
|
||||
|
||||
public static final void _wglTexSubImage2D(int target, int level, int xoffset, int yoffset,
|
||||
int width, int height, int format, int type, FloatBuffer data) {
|
||||
ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data));
|
||||
data == null ? null : EaglerArrayBufferAllocator.getDataView8Unsigned(data));
|
||||
}
|
||||
|
||||
public static final void _wglCopyTexSubImage2D(int target, int level, int xoffset, int yoffset,
|
||||
@ -455,32 +463,32 @@ public class PlatformOpenGL {
|
||||
|
||||
public static final void _wglUniformMatrix2fv(IUniformGL obj, boolean transpose, FloatBuffer mat) {
|
||||
if(obj != null) ctx.uniformMatrix2fv(((OpenGLObjects.UniformGL)obj).ptr, transpose,
|
||||
mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat));
|
||||
mat == null ? null : EaglerArrayBufferAllocator.getDataView32F(mat));
|
||||
}
|
||||
|
||||
public static final void _wglUniformMatrix3fv(IUniformGL obj, boolean transpose, FloatBuffer mat) {
|
||||
if(obj != null) ctx.uniformMatrix3fv(((OpenGLObjects.UniformGL)obj).ptr, transpose,
|
||||
mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat));
|
||||
mat == null ? null : EaglerArrayBufferAllocator.getDataView32F(mat));
|
||||
}
|
||||
|
||||
public static final void _wglUniformMatrix3x2fv(IUniformGL obj, boolean transpose, FloatBuffer mat) {
|
||||
if(obj != null) ctx.uniformMatrix3x2fv(((OpenGLObjects.UniformGL)obj).ptr, transpose,
|
||||
mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat));
|
||||
mat == null ? null : EaglerArrayBufferAllocator.getDataView32F(mat));
|
||||
}
|
||||
|
||||
public static final void _wglUniformMatrix4fv(IUniformGL obj, boolean transpose, FloatBuffer mat) {
|
||||
if(obj != null) ctx.uniformMatrix4fv(((OpenGLObjects.UniformGL)obj).ptr, transpose,
|
||||
mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat));
|
||||
mat == null ? null : EaglerArrayBufferAllocator.getDataView32F(mat));
|
||||
}
|
||||
|
||||
public static final void _wglUniformMatrix4x2fv(IUniformGL obj, boolean transpose, FloatBuffer mat) {
|
||||
if(obj != null) ctx.uniformMatrix4x2fv(((OpenGLObjects.UniformGL)obj).ptr, transpose,
|
||||
mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat));
|
||||
mat == null ? null : EaglerArrayBufferAllocator.getDataView32F(mat));
|
||||
}
|
||||
|
||||
public static final void _wglUniformMatrix4x3fv(IUniformGL obj, boolean transpose, FloatBuffer mat) {
|
||||
if(obj != null) ctx.uniformMatrix4x3fv(((OpenGLObjects.UniformGL)obj).ptr, transpose,
|
||||
mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat));
|
||||
mat == null ? null : EaglerArrayBufferAllocator.getDataView32F(mat));
|
||||
}
|
||||
|
||||
public static final void _wglBindFramebuffer(int target, IFramebufferGL framebuffer) {
|
||||
@ -570,7 +578,11 @@ public class PlatformOpenGL {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static final boolean checkLinearHDR32FSupport() {
|
||||
return hasLinearHDR32FSupport;
|
||||
}
|
||||
|
||||
private static final void checkErr(String name) {
|
||||
int i = ctx.getError();
|
||||
if(i != 0) {
|
||||
|
@ -28,7 +28,6 @@ import org.teavm.jso.dom.html.HTMLCanvasElement;
|
||||
import org.teavm.jso.dom.html.HTMLDocument;
|
||||
import org.teavm.jso.dom.html.HTMLElement;
|
||||
import org.teavm.jso.typedarrays.ArrayBuffer;
|
||||
import org.teavm.jso.typedarrays.DataView;
|
||||
import org.teavm.jso.typedarrays.Uint8Array;
|
||||
import org.teavm.jso.webaudio.MediaStream;
|
||||
import org.teavm.jso.webgl.WebGLFramebuffer;
|
||||
@ -275,27 +274,27 @@ public class PlatformRuntime {
|
||||
}
|
||||
|
||||
public static ByteBuffer castPrimitiveByteArray(byte[] array) {
|
||||
return EaglerArrayBufferAllocator.wrapByteBufferTeaVM(DataView.create(TeaVMUtils.unwrapArrayBuffer(array)));
|
||||
return EaglerArrayBufferAllocator.wrapByteBufferTeaVM(TeaVMUtils.unwrapByteArray(array));
|
||||
}
|
||||
|
||||
public static IntBuffer castPrimitiveIntArray(int[] array) {
|
||||
return EaglerArrayBufferAllocator.wrapIntBufferTeaVM(DataView.create(TeaVMUtils.unwrapArrayBuffer(array)));
|
||||
return EaglerArrayBufferAllocator.wrapIntBufferTeaVM(TeaVMUtils.unwrapIntArray(array));
|
||||
}
|
||||
|
||||
public static FloatBuffer castPrimitiveFloatArray(float[] array) {
|
||||
return EaglerArrayBufferAllocator.wrapFloatBufferTeaVM(DataView.create(TeaVMUtils.unwrapArrayBuffer(array)));
|
||||
return EaglerArrayBufferAllocator.wrapFloatBufferTeaVM(TeaVMUtils.unwrapFloatArray(array));
|
||||
}
|
||||
|
||||
public static byte[] castNativeByteBuffer(ByteBuffer buffer) {
|
||||
return TeaVMUtils.wrapUnsignedByteArray(EaglerArrayBufferAllocator.getDataViewStupid(buffer));
|
||||
return TeaVMUtils.wrapUnsignedByteArray(EaglerArrayBufferAllocator.getDataView8Unsigned(buffer));
|
||||
}
|
||||
|
||||
public static int[] castNativeIntBuffer(IntBuffer buffer) {
|
||||
return TeaVMUtils.wrapIntArray(EaglerArrayBufferAllocator.getDataViewStupid32(buffer));
|
||||
return TeaVMUtils.wrapIntArray(EaglerArrayBufferAllocator.getDataView32(buffer));
|
||||
}
|
||||
|
||||
public static float[] castNativeFloatBuffer(FloatBuffer buffer) {
|
||||
return TeaVMUtils.wrapFloatArray(EaglerArrayBufferAllocator.getFloatArrayStupid(buffer));
|
||||
return TeaVMUtils.wrapFloatArray(EaglerArrayBufferAllocator.getDataView32F(buffer));
|
||||
}
|
||||
|
||||
public static void freeByteBuffer(ByteBuffer byteBuffer) {
|
||||
@ -500,12 +499,13 @@ public class PlatformRuntime {
|
||||
return TeaVMClientConfigAdapter.instance;
|
||||
}
|
||||
|
||||
private static boolean canRec = false;
|
||||
private static boolean recording = false;
|
||||
private static JSObject mediaRec = null;
|
||||
private static HTMLCanvasElement recCanvas = null;
|
||||
private static CanvasRenderingContext2D recCtx = null;
|
||||
private static MediaStream recStream = null;
|
||||
static boolean canRec = false;
|
||||
static boolean recording = false;
|
||||
static long lastFrame = 0l;
|
||||
static JSObject mediaRec = null;
|
||||
static HTMLCanvasElement recCanvas = null;
|
||||
static CanvasRenderingContext2D recCtx = null;
|
||||
static MediaStream recStream = null;
|
||||
|
||||
public static boolean isRec() {
|
||||
return recording && canRec;
|
||||
@ -534,7 +534,7 @@ public class PlatformRuntime {
|
||||
return recording ? "recording.stop" : "recording.start";
|
||||
}
|
||||
|
||||
private static void recFrame() {
|
||||
static void recFrame() {
|
||||
if (mediaRec != null) {
|
||||
int w = PlatformRuntime.canvas.getWidth();
|
||||
int h = PlatformRuntime.canvas.getHeight();
|
||||
@ -546,21 +546,6 @@ public class PlatformRuntime {
|
||||
}
|
||||
}
|
||||
|
||||
private static void onRecFrame() {
|
||||
if (recording) {
|
||||
recFrame();
|
||||
long t = System.currentTimeMillis();
|
||||
Window.requestAnimationFrame(timestamp -> {
|
||||
long d = (1000 / 30) - (System.currentTimeMillis() - t);
|
||||
if (d <= 0) {
|
||||
onRecFrame();
|
||||
} else {
|
||||
Window.setTimeout(PlatformRuntime::onRecFrame, d);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@JSFunctor
|
||||
private static interface MediaHandler extends JSObject {
|
||||
void onMedia(MediaStream stream);
|
||||
@ -630,7 +615,6 @@ public class PlatformRuntime {
|
||||
}, logger::info);
|
||||
}
|
||||
});
|
||||
onRecFrame();
|
||||
} else {
|
||||
stopRec(mediaRec);
|
||||
mediaRec = null;
|
||||
|
@ -0,0 +1,439 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelPeerState;
|
||||
import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelReadyState;
|
||||
import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelType;
|
||||
import net.lax1dude.eaglercraft.v1_8.voice.VoiceClientController;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONWriter;
|
||||
import org.teavm.jso.JSBody;
|
||||
import org.teavm.jso.JSObject;
|
||||
import org.teavm.jso.dom.events.Event;
|
||||
import org.teavm.jso.dom.events.EventListener;
|
||||
import org.teavm.jso.dom.html.HTMLAudioElement;
|
||||
import org.teavm.jso.dom.html.HTMLDocument;
|
||||
import org.teavm.jso.json.JSON;
|
||||
import org.teavm.jso.typedarrays.Uint8Array;
|
||||
import org.teavm.jso.webaudio.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* 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 HOLDER 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.
|
||||
*
|
||||
*/
|
||||
public class PlatformVoiceClient {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger("PlatformVoiceClient");
|
||||
|
||||
private static final HashMap<EaglercraftUUID, AnalyserNode> voiceAnalysers = new HashMap<>();
|
||||
private static final HashMap<EaglercraftUUID, GainNode> voiceGains = new HashMap<>();
|
||||
private static final HashMap<EaglercraftUUID, PannerNode> voicePanners = new HashMap<>();
|
||||
|
||||
@JSBody(params = {}, script = "return typeof window.RTCPeerConnection !== \"undefined\" && typeof navigator.mediaDevices !== \"undefined\" && typeof navigator.mediaDevices.getUserMedia !== \"undefined\";")
|
||||
public static native boolean isSupported();
|
||||
|
||||
@JSBody(params = { "item" }, script = "return item.streams[0];")
|
||||
static native MediaStream getFirstStream(JSObject item);
|
||||
|
||||
@JSBody(params = { "aud", "stream" }, script = "return aud.srcObject = stream;")
|
||||
static native void setSrcObject(HTMLAudioElement aud, MediaStream stream);
|
||||
|
||||
@JSBody(params = { "aud" }, script = "return aud.remove();")
|
||||
static native void removeAud(HTMLAudioElement aud);
|
||||
|
||||
@JSBody(params = { "pc", "stream" }, script = "return stream.getTracks().forEach((track) => { pc.addTrack(track, stream); });")
|
||||
static native void addStream(JSObject pc, MediaStream stream);
|
||||
|
||||
@JSBody(params = { "rawStream", "muted" }, script = "return rawStream.getAudioTracks()[0].enabled = !muted;")
|
||||
static native void mute(MediaStream rawStream, boolean muted);
|
||||
|
||||
@JSBody(params = { "peerConnection", "str" }, script = "return peerConnection.addIceCandidate(new RTCIceCandidate(JSON.parse(str)));")
|
||||
static native void addIceCandidate(JSObject peerConnection, String str);
|
||||
|
||||
public static void disconnect(JSObject peerConnection) {
|
||||
PlatformWebRTC.closeIt(peerConnection);
|
||||
}
|
||||
|
||||
public static void setVoiceProximity(int prox) {
|
||||
for (PannerNode panner : voicePanners.values()) {
|
||||
panner.setMaxDistance(VoiceClientController.getVoiceListenVolume() * 2 * prox + 0.1f);
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateVoicePosition(EaglercraftUUID uuid, double x, double y, double z) {
|
||||
if (voicePanners.containsKey(uuid)) voicePanners.get(uuid).setPosition((float) x, (float) y, (float) z);
|
||||
}
|
||||
|
||||
public static class VoicePeer {
|
||||
public final EaglercraftUUID peerId;
|
||||
public final JSObject peerConnection;
|
||||
public MediaStream rawStream;
|
||||
public VoicePeer(EaglercraftUUID peerId, JSObject peerConnection, boolean offer) {
|
||||
this.peerId = peerId;
|
||||
this.peerConnection = peerConnection;
|
||||
|
||||
TeaVMUtils.addEventListener(peerConnection, "icecandidate", (EventListener<Event>) evt -> {
|
||||
if (PlatformWebRTC.hasCandidate(evt)) {
|
||||
Map<String, String> m = new HashMap<>();
|
||||
m.put("sdpMLineIndex", "" + PlatformWebRTC.getSdpMLineIndex(evt));
|
||||
m.put("candidate", PlatformWebRTC.getCandidate(evt));
|
||||
handleIceCandidate(peerId, JSONWriter.valueToString(m));
|
||||
}
|
||||
});
|
||||
TeaVMUtils.addEventListener(peerConnection, "track", (EventListener<Event>) evt -> {
|
||||
rawStream = getFirstStream(evt);
|
||||
HTMLAudioElement aud = (HTMLAudioElement) HTMLDocument.current().createElement("audio");
|
||||
aud.setAutoplay(true);
|
||||
aud.setMuted(true);
|
||||
TeaVMUtils.addEventListener(aud, "ended", (EventListener<Event>) evt2 -> {
|
||||
removeAud(aud);
|
||||
});
|
||||
setSrcObject(aud, rawStream);
|
||||
handlePeerTrack(peerId, rawStream);
|
||||
});
|
||||
|
||||
addStream(peerConnection, localMediaStream.getStream());
|
||||
if (offer) {
|
||||
PlatformWebRTC.createOffer(peerConnection, desc -> {
|
||||
PlatformWebRTC.setLocalDescription(peerConnection, desc, () -> {
|
||||
handleDescription(peerId, JSON.stringify(desc));
|
||||
}, err -> {
|
||||
logger.error("Failed to set local description for \"{}\"! {}", peerId, err);
|
||||
if (peerStateInitial == EnumVoiceChannelPeerState.LOADING) {
|
||||
peerStateInitial = EnumVoiceChannelPeerState.FAILED;
|
||||
}
|
||||
signalDisconnect(peerId, false);
|
||||
});
|
||||
}, err -> {
|
||||
logger.error("Failed to set create offer for \"{}\"! {}", peerId, err);
|
||||
if (peerStateInitial == EnumVoiceChannelPeerState.LOADING) {
|
||||
peerStateInitial = EnumVoiceChannelPeerState.FAILED;
|
||||
}
|
||||
signalDisconnect(peerId, false);
|
||||
});
|
||||
}
|
||||
|
||||
TeaVMUtils.addEventListener(peerConnection, "connectionstatechange", (EventListener<Event>) evt -> {
|
||||
String cs = PlatformWebRTC.getConnectionState(peerConnection);
|
||||
if ("disconnected".equals(cs)) {
|
||||
signalDisconnect(peerId, false);
|
||||
} else if ("connected".equals(cs)) {
|
||||
if (peerState != EnumVoiceChannelPeerState.SUCCESS) {
|
||||
peerState = EnumVoiceChannelPeerState.SUCCESS;
|
||||
}
|
||||
} else if ("failed".equals(cs)) {
|
||||
if (peerState == EnumVoiceChannelPeerState.LOADING) {
|
||||
peerState = EnumVoiceChannelPeerState.FAILED;
|
||||
}
|
||||
signalDisconnect(peerId, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
PlatformVoiceClient.disconnect(peerConnection);
|
||||
}
|
||||
|
||||
public void mute(boolean muted) {
|
||||
PlatformVoiceClient.mute(rawStream, muted);
|
||||
}
|
||||
|
||||
public void setRemoteDescription(String descJSON) {
|
||||
try {
|
||||
JSONObject remoteDesc = new JSONObject(descJSON);
|
||||
PlatformWebRTC.setRemoteDescription2(peerConnection, descJSON, () -> {
|
||||
if (remoteDesc.has("type") && "offer".equals(remoteDesc.getString("type"))) {
|
||||
PlatformWebRTC.createAnswer(peerConnection, desc -> {
|
||||
PlatformWebRTC.setLocalDescription(peerConnection, desc, () -> {
|
||||
handleDescription(peerId, JSON.stringify(desc));
|
||||
if (peerStateDesc != EnumVoiceChannelPeerState.SUCCESS) peerStateDesc = EnumVoiceChannelPeerState.SUCCESS;
|
||||
}, err -> {
|
||||
logger.error("Failed to set local description for \"{}\"! {}", peerId, err.getMessage());
|
||||
if (peerStateDesc == EnumVoiceChannelPeerState.LOADING) peerStateDesc = EnumVoiceChannelPeerState.FAILED;
|
||||
signalDisconnect(peerId, false);
|
||||
});
|
||||
}, err -> {
|
||||
logger.error("Failed to create answer for \"{}\"! {}", peerId, err.getMessage());
|
||||
if (peerStateDesc == EnumVoiceChannelPeerState.LOADING) peerStateDesc = EnumVoiceChannelPeerState.FAILED;
|
||||
signalDisconnect(peerId, false);
|
||||
});
|
||||
}
|
||||
}, err -> {
|
||||
logger.error("Failed to set remote description for \"{}\"! {}", peerId, err.getMessage());
|
||||
if (peerStateDesc == EnumVoiceChannelPeerState.LOADING) peerStateDesc = EnumVoiceChannelPeerState.FAILED;
|
||||
signalDisconnect(peerId, false);
|
||||
});
|
||||
} catch (Throwable err) {
|
||||
logger.error("Failed to parse remote description for \"{}\"! {}", peerId, err.getMessage());
|
||||
if (peerStateDesc == EnumVoiceChannelPeerState.LOADING) peerStateDesc = EnumVoiceChannelPeerState.FAILED;
|
||||
signalDisconnect(peerId, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void addICECandidate(String candidate) {
|
||||
try {
|
||||
addIceCandidate(peerConnection, candidate);
|
||||
if (peerStateIce != EnumVoiceChannelPeerState.SUCCESS) peerStateIce = EnumVoiceChannelPeerState.SUCCESS;
|
||||
} catch (Throwable err) {
|
||||
logger.error("Failed to parse ice candidate for \"{}\"! {}", peerId, err.getMessage());
|
||||
if (peerStateIce == EnumVoiceChannelPeerState.LOADING) peerStateIce = EnumVoiceChannelPeerState.FAILED;
|
||||
signalDisconnect(peerId, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<Map<String, String>> iceServers = new HashSet<>();
|
||||
public static boolean hasInit = false;
|
||||
public static Map<EaglercraftUUID, VoicePeer> peerList = new HashMap<>();
|
||||
public static MediaStreamAudioDestinationNode localMediaStream;
|
||||
public static GainNode localMediaStreamGain;
|
||||
public static MediaStream localRawMediaStream;
|
||||
public static EnumVoiceChannelReadyState readyState = EnumVoiceChannelReadyState.NONE;
|
||||
public static EnumVoiceChannelPeerState peerState = EnumVoiceChannelPeerState.LOADING;
|
||||
public static EnumVoiceChannelPeerState peerStateConnect = EnumVoiceChannelPeerState.LOADING;
|
||||
public static EnumVoiceChannelPeerState peerStateInitial = EnumVoiceChannelPeerState.LOADING;
|
||||
public static EnumVoiceChannelPeerState peerStateDesc = EnumVoiceChannelPeerState.LOADING;
|
||||
public static EnumVoiceChannelPeerState peerStateIce = EnumVoiceChannelPeerState.LOADING;
|
||||
public static AudioContext microphoneVolumeAudioContext = null;
|
||||
|
||||
public static void setICEServers(String[] urls) {
|
||||
iceServers.clear();
|
||||
if (urls == null) return;
|
||||
for (String url : urls) {
|
||||
String[] etr = url.split(";");
|
||||
if (etr.length == 1) {
|
||||
Map<String, String> m = new HashMap<>();
|
||||
m.put("urls", etr[0]);
|
||||
iceServers.add(m);
|
||||
} else if (etr.length == 3) {
|
||||
Map<String, String> m = new HashMap<>();
|
||||
m.put("urls", etr[0]);
|
||||
m.put("username", etr[1]);
|
||||
m.put("credential", etr[2]);
|
||||
iceServers.add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void activateVoice(boolean talk) {
|
||||
if (hasInit) {
|
||||
PlatformVoiceClient.mute(localRawMediaStream, !talk);
|
||||
}
|
||||
}
|
||||
|
||||
public static void initializeDevices() {
|
||||
if (!hasInit) {
|
||||
localRawMediaStream = PlatformRuntime.getMic();
|
||||
if (localRawMediaStream == null) {
|
||||
readyState = EnumVoiceChannelReadyState.ABORTED;
|
||||
return;
|
||||
}
|
||||
microphoneVolumeAudioContext = AudioContext.create();
|
||||
mute(localRawMediaStream, true);
|
||||
localMediaStream = microphoneVolumeAudioContext.createMediaStreamDestination();
|
||||
localMediaStreamGain = microphoneVolumeAudioContext.createGain();
|
||||
microphoneVolumeAudioContext.createMediaStreamSource(localRawMediaStream).connect(localMediaStreamGain);
|
||||
localMediaStreamGain.connect(localMediaStream);
|
||||
localMediaStreamGain.getGain().setValue(1.0F);
|
||||
readyState = EnumVoiceChannelReadyState.DEVICE_INITIALIZED;
|
||||
hasInit = true;
|
||||
} else {
|
||||
readyState = EnumVoiceChannelReadyState.DEVICE_INITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
public static void tickVoiceClient() {
|
||||
for (EaglercraftUUID uuid : voiceAnalysers.keySet()) {
|
||||
AnalyserNode analyser = voiceAnalysers.get(uuid);
|
||||
Uint8Array array = Uint8Array.create(analyser.getFrequencyBinCount());
|
||||
analyser.getByteFrequencyData(array);
|
||||
int len = array.getLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (array.get(i) >= 0.1f) {
|
||||
VoiceClientController.getVoiceSpeaking().add(uuid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setMicVolume(float val) {
|
||||
if (hasInit) {
|
||||
if(val > 0.5F) val = 0.5F + (val - 0.5F) * 2.0F;
|
||||
if(val > 1.5F) val = 1.5F;
|
||||
if(val < 0.0F) val = 0.0F;
|
||||
localMediaStreamGain.getGain().setValue(val * 2.0F);
|
||||
}
|
||||
}
|
||||
|
||||
public static void resetPeerStates() {
|
||||
peerState = peerStateConnect = peerStateInitial = peerStateDesc = peerStateIce = EnumVoiceChannelPeerState.LOADING;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelPeerState getPeerState() {
|
||||
return peerState;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelPeerState getPeerStateConnect() {
|
||||
return peerStateConnect;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelPeerState getPeerStateInitial() {
|
||||
return peerStateInitial;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelPeerState getPeerStateDesc() {
|
||||
return peerStateDesc;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelPeerState getPeerStateIce() {
|
||||
return peerStateIce;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelReadyState getReadyState() {
|
||||
return readyState;
|
||||
}
|
||||
|
||||
public static void signalConnect(EaglercraftUUID peerId, boolean offer) {
|
||||
if (!hasInit) initializeDevices();
|
||||
try {
|
||||
JSObject peerConnection = PlatformWebRTC.createRTCPeerConnection(JSONWriter.valueToString(iceServers));
|
||||
VoicePeer peerInstance = new VoicePeer(peerId, peerConnection, offer);
|
||||
peerList.put(peerId, peerInstance);
|
||||
if (peerStateConnect != EnumVoiceChannelPeerState.SUCCESS) peerStateConnect = EnumVoiceChannelPeerState.SUCCESS;
|
||||
} catch (Throwable e) {
|
||||
if (peerStateConnect == EnumVoiceChannelPeerState.LOADING) peerStateConnect = EnumVoiceChannelPeerState.FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
public static void signalDescription(EaglercraftUUID peerId, String descJSON) {
|
||||
VoicePeer peer = peerList.get(peerId);
|
||||
if (peer != null) {
|
||||
peer.setRemoteDescription(descJSON);
|
||||
}
|
||||
}
|
||||
|
||||
public static void signalDisconnect(EaglercraftUUID peerId, boolean quiet) {
|
||||
VoicePeer peer = peerList.get(peerId);
|
||||
if (peer != null) {
|
||||
peerList.remove(peerId, peer);
|
||||
try {
|
||||
peer.disconnect();
|
||||
} catch (Throwable ignored) {}
|
||||
handlePeerDisconnect(peerId, quiet);
|
||||
}
|
||||
}
|
||||
|
||||
public static void mutePeer(EaglercraftUUID peerId, boolean muted) {
|
||||
VoicePeer peer = peerList.get(peerId);
|
||||
if (peer != null) {
|
||||
peer.mute(muted);
|
||||
}
|
||||
}
|
||||
|
||||
public static void signalICECandidate(EaglercraftUUID peerId, String candidate) {
|
||||
VoicePeer peer = peerList.get(peerId);
|
||||
if (peer != null) {
|
||||
peer.addICECandidate(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleIceCandidate(EaglercraftUUID peerId, String candidate) {
|
||||
VoiceClientController.sendPacketICE(peerId, candidate);
|
||||
}
|
||||
|
||||
public static void handleDescription(EaglercraftUUID peerId, String desc) {
|
||||
VoiceClientController.sendPacketDesc(peerId, desc);
|
||||
}
|
||||
|
||||
public static void handlePeerTrack(EaglercraftUUID peerId, MediaStream audioStream) {
|
||||
if (VoiceClientController.getVoiceChannel() == EnumVoiceChannelType.NONE) return;
|
||||
MediaStreamAudioSourceNode audioNode = PlatformAudio.audioctx.createMediaStreamSource(audioStream);
|
||||
AnalyserNode analyser = PlatformAudio.audioctx.createAnalyser();
|
||||
analyser.setSmoothingTimeConstant(0f);
|
||||
analyser.setFftSize(32);
|
||||
audioNode.connect(analyser);
|
||||
voiceAnalysers.put(peerId, analyser);
|
||||
if (VoiceClientController.getVoiceChannel() == EnumVoiceChannelType.GLOBAL) {
|
||||
GainNode gain = PlatformAudio.audioctx.createGain();
|
||||
gain.getGain().setValue(VoiceClientController.getVoiceListenVolume());
|
||||
analyser.connect(gain);
|
||||
gain.connect(PlatformAudio.audioctx.getDestination());
|
||||
gain.connect(PlatformAudio.recDest);
|
||||
voiceGains.put(peerId, gain);
|
||||
VoiceClientController.getVoiceListening().add(peerId);
|
||||
} else if (VoiceClientController.getVoiceChannel() == EnumVoiceChannelType.PROXIMITY) {
|
||||
PannerNode panner = PlatformAudio.audioctx.createPanner();
|
||||
panner.setRolloffFactor(1f);
|
||||
panner.setDistanceModel("linear");
|
||||
panner.setPanningModel("HRTF");
|
||||
panner.setConeInnerAngle(360f);
|
||||
panner.setConeOuterAngle(0f);
|
||||
panner.setConeOuterGain(0f);
|
||||
panner.setOrientation(0f, 1f, 0f);
|
||||
panner.setPosition(0, 0, 0);
|
||||
float vol = VoiceClientController.getVoiceListenVolume();
|
||||
panner.setMaxDistance(vol * 2 * VoiceClientController.getVoiceProximity() + 0.1f);
|
||||
GainNode gain = PlatformAudio.audioctx.createGain();
|
||||
gain.getGain().setValue(vol);
|
||||
analyser.connect(gain);
|
||||
gain.connect(panner);
|
||||
panner.connect(PlatformAudio.audioctx.getDestination());
|
||||
panner.connect(PlatformAudio.recDest);
|
||||
voiceGains.put(peerId, gain);
|
||||
VoiceClientController.getVoiceListening().add(peerId);
|
||||
voicePanners.put(peerId, panner);
|
||||
}
|
||||
if (VoiceClientController.getVoiceMuted().contains(peerId)) mutePeer(peerId, true);
|
||||
}
|
||||
|
||||
public static void handlePeerDisconnect(EaglercraftUUID peerId, boolean quiet) {
|
||||
if (voiceAnalysers.containsKey(peerId)) {
|
||||
voiceAnalysers.get(peerId).disconnect();
|
||||
voiceAnalysers.remove(peerId);
|
||||
}
|
||||
if (voiceGains.containsKey(peerId)) {
|
||||
voiceGains.get(peerId).disconnect();
|
||||
voiceGains.remove(peerId);
|
||||
VoiceClientController.getVoiceListening().remove(peerId);
|
||||
}
|
||||
if (voicePanners.containsKey(peerId)) {
|
||||
voicePanners.get(peerId).disconnect();
|
||||
voicePanners.remove(peerId);
|
||||
}
|
||||
if (!quiet) {
|
||||
VoiceClientController.sendPacketDisconnect(peerId);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setVoiceListenVolume(float f) {
|
||||
for (EaglercraftUUID uuid : voiceGains.keySet()) {
|
||||
GainNode gain = voiceGains.get(uuid);
|
||||
float val = f;
|
||||
if(val > 0.5f) val = 0.5f + (val - 0.5f) * 3.0f;
|
||||
if(val > 2.0f) val = 2.0f;
|
||||
if(val < 0.0f) val = 0.0f;
|
||||
gain.getGain().setValue(val * 2.0f);
|
||||
if (voicePanners.containsKey(uuid)) voicePanners.get(uuid).setMaxDistance(f * 2 * VoiceClientController.getVoiceProximity() + 0.1f);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
|
||||
|
||||
import org.teavm.jso.typedarrays.ArrayBuffer;
|
||||
import org.teavm.jso.typedarrays.DataView;
|
||||
import org.teavm.jso.typedarrays.Float32Array;
|
||||
import org.teavm.jso.typedarrays.Int32Array;
|
||||
import org.teavm.jso.typedarrays.Int8Array;
|
||||
import org.teavm.jso.typedarrays.Uint16Array;
|
||||
import org.teavm.jso.typedarrays.Uint8Array;
|
||||
|
||||
@ -31,27 +31,31 @@ public class EaglerArrayBufferAllocator {
|
||||
}
|
||||
|
||||
public static ByteBuffer allocateByteBuffer(int size) {
|
||||
return new EaglerArrayByteBuffer(DataView.create(ArrayBuffer.create(size)));
|
||||
return new EaglerArrayByteBuffer(Int8Array.create(size));
|
||||
}
|
||||
|
||||
public static ByteBuffer wrapByteBufferTeaVM(DataView dv) {
|
||||
return new EaglerArrayByteBuffer(dv);
|
||||
}
|
||||
|
||||
public static IntBuffer allocateIntBuffer(int size) {
|
||||
return new EaglerArrayIntBuffer(DataView.create(ArrayBuffer.create(size << 2)));
|
||||
public static ByteBuffer wrapByteBufferTeaVM(Int8Array typedArray) {
|
||||
return new EaglerArrayByteBuffer(typedArray);
|
||||
}
|
||||
|
||||
public static IntBuffer wrapIntBufferTeaVM(DataView dv) {
|
||||
return new EaglerArrayIntBuffer(dv);
|
||||
public static IntBuffer allocateIntBuffer(int size) {
|
||||
return new EaglerArrayIntBuffer(Int32Array.create(size));
|
||||
}
|
||||
|
||||
public static IntBuffer wrapIntBufferTeaVM(Int32Array typedArray) {
|
||||
return new EaglerArrayIntBuffer(typedArray);
|
||||
}
|
||||
|
||||
public static FloatBuffer allocateFloatBuffer(int size) {
|
||||
return new EaglerArrayFloatBuffer(DataView.create(ArrayBuffer.create(size << 2)));
|
||||
return new EaglerArrayFloatBuffer(Float32Array.create(size));
|
||||
}
|
||||
|
||||
public static FloatBuffer wrapFloatBufferTeaVM(DataView dv) {
|
||||
return new EaglerArrayFloatBuffer(dv);
|
||||
public static FloatBuffer wrapFloatBufferTeaVM(Float32Array typedArray) {
|
||||
return new EaglerArrayFloatBuffer(typedArray);
|
||||
}
|
||||
|
||||
public static DataView getDataView(ByteBuffer buffer) {
|
||||
@ -63,121 +67,115 @@ public class EaglerArrayBufferAllocator {
|
||||
if(p == 0 && l == b.capacity) {
|
||||
return d;
|
||||
}else {
|
||||
int i = d.getByteOffset();
|
||||
return DataView.create(d.getBuffer(), i + p, l - p);
|
||||
return DataView.create(d.getBuffer(), d.getByteOffset() + p, l - p);
|
||||
}
|
||||
}else {
|
||||
throw notEagler(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static Uint8Array getDataViewStupid(ByteBuffer buffer) {
|
||||
public static Int8Array getDataView8(ByteBuffer buffer) {
|
||||
if(buffer instanceof EaglerArrayByteBuffer) {
|
||||
EaglerArrayByteBuffer b = (EaglerArrayByteBuffer)buffer;
|
||||
DataView d = b.dataView;
|
||||
int p = b.position;
|
||||
int l = b.limit;
|
||||
int i = d.getByteOffset();
|
||||
return Uint8Array.create(d.getBuffer(), i + p, l - p);
|
||||
}else {
|
||||
throw notEagler(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static Uint16Array getDataViewStupid16(ByteBuffer buffer) {
|
||||
if(buffer instanceof EaglerArrayByteBuffer) {
|
||||
EaglerArrayByteBuffer b = (EaglerArrayByteBuffer)buffer;
|
||||
DataView d = b.dataView;
|
||||
int p = b.position;
|
||||
int l = b.limit;
|
||||
int i = d.getByteOffset();
|
||||
return Uint16Array.create(d.getBuffer(), i + p, (l - p) >> 1);
|
||||
}else {
|
||||
throw notEagler(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static DataView getDataView(IntBuffer buffer) {
|
||||
if(buffer instanceof EaglerArrayIntBuffer) {
|
||||
EaglerArrayIntBuffer b = (EaglerArrayIntBuffer)buffer;
|
||||
DataView d = b.dataView;
|
||||
Int8Array d = b.typedArray;
|
||||
int p = b.position;
|
||||
int l = b.limit;
|
||||
if(p == 0 && l == b.capacity) {
|
||||
return d;
|
||||
}else {
|
||||
int i = d.getByteOffset();
|
||||
return DataView.create(d.getBuffer(), i + (p << 2), (l - p) << 2);
|
||||
return Int8Array.create(d.getBuffer(), d.getByteOffset() + p, l - p);
|
||||
}
|
||||
}else {
|
||||
throw notEagler(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static Uint8Array getDataViewStupid(IntBuffer buffer) {
|
||||
if(buffer instanceof EaglerArrayIntBuffer) {
|
||||
EaglerArrayIntBuffer b = (EaglerArrayIntBuffer)buffer;
|
||||
DataView d = b.dataView;
|
||||
public static Uint8Array getDataView8Unsigned(ByteBuffer buffer) {
|
||||
if(buffer instanceof EaglerArrayByteBuffer) {
|
||||
EaglerArrayByteBuffer b = (EaglerArrayByteBuffer)buffer;
|
||||
Int8Array d = b.typedArray;
|
||||
int p = b.position;
|
||||
int l = b.limit;
|
||||
int i = d.getByteOffset();
|
||||
return Uint8Array.create(d.getBuffer(), i + (p << 2), (l - p) << 2);
|
||||
return Uint8Array.create(d.getBuffer(), i + p, b.limit - p);
|
||||
}else {
|
||||
throw notEagler(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static Int32Array getDataViewStupid32(IntBuffer buffer) {
|
||||
if(buffer instanceof EaglerArrayIntBuffer) {
|
||||
EaglerArrayIntBuffer b = (EaglerArrayIntBuffer)buffer;
|
||||
DataView d = b.dataView;
|
||||
public static Uint16Array getDataView16Unsigned(ByteBuffer buffer) {
|
||||
if(buffer instanceof EaglerArrayByteBuffer) {
|
||||
EaglerArrayByteBuffer b = (EaglerArrayByteBuffer)buffer;
|
||||
Int8Array d = b.typedArray;
|
||||
int p = b.position;
|
||||
int l = b.limit;
|
||||
int i = d.getByteOffset();
|
||||
return Int32Array.create(d.getBuffer(), i + (p << 2), (l - p) << 2);
|
||||
return Uint16Array.create(d.getBuffer(), d.getByteOffset() + p, (b.limit - p) >> 1);
|
||||
}else {
|
||||
throw notEagler(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static DataView getDataView(FloatBuffer buffer) {
|
||||
if(buffer instanceof EaglerArrayFloatBuffer) {
|
||||
EaglerArrayFloatBuffer b = (EaglerArrayFloatBuffer)buffer;
|
||||
DataView d = b.dataView;
|
||||
public static Float32Array getDataView32F(ByteBuffer buffer) {
|
||||
if(buffer instanceof EaglerArrayByteBuffer) {
|
||||
EaglerArrayByteBuffer b = (EaglerArrayByteBuffer)buffer;
|
||||
Int8Array d = b.typedArray;
|
||||
int p = b.position;
|
||||
return Float32Array.create(d.getBuffer(), d.getByteOffset() + p, (b.limit - p) >> 2);
|
||||
}else {
|
||||
throw notEagler(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static Int32Array getDataView32(IntBuffer buffer) {
|
||||
if(buffer instanceof EaglerArrayIntBuffer) {
|
||||
EaglerArrayIntBuffer b = (EaglerArrayIntBuffer)buffer;
|
||||
Int32Array d = b.typedArray;
|
||||
int p = b.position;
|
||||
int l = b.limit;
|
||||
if(p == 0 && l == b.capacity) {
|
||||
return d;
|
||||
}else {
|
||||
int i = d.getByteOffset();
|
||||
return DataView.create(d.getBuffer(), i + (p << 2), (l - p) << 2);
|
||||
return Int32Array.create(d.getBuffer(), d.getByteOffset() + (p << 2), l - p);
|
||||
}
|
||||
}else {
|
||||
throw notEagler(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static Uint8Array getDataViewStupid(FloatBuffer buffer) {
|
||||
if(buffer instanceof EaglerArrayFloatBuffer) {
|
||||
EaglerArrayFloatBuffer b = (EaglerArrayFloatBuffer)buffer;
|
||||
DataView d = b.dataView;
|
||||
public static Uint8Array getDataView8Unsigned(IntBuffer buffer) {
|
||||
if(buffer instanceof EaglerArrayIntBuffer) {
|
||||
EaglerArrayIntBuffer b = (EaglerArrayIntBuffer)buffer;
|
||||
Int32Array d = b.typedArray;
|
||||
int p = b.position;
|
||||
int l = b.limit;
|
||||
int i = d.getByteOffset();
|
||||
return Uint8Array.create(d.getBuffer(), i + (p << 2), (l - p) << 2);
|
||||
return Uint8Array.create(d.getBuffer(), d.getByteOffset() + (p << 2), (l - p) << 2);
|
||||
}else {
|
||||
throw notEagler(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static Float32Array getFloatArrayStupid(FloatBuffer buffer) {
|
||||
public static Float32Array getDataView32F(FloatBuffer buffer) {
|
||||
if(buffer instanceof EaglerArrayFloatBuffer) {
|
||||
EaglerArrayFloatBuffer b = (EaglerArrayFloatBuffer)buffer;
|
||||
DataView d = b.dataView;
|
||||
Float32Array d = b.typedArray;
|
||||
int p = b.position;
|
||||
int l = b.limit;
|
||||
int i = d.getByteOffset();
|
||||
return Float32Array.create(d.getBuffer(), i + p, l - p);
|
||||
if(p == 0 && l == b.capacity) {
|
||||
return d;
|
||||
}else {
|
||||
return Float32Array.create(d.getBuffer(), d.getByteOffset() + (p << 2), l - p);
|
||||
}
|
||||
}else {
|
||||
throw notEagler(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static Uint8Array getDataView8Unsigned(FloatBuffer buffer) {
|
||||
if(buffer instanceof EaglerArrayFloatBuffer) {
|
||||
EaglerArrayFloatBuffer b = (EaglerArrayFloatBuffer)buffer;
|
||||
Float32Array d = b.typedArray;
|
||||
int p = b.position;
|
||||
int l = b.limit;
|
||||
return Uint8Array.create(d.getBuffer(), d.getByteOffset() + (p << 2), (l - p) << 2);
|
||||
}else {
|
||||
throw notEagler(buffer);
|
||||
}
|
||||
|
@ -1,8 +1,12 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
|
||||
|
||||
import org.teavm.jso.typedarrays.ArrayBuffer;
|
||||
import org.teavm.jso.typedarrays.DataView;
|
||||
import org.teavm.jso.typedarrays.Uint8Array;
|
||||
import org.teavm.jso.typedarrays.Float32Array;
|
||||
import org.teavm.jso.typedarrays.Int16Array;
|
||||
import org.teavm.jso.typedarrays.Int32Array;
|
||||
import org.teavm.jso.typedarrays.Int8Array;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2023 lax1dude. All Rights Reserved.
|
||||
@ -22,16 +26,18 @@ import org.teavm.jso.typedarrays.Uint8Array;
|
||||
public class EaglerArrayByteBuffer implements ByteBuffer {
|
||||
|
||||
final DataView dataView;
|
||||
final Int8Array typedArray;
|
||||
|
||||
final int capacity;
|
||||
int position;
|
||||
int limit;
|
||||
int mark;
|
||||
|
||||
static final DataView ZERO_LENGTH_BUFFER = DataView.create(ArrayBuffer.create(0));
|
||||
static final Int8Array ZERO_LENGTH_BUFFER = Int8Array.create(0);
|
||||
|
||||
EaglerArrayByteBuffer(DataView dataView) {
|
||||
this.dataView = dataView;
|
||||
this.typedArray = Int8Array.create(dataView.getBuffer(), dataView.getByteOffset(), dataView.getByteLength());
|
||||
this.capacity = dataView.getByteLength();
|
||||
this.position = 0;
|
||||
this.limit = this.capacity;
|
||||
@ -40,11 +46,30 @@ public class EaglerArrayByteBuffer implements ByteBuffer {
|
||||
|
||||
EaglerArrayByteBuffer(DataView dataView, int position, int limit, int mark) {
|
||||
this.dataView = dataView;
|
||||
this.typedArray = Int8Array.create(dataView.getBuffer(), dataView.getByteOffset(), dataView.getByteLength());
|
||||
this.capacity = dataView.getByteLength();
|
||||
this.position = position;
|
||||
this.limit = limit;
|
||||
this.mark = mark;
|
||||
}
|
||||
|
||||
EaglerArrayByteBuffer(Int8Array typedArray) {
|
||||
this.typedArray = typedArray;
|
||||
this.dataView = DataView.create(typedArray.getBuffer(), typedArray.getByteOffset(), typedArray.getByteLength());
|
||||
this.capacity = typedArray.getByteLength();
|
||||
this.position = 0;
|
||||
this.limit = this.capacity;
|
||||
this.mark = -1;
|
||||
}
|
||||
|
||||
EaglerArrayByteBuffer(Int8Array typedArray, int position, int limit, int mark) {
|
||||
this.typedArray = typedArray;
|
||||
this.dataView = DataView.create(typedArray.getBuffer(), typedArray.getByteOffset(), typedArray.getByteLength());
|
||||
this.capacity = typedArray.getByteLength();
|
||||
this.position = position;
|
||||
this.limit = limit;
|
||||
this.mark = mark;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int capacity() {
|
||||
@ -93,8 +118,12 @@ public class EaglerArrayByteBuffer implements ByteBuffer {
|
||||
|
||||
@Override
|
||||
public ByteBuffer slice() {
|
||||
int o = dataView.getByteOffset();
|
||||
return new EaglerArrayByteBuffer(DataView.create(dataView.getBuffer(), o + position, limit - position));
|
||||
if(position == limit) {
|
||||
return new EaglerArrayByteBuffer(ZERO_LENGTH_BUFFER);
|
||||
}else {
|
||||
if(position > limit) throw new ArrayIndexOutOfBoundsException(position);
|
||||
return new EaglerArrayByteBuffer(Int8Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + position, limit - position));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -110,35 +139,33 @@ public class EaglerArrayByteBuffer implements ByteBuffer {
|
||||
@Override
|
||||
public byte get() {
|
||||
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
|
||||
return dataView.getInt8(position++);
|
||||
return typedArray.get(position++);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer put(byte b) {
|
||||
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
|
||||
dataView.setInt8(position++, b);
|
||||
typedArray.set(position++, b);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte get(int index) {
|
||||
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
|
||||
return dataView.getInt8(index);
|
||||
return typedArray.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer put(int index, byte b) {
|
||||
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
|
||||
dataView.setInt8(index, b);
|
||||
typedArray.set(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] = dataView.getInt8(position + i);
|
||||
}
|
||||
TeaVMUtils.unwrapArrayBufferView(dst).set(Int8Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + position, length), offset);
|
||||
position += length;
|
||||
return this;
|
||||
}
|
||||
@ -146,9 +173,7 @@ public class EaglerArrayByteBuffer implements ByteBuffer {
|
||||
@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] = dataView.getInt8(position + i);
|
||||
}
|
||||
TeaVMUtils.unwrapArrayBufferView(dst).set(Int8Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + position, dst.length));
|
||||
position += dst.length;
|
||||
return this;
|
||||
}
|
||||
@ -159,10 +184,7 @@ public class EaglerArrayByteBuffer implements ByteBuffer {
|
||||
EaglerArrayByteBuffer c = (EaglerArrayByteBuffer)src;
|
||||
int l = c.limit - c.position;
|
||||
if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1);
|
||||
int o = c.dataView.getByteOffset();
|
||||
Uint8Array.create(dataView.getBuffer()).set(
|
||||
Uint8Array.create(c.dataView.getBuffer(), o + c.position, c.limit - c.position),
|
||||
dataView.getByteOffset() + position);
|
||||
typedArray.set(Int8Array.create(c.typedArray.getBuffer(), c.typedArray.getByteOffset() + c.position, l), position);
|
||||
position += l;
|
||||
c.position += l;
|
||||
}else {
|
||||
@ -179,8 +201,10 @@ public class EaglerArrayByteBuffer implements ByteBuffer {
|
||||
@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) {
|
||||
dataView.setInt8(position + i, src[offset + i]);
|
||||
if(offset == 0 && length == src.length) {
|
||||
typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position);
|
||||
}else {
|
||||
typedArray.set(Int8Array.create(TeaVMUtils.unwrapArrayBuffer(src), offset, length), position);
|
||||
}
|
||||
position += length;
|
||||
return this;
|
||||
@ -189,10 +213,7 @@ public class EaglerArrayByteBuffer implements ByteBuffer {
|
||||
@Override
|
||||
public ByteBuffer put(byte[] src) {
|
||||
if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1);
|
||||
//dataView.set(src, position); // doesn't work
|
||||
for(int i = 0; i < src.length; ++i) {
|
||||
dataView.setInt8(position + i, src[i]);
|
||||
}
|
||||
typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position);
|
||||
position += src.length;
|
||||
return this;
|
||||
}
|
||||
@ -211,12 +232,10 @@ public class EaglerArrayByteBuffer implements ByteBuffer {
|
||||
return new EaglerArrayByteBuffer(ZERO_LENGTH_BUFFER);
|
||||
}
|
||||
|
||||
int o = dataView.getByteOffset();
|
||||
Int8Array dst = Int8Array.create(limit - position);
|
||||
dst.set(Int8Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + position, limit - position));
|
||||
|
||||
Uint8Array dst = Uint8Array.create(ArrayBuffer.create(limit - position));
|
||||
dst.set(Uint8Array.create(dataView.getBuffer(), o + position, limit - position));
|
||||
|
||||
return new EaglerArrayByteBuffer(DataView.create(dst.getBuffer()));
|
||||
return new EaglerArrayByteBuffer(dst);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -279,7 +298,7 @@ public class EaglerArrayByteBuffer implements ByteBuffer {
|
||||
|
||||
@Override
|
||||
public ShortBuffer asShortBuffer() {
|
||||
return new EaglerArrayShortBuffer(dataView);
|
||||
return new EaglerArrayShortBuffer(Int16Array.create(typedArray.getBuffer(), typedArray.getByteOffset(), typedArray.getLength() >> 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -313,7 +332,7 @@ public class EaglerArrayByteBuffer implements ByteBuffer {
|
||||
|
||||
@Override
|
||||
public IntBuffer asIntBuffer() {
|
||||
return new EaglerArrayIntBuffer(dataView);
|
||||
return new EaglerArrayIntBuffer(Int32Array.create(typedArray.getBuffer(), typedArray.getByteOffset(), typedArray.getLength() >> 2));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -388,7 +407,7 @@ public class EaglerArrayByteBuffer implements ByteBuffer {
|
||||
|
||||
@Override
|
||||
public FloatBuffer asFloatBuffer() {
|
||||
return new EaglerArrayFloatBuffer(dataView);
|
||||
return new EaglerArrayFloatBuffer(Float32Array.create(typedArray.getBuffer(), typedArray.getByteOffset(), typedArray.getLength() >> 2));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,8 +1,8 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
|
||||
|
||||
import org.teavm.jso.typedarrays.ArrayBuffer;
|
||||
import org.teavm.jso.typedarrays.DataView;
|
||||
import org.teavm.jso.typedarrays.Uint8Array;
|
||||
import org.teavm.jso.typedarrays.Float32Array;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2023 lax1dude. All Rights Reserved.
|
||||
@ -21,7 +21,7 @@ import org.teavm.jso.typedarrays.Uint8Array;
|
||||
*/
|
||||
public class EaglerArrayFloatBuffer implements FloatBuffer {
|
||||
|
||||
final DataView dataView;
|
||||
final Float32Array typedArray;
|
||||
|
||||
final int capacity;
|
||||
int position;
|
||||
@ -30,17 +30,19 @@ public class EaglerArrayFloatBuffer implements FloatBuffer {
|
||||
|
||||
private static final int SHIFT = 2;
|
||||
|
||||
EaglerArrayFloatBuffer(DataView dataView) {
|
||||
this.dataView = dataView;
|
||||
this.capacity = dataView.getByteLength() >> SHIFT;
|
||||
static final Float32Array ZERO_LENGTH_BUFFER = Float32Array.create(0);
|
||||
|
||||
EaglerArrayFloatBuffer(Float32Array typedArray) {
|
||||
this.typedArray = typedArray;
|
||||
this.capacity = typedArray.getLength();
|
||||
this.position = 0;
|
||||
this.limit = this.capacity;
|
||||
this.mark = -1;
|
||||
}
|
||||
|
||||
EaglerArrayFloatBuffer(DataView dataView, int position, int limit, int mark) {
|
||||
this.dataView = dataView;
|
||||
this.capacity = dataView.getByteLength() >> SHIFT;
|
||||
EaglerArrayFloatBuffer(Float32Array typedArray, int position, int limit, int mark) {
|
||||
this.typedArray = typedArray;
|
||||
this.capacity = typedArray.getLength();
|
||||
this.position = position;
|
||||
this.limit = limit;
|
||||
this.mark = mark;
|
||||
@ -93,64 +95,66 @@ public class EaglerArrayFloatBuffer implements FloatBuffer {
|
||||
|
||||
@Override
|
||||
public FloatBuffer slice() {
|
||||
int o = dataView.getByteOffset();
|
||||
return new EaglerArrayFloatBuffer(DataView.create(dataView.getBuffer(), o + (position << SHIFT), (limit - position) << SHIFT));
|
||||
if(position == limit) {
|
||||
return new EaglerArrayFloatBuffer(ZERO_LENGTH_BUFFER);
|
||||
}else {
|
||||
if(position > limit) throw new ArrayIndexOutOfBoundsException(position);
|
||||
return new EaglerArrayFloatBuffer(Float32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), limit - position));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloatBuffer duplicate() {
|
||||
return new EaglerArrayFloatBuffer(dataView, position, limit, mark);
|
||||
return new EaglerArrayFloatBuffer(typedArray, position, limit, mark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloatBuffer asReadOnlyBuffer() {
|
||||
return new EaglerArrayFloatBuffer(dataView, position, limit, mark);
|
||||
return new EaglerArrayFloatBuffer(typedArray, position, limit, mark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float get() {
|
||||
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
|
||||
return dataView.getFloat32((position++) << SHIFT, true);
|
||||
return typedArray.get(position++);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloatBuffer put(float b) {
|
||||
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
|
||||
dataView.setFloat32((position++) << SHIFT, b, true);
|
||||
typedArray.set(position++, b);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float get(int index) {
|
||||
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
|
||||
return dataView.getFloat32(index << SHIFT, true);
|
||||
return typedArray.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloatBuffer put(int index, float b) {
|
||||
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
|
||||
dataView.setFloat32(index << SHIFT, b, true);
|
||||
typedArray.set(index, b);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getElement(int index) {
|
||||
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
|
||||
return dataView.getFloat32(index << SHIFT, true);
|
||||
return typedArray.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putElement(int index, float value) {
|
||||
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
|
||||
dataView.setFloat32(index << SHIFT, value, true);
|
||||
typedArray.set(index, 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] = dataView.getFloat32((position + i) << SHIFT, true);
|
||||
}
|
||||
TeaVMUtils.unwrapArrayBufferView(dst).set(Float32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), length), offset);
|
||||
position += length;
|
||||
return this;
|
||||
}
|
||||
@ -158,9 +162,7 @@ public class EaglerArrayFloatBuffer implements FloatBuffer {
|
||||
@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] = dataView.getFloat32((position + i) << SHIFT, true);
|
||||
}
|
||||
TeaVMUtils.unwrapArrayBufferView(dst).set(Float32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), dst.length));
|
||||
position += dst.length;
|
||||
return this;
|
||||
}
|
||||
@ -171,17 +173,14 @@ public class EaglerArrayFloatBuffer implements FloatBuffer {
|
||||
EaglerArrayFloatBuffer c = (EaglerArrayFloatBuffer)src;
|
||||
int l = c.limit - c.position;
|
||||
if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1);
|
||||
int o = c.dataView.getByteOffset();
|
||||
Uint8Array.create(dataView.getBuffer()).set(
|
||||
Uint8Array.create(c.dataView.getBuffer(), o + (c.position << SHIFT), (c.limit - c.position) << SHIFT),
|
||||
dataView.getByteOffset() + (position << SHIFT));
|
||||
typedArray.set(Float32Array.create(c.typedArray.getBuffer(), c.typedArray.getByteOffset() + (c.position << SHIFT), l), position);
|
||||
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) {
|
||||
dataView.setFloat32((position + l) << SHIFT, src.get(), true);
|
||||
typedArray.set(position + l, src.get());
|
||||
}
|
||||
position += l;
|
||||
}
|
||||
@ -191,8 +190,10 @@ public class EaglerArrayFloatBuffer implements FloatBuffer {
|
||||
@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) {
|
||||
dataView.setFloat32((position + i) << SHIFT, src[offset + i], true);
|
||||
if(offset == 0 && length == src.length) {
|
||||
typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position);
|
||||
}else {
|
||||
typedArray.set(Float32Array.create(TeaVMUtils.unwrapArrayBuffer(src), offset << SHIFT, length), position);
|
||||
}
|
||||
position += length;
|
||||
return this;
|
||||
@ -201,9 +202,7 @@ public class EaglerArrayFloatBuffer implements FloatBuffer {
|
||||
@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) {
|
||||
dataView.setFloat32((position + i) << SHIFT, src[i], true);
|
||||
}
|
||||
typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position);
|
||||
position += src.length;
|
||||
return this;
|
||||
}
|
||||
@ -219,15 +218,13 @@ public class EaglerArrayFloatBuffer implements FloatBuffer {
|
||||
if(position > limit) throw new ArrayIndexOutOfBoundsException(position);
|
||||
|
||||
if(position == limit) {
|
||||
return new EaglerArrayFloatBuffer(EaglerArrayByteBuffer.ZERO_LENGTH_BUFFER);
|
||||
return new EaglerArrayFloatBuffer(ZERO_LENGTH_BUFFER);
|
||||
}
|
||||
|
||||
int o = dataView.getByteOffset();
|
||||
Float32Array dst = Float32Array.create(limit - position);
|
||||
dst.set(Float32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), limit - position));
|
||||
|
||||
Uint8Array dst = Uint8Array.create(ArrayBuffer.create((limit - position) << SHIFT));
|
||||
dst.set(Uint8Array.create(dataView.getBuffer(), o + (position << SHIFT), (limit - position) << SHIFT));
|
||||
|
||||
return new EaglerArrayFloatBuffer(DataView.create(dst.getBuffer()));
|
||||
return new EaglerArrayFloatBuffer(dst);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,8 +1,8 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
|
||||
|
||||
import org.teavm.jso.typedarrays.ArrayBuffer;
|
||||
import org.teavm.jso.typedarrays.DataView;
|
||||
import org.teavm.jso.typedarrays.Uint8Array;
|
||||
import org.teavm.jso.typedarrays.Int32Array;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2023 lax1dude. All Rights Reserved.
|
||||
@ -21,7 +21,7 @@ import org.teavm.jso.typedarrays.Uint8Array;
|
||||
*/
|
||||
public class EaglerArrayIntBuffer implements IntBuffer {
|
||||
|
||||
final DataView dataView;
|
||||
final Int32Array typedArray;
|
||||
|
||||
final int capacity;
|
||||
int position;
|
||||
@ -30,17 +30,19 @@ public class EaglerArrayIntBuffer implements IntBuffer {
|
||||
|
||||
private static final int SHIFT = 2;
|
||||
|
||||
EaglerArrayIntBuffer(DataView dataView) {
|
||||
this.dataView = dataView;
|
||||
this.capacity = dataView.getByteLength() >> SHIFT;
|
||||
static final Int32Array ZERO_LENGTH_BUFFER = Int32Array.create(0);
|
||||
|
||||
EaglerArrayIntBuffer(Int32Array typedArray) {
|
||||
this.typedArray = typedArray;
|
||||
this.capacity = typedArray.getLength();
|
||||
this.position = 0;
|
||||
this.limit = this.capacity;
|
||||
this.mark = -1;
|
||||
}
|
||||
|
||||
EaglerArrayIntBuffer(DataView dataView, int position, int limit, int mark) {
|
||||
this.dataView = dataView;
|
||||
this.capacity = dataView.getByteLength() >> SHIFT;
|
||||
EaglerArrayIntBuffer(Int32Array typedArray, int position, int limit, int mark) {
|
||||
this.typedArray = typedArray;
|
||||
this.capacity = typedArray.getLength();
|
||||
this.position = position;
|
||||
this.limit = limit;
|
||||
this.mark = mark;
|
||||
@ -93,64 +95,66 @@ public class EaglerArrayIntBuffer implements IntBuffer {
|
||||
|
||||
@Override
|
||||
public IntBuffer slice() {
|
||||
int o = dataView.getByteOffset();
|
||||
return new EaglerArrayIntBuffer(DataView.create(dataView.getBuffer(), o + (position << SHIFT), (limit - position) << SHIFT));
|
||||
if(position == limit) {
|
||||
return new EaglerArrayIntBuffer(ZERO_LENGTH_BUFFER);
|
||||
}else {
|
||||
if(position > limit) throw new ArrayIndexOutOfBoundsException(position);
|
||||
return new EaglerArrayIntBuffer(Int32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), limit - position));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntBuffer duplicate() {
|
||||
return new EaglerArrayIntBuffer(dataView, position, limit, mark);
|
||||
return new EaglerArrayIntBuffer(typedArray, position, limit, mark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntBuffer asReadOnlyBuffer() {
|
||||
return new EaglerArrayIntBuffer(dataView, position, limit, mark);
|
||||
return new EaglerArrayIntBuffer(typedArray, position, limit, mark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get() {
|
||||
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
|
||||
return dataView.getInt32((position++) << SHIFT, true);
|
||||
return typedArray.get(position++);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntBuffer put(int b) {
|
||||
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
|
||||
dataView.setInt32((position++) << SHIFT, b, true);
|
||||
typedArray.set(position++, b);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get(int index) {
|
||||
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
|
||||
return dataView.getInt32(index << SHIFT, true);
|
||||
return typedArray.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntBuffer put(int index, int b) {
|
||||
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
|
||||
dataView.setInt32(index << SHIFT, b, true);
|
||||
typedArray.set(index, b);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getElement(int index) {
|
||||
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
|
||||
return dataView.getInt32(index << SHIFT, true);
|
||||
return typedArray.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putElement(int index, int value) {
|
||||
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
|
||||
dataView.setInt32(index << SHIFT, value, true);
|
||||
typedArray.set(index, 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] = dataView.getInt32((position + i) << SHIFT, true);
|
||||
}
|
||||
TeaVMUtils.unwrapArrayBufferView(dst).set(Int32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), length), offset);
|
||||
position += length;
|
||||
return this;
|
||||
}
|
||||
@ -158,9 +162,7 @@ public class EaglerArrayIntBuffer implements IntBuffer {
|
||||
@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] = dataView.getInt32((position + i) << SHIFT, true);
|
||||
}
|
||||
TeaVMUtils.unwrapArrayBufferView(dst).set(Int32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), dst.length));
|
||||
position += dst.length;
|
||||
return this;
|
||||
}
|
||||
@ -171,17 +173,14 @@ public class EaglerArrayIntBuffer implements IntBuffer {
|
||||
EaglerArrayIntBuffer c = (EaglerArrayIntBuffer)src;
|
||||
int l = c.limit - c.position;
|
||||
if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1);
|
||||
int o = c.dataView.getByteOffset();
|
||||
Uint8Array.create(dataView.getBuffer()).set(
|
||||
Uint8Array.create(c.dataView.getBuffer(), o + (c.position << SHIFT), (c.limit - c.position) << SHIFT),
|
||||
dataView.getByteOffset() + (position << SHIFT));
|
||||
typedArray.set(Int32Array.create(c.typedArray.getBuffer(), c.typedArray.getByteOffset() + (c.position << SHIFT), l), position);
|
||||
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) {
|
||||
dataView.setInt32((position + l) << SHIFT, src.get(), true);
|
||||
typedArray.set(position + l, src.get());
|
||||
}
|
||||
position += l;
|
||||
}
|
||||
@ -191,8 +190,10 @@ public class EaglerArrayIntBuffer implements IntBuffer {
|
||||
@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) {
|
||||
dataView.setInt32((position + i) << SHIFT, src[offset + i], true);
|
||||
if(offset == 0 && length == src.length) {
|
||||
typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position);
|
||||
}else {
|
||||
typedArray.set(Int32Array.create(TeaVMUtils.unwrapArrayBuffer(src), offset << SHIFT, length), position);
|
||||
}
|
||||
position += length;
|
||||
return this;
|
||||
@ -201,9 +202,7 @@ public class EaglerArrayIntBuffer implements IntBuffer {
|
||||
@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) {
|
||||
dataView.setInt32((position + i) << SHIFT, src[i], true);
|
||||
}
|
||||
typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position);
|
||||
position += src.length;
|
||||
return this;
|
||||
}
|
||||
@ -219,15 +218,13 @@ public class EaglerArrayIntBuffer implements IntBuffer {
|
||||
if(position > limit) throw new ArrayIndexOutOfBoundsException(position);
|
||||
|
||||
if(position == limit) {
|
||||
return new EaglerArrayIntBuffer(EaglerArrayByteBuffer.ZERO_LENGTH_BUFFER);
|
||||
return new EaglerArrayIntBuffer(ZERO_LENGTH_BUFFER);
|
||||
}
|
||||
|
||||
int o = dataView.getByteOffset();
|
||||
Int32Array dst = Int32Array.create(limit - position);
|
||||
dst.set(Int32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), limit - position));
|
||||
|
||||
Uint8Array dst = Uint8Array.create(ArrayBuffer.create((limit - position) << SHIFT));
|
||||
dst.set(Uint8Array.create(dataView.getBuffer(), o + (position << SHIFT), (limit - position) << SHIFT));
|
||||
|
||||
return new EaglerArrayIntBuffer(DataView.create(dst.getBuffer()));
|
||||
return new EaglerArrayIntBuffer(dst);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,8 +1,8 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
|
||||
|
||||
import org.teavm.jso.typedarrays.ArrayBuffer;
|
||||
import org.teavm.jso.typedarrays.DataView;
|
||||
import org.teavm.jso.typedarrays.Uint8Array;
|
||||
import org.teavm.jso.typedarrays.Int16Array;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2023 lax1dude. All Rights Reserved.
|
||||
@ -21,7 +21,7 @@ import org.teavm.jso.typedarrays.Uint8Array;
|
||||
*/
|
||||
public class EaglerArrayShortBuffer implements ShortBuffer {
|
||||
|
||||
final DataView dataView;
|
||||
final Int16Array typedArray;
|
||||
|
||||
final int capacity;
|
||||
int position;
|
||||
@ -30,17 +30,19 @@ public class EaglerArrayShortBuffer implements ShortBuffer {
|
||||
|
||||
private static final int SHIFT = 1;
|
||||
|
||||
EaglerArrayShortBuffer(DataView dataView) {
|
||||
this.dataView = dataView;
|
||||
this.capacity = dataView.getByteLength() >> SHIFT;
|
||||
static final Int16Array ZERO_LENGTH_BUFFER = Int16Array.create(0);
|
||||
|
||||
EaglerArrayShortBuffer(Int16Array typedArray) {
|
||||
this.typedArray = typedArray;
|
||||
this.capacity = typedArray.getLength();
|
||||
this.position = 0;
|
||||
this.limit = this.capacity;
|
||||
this.mark = -1;
|
||||
}
|
||||
|
||||
EaglerArrayShortBuffer(DataView dataView, int position, int limit, int mark) {
|
||||
this.dataView = dataView;
|
||||
this.capacity = dataView.getByteLength() >> SHIFT;
|
||||
EaglerArrayShortBuffer(Int16Array typedArray, int position, int limit, int mark) {
|
||||
this.typedArray = typedArray;
|
||||
this.capacity = typedArray.getLength();
|
||||
this.position = position;
|
||||
this.limit = limit;
|
||||
this.mark = mark;
|
||||
@ -93,64 +95,66 @@ public class EaglerArrayShortBuffer implements ShortBuffer {
|
||||
|
||||
@Override
|
||||
public ShortBuffer slice() {
|
||||
int o = dataView.getByteOffset();
|
||||
return new EaglerArrayShortBuffer(DataView.create(dataView.getBuffer(), o + (position << SHIFT), (limit - position) << SHIFT));
|
||||
if(position == limit) {
|
||||
return new EaglerArrayShortBuffer(ZERO_LENGTH_BUFFER);
|
||||
}else {
|
||||
if(position > limit) throw new ArrayIndexOutOfBoundsException(position);
|
||||
return new EaglerArrayShortBuffer(Int16Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), limit - position));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShortBuffer duplicate() {
|
||||
return new EaglerArrayShortBuffer(dataView, position, limit, mark);
|
||||
return new EaglerArrayShortBuffer(typedArray, position, limit, mark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShortBuffer asReadOnlyBuffer() {
|
||||
return new EaglerArrayShortBuffer(dataView, position, limit, mark);
|
||||
return new EaglerArrayShortBuffer(typedArray, position, limit, mark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short get() {
|
||||
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
|
||||
return dataView.getInt16((position++) << SHIFT, true);
|
||||
return typedArray.get(position++);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShortBuffer put(short b) {
|
||||
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
|
||||
dataView.setInt16((position++) << SHIFT, b, true);
|
||||
typedArray.set(position++, b);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short get(int index) {
|
||||
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
|
||||
return dataView.getInt16(index << SHIFT, true);
|
||||
return typedArray.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShortBuffer put(int index, short b) {
|
||||
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
|
||||
dataView.setInt16(index << SHIFT, b, true);
|
||||
typedArray.set(index, b);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getElement(int index) {
|
||||
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
|
||||
return dataView.getInt16(index << SHIFT, true);
|
||||
return typedArray.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putElement(int index, short value) {
|
||||
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
|
||||
dataView.setInt16(index << SHIFT, value, true);
|
||||
typedArray.set(index, 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] = dataView.getInt16((position + i) << SHIFT, true);
|
||||
}
|
||||
TeaVMUtils.unwrapArrayBufferView(dst).set(Int16Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), length), offset);
|
||||
position += length;
|
||||
return this;
|
||||
}
|
||||
@ -158,9 +162,7 @@ public class EaglerArrayShortBuffer implements ShortBuffer {
|
||||
@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] = dataView.getInt16((position + i) << SHIFT, true);
|
||||
}
|
||||
TeaVMUtils.unwrapArrayBufferView(dst).set(Int16Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), dst.length));
|
||||
position += dst.length;
|
||||
return this;
|
||||
}
|
||||
@ -171,17 +173,14 @@ public class EaglerArrayShortBuffer implements ShortBuffer {
|
||||
EaglerArrayShortBuffer c = (EaglerArrayShortBuffer)src;
|
||||
int l = c.limit - c.position;
|
||||
if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1);
|
||||
int o = c.dataView.getByteOffset();
|
||||
Uint8Array.create(dataView.getBuffer()).set(
|
||||
Uint8Array.create(c.dataView.getBuffer(), o + (c.position << SHIFT), (c.limit - c.position) << SHIFT),
|
||||
dataView.getByteOffset() + (position << SHIFT));
|
||||
typedArray.set(Int16Array.create(c.typedArray.getBuffer(), c.typedArray.getByteOffset() + (c.position << SHIFT), l), position);
|
||||
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) {
|
||||
dataView.setInt16((position + l) << SHIFT, src.get(), true);
|
||||
typedArray.set(position + l, src.get());
|
||||
}
|
||||
position += l;
|
||||
}
|
||||
@ -191,8 +190,10 @@ public class EaglerArrayShortBuffer implements ShortBuffer {
|
||||
@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) {
|
||||
dataView.setInt16((position + i) << SHIFT, src[offset + i], true);
|
||||
if(offset == 0 && length == src.length) {
|
||||
typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position);
|
||||
}else {
|
||||
typedArray.set(Int16Array.create(TeaVMUtils.unwrapArrayBuffer(src), offset << SHIFT, length), position);
|
||||
}
|
||||
position += length;
|
||||
return this;
|
||||
@ -201,9 +202,7 @@ public class EaglerArrayShortBuffer implements ShortBuffer {
|
||||
@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) {
|
||||
dataView.setInt16((position + i) << SHIFT, src[i], true);
|
||||
}
|
||||
typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position);
|
||||
position += src.length;
|
||||
return this;
|
||||
}
|
||||
@ -219,15 +218,13 @@ public class EaglerArrayShortBuffer implements ShortBuffer {
|
||||
if(position > limit) throw new ArrayIndexOutOfBoundsException(position);
|
||||
|
||||
if(position == limit) {
|
||||
return new EaglerArrayShortBuffer(EaglerArrayByteBuffer.ZERO_LENGTH_BUFFER);
|
||||
return new EaglerArrayShortBuffer(ZERO_LENGTH_BUFFER);
|
||||
}
|
||||
|
||||
int o = dataView.getByteOffset();
|
||||
Int16Array dst = Int16Array.create(limit - position);
|
||||
dst.set(Int16Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), limit - position));
|
||||
|
||||
Uint8Array dst = Uint8Array.create(ArrayBuffer.create((limit - position) << SHIFT));
|
||||
dst.set(Uint8Array.create(dataView.getBuffer(), o + (position << SHIFT), (limit - position) << SHIFT));
|
||||
|
||||
return new EaglerArrayShortBuffer(DataView.create(dst.getBuffer()));
|
||||
return new EaglerArrayShortBuffer(dst);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
File diff suppressed because one or more lines are too long
@ -55,6 +55,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
|
||||
private boolean logInvalidCerts = false;
|
||||
private boolean checkRelaysForUpdates = false;
|
||||
private boolean enableSignatureBadge = false;
|
||||
private boolean allowVoiceClient = true;
|
||||
|
||||
public void loadNative(JSObject jsObject) {
|
||||
integratedServerOpts = new JSONObject();
|
||||
@ -73,12 +74,14 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
|
||||
useSpecialCursors = eaglercraftXOpts.getHtml5CursorSupport(false);
|
||||
logInvalidCerts = EaglercraftVersion.enableUpdateService && !demoMode && eaglercraftXOpts.getLogInvalidCerts(false);
|
||||
enableSignatureBadge = eaglercraftXOpts.getEnableSignatureBadge(false);
|
||||
allowVoiceClient = eaglercraftXOpts.getAllowVoiceClient(true);
|
||||
|
||||
integratedServerOpts.put("worldsDB", worldsDB);
|
||||
integratedServerOpts.put("demoMode", demoMode);
|
||||
integratedServerOpts.put("lang", defaultLocale);
|
||||
integratedServerOpts.put("allowUpdateSvc", isAllowUpdateSvc);
|
||||
integratedServerOpts.put("allowUpdateDL", isAllowUpdateDL);
|
||||
integratedServerOpts.put("allowVoiceClient", allowVoiceClient);
|
||||
|
||||
JSEaglercraftXOptsServersArray serversArray = eaglercraftXOpts.getServers();
|
||||
if(serversArray != null) {
|
||||
@ -158,6 +161,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
|
||||
useSpecialCursors = eaglercraftOpts.optBoolean("html5CursorSupport", false);
|
||||
logInvalidCerts = EaglercraftVersion.enableUpdateService && !demoMode && eaglercraftOpts.optBoolean("logInvalidCerts", false);
|
||||
enableSignatureBadge = eaglercraftOpts.optBoolean("enableSignatureBadge", false);
|
||||
allowVoiceClient = eaglercraftOpts.optBoolean("allowVoiceClient", true);
|
||||
JSONArray serversArray = eaglercraftOpts.optJSONArray("servers");
|
||||
if(serversArray != null) {
|
||||
for(int i = 0, l = serversArray.length(); i < l; ++i) {
|
||||
@ -300,6 +304,11 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
|
||||
return enableSignatureBadge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllowVoiceClient() {
|
||||
return allowVoiceClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
@ -317,6 +326,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
|
||||
jsonObject.put("logInvalidCerts", logInvalidCerts);
|
||||
jsonObject.put("checkRelaysForUpdates", checkRelaysForUpdates);
|
||||
jsonObject.put("enableSignatureBadge", enableSignatureBadge);
|
||||
jsonObject.put("allowVoiceClient", allowVoiceClient);
|
||||
JSONArray serversArr = new JSONArray();
|
||||
for(int i = 0, l = defaultServers.size(); i < l; ++i) {
|
||||
DefaultServer srv = defaultServers.get(i);
|
||||
|
@ -9,6 +9,7 @@ import org.teavm.jso.browser.Window;
|
||||
import org.teavm.jso.typedarrays.ArrayBuffer;
|
||||
import org.teavm.jso.typedarrays.ArrayBufferView;
|
||||
import org.teavm.jso.typedarrays.Float32Array;
|
||||
import org.teavm.jso.typedarrays.Int16Array;
|
||||
import org.teavm.jso.typedarrays.Int32Array;
|
||||
import org.teavm.jso.typedarrays.Int8Array;
|
||||
import org.teavm.jso.typedarrays.Uint8Array;
|
||||
@ -57,6 +58,10 @@ public class TeaVMUtils {
|
||||
return ((TeaVMArrayObject)(Object)buf).getData().getBuffer();
|
||||
}
|
||||
|
||||
public static ArrayBufferView unwrapArrayBufferView(byte[] buf) {
|
||||
return ((TeaVMArrayObject)(Object)buf).getData();
|
||||
}
|
||||
|
||||
@JSBody(params = { "buf" }, script = "return $rt_createByteArray(buf.buffer)")
|
||||
private static native JSObject wrapByteArray0(JSObject buf);
|
||||
|
||||
@ -80,6 +85,10 @@ public class TeaVMUtils {
|
||||
return ((TeaVMArrayObject)(Object)buf).getData().getBuffer();
|
||||
}
|
||||
|
||||
public static ArrayBufferView unwrapArrayBufferView(int[] buf) {
|
||||
return ((TeaVMArrayObject)(Object)buf).getData();
|
||||
}
|
||||
|
||||
@JSBody(params = { "buf" }, script = "return $rt_createIntArray(buf.buffer)")
|
||||
private static native JSObject wrapIntArray0(JSObject buf);
|
||||
|
||||
@ -95,6 +104,10 @@ public class TeaVMUtils {
|
||||
return ((TeaVMArrayObject)(Object)buf).getData().getBuffer();
|
||||
}
|
||||
|
||||
public static ArrayBufferView unwrapArrayBufferView(float[] buf) {
|
||||
return ((TeaVMArrayObject)(Object)buf).getData();
|
||||
}
|
||||
|
||||
@JSBody(params = { "buf" }, script = "return $rt_createFloatArray(buf.buffer)")
|
||||
private static native JSObject wrapFloatArray0(JSObject buf);
|
||||
|
||||
@ -102,6 +115,25 @@ public class TeaVMUtils {
|
||||
return (float[])(Object)wrapFloatArray0(buf);
|
||||
}
|
||||
|
||||
public static Int16Array unwrapShortArray(short[] buf) {
|
||||
return Int16Array.create(((TeaVMArrayObject)(Object)buf).getData().getBuffer());
|
||||
}
|
||||
|
||||
public static ArrayBuffer unwrapArrayBuffer(short[] buf) {
|
||||
return ((TeaVMArrayObject)(Object)buf).getData().getBuffer();
|
||||
}
|
||||
|
||||
public static ArrayBufferView unwrapArrayBufferView(short[] buf) {
|
||||
return ((TeaVMArrayObject)(Object)buf).getData();
|
||||
}
|
||||
|
||||
@JSBody(params = { "buf" }, script = "return $rt_createShortArray(buf.buffer)")
|
||||
private static native JSObject wrapShortArray0(JSObject buf);
|
||||
|
||||
public static short[] wrapShortArray(Int16Array buf) {
|
||||
return (short[])(Object)wrapShortArray0(buf);
|
||||
}
|
||||
|
||||
@Async
|
||||
public static native void sleepSetTimeout(int millis);
|
||||
|
||||
|
@ -80,4 +80,7 @@ public abstract class JSEaglercraftXOptsRoot implements JSObject {
|
||||
@JSBody(params = { "def" }, script = "return (typeof this.checkRelaysForUpdates === \"boolean\") ? this.checkRelaysForUpdates : def;")
|
||||
public native boolean getCheckRelaysForUpdates(boolean defaultValue);
|
||||
|
||||
@JSBody(params = { "def" }, script = "return (typeof this.allowVoiceClient === \"boolean\") ? this.allowVoiceClient : def;")
|
||||
public native boolean getAllowVoiceClient(boolean defaultValue);
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user