1
0
Fork 0
This commit is contained in:
HoosierTransfer 2024-04-23 15:37:06 -04:00
parent 37f2ac12ba
commit 033e99a4d7
147 changed files with 78231 additions and 133960 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -11,18 +11,26 @@
- Made the integrated PBR resource pack
- Wrote all desktop emulation code
- Wrote EaglercraftXBungee
- Wrote WebRTC Relay Server
- Wrote WebRTC relay server
- Wrote voice chat server
- Wrote the patch and build system
ayunami2000:
- Many bug fixes
- WebRTC LAN worlds
- WebRTC voice chat
- Added resource packs
- Added screen recording
- Added seamless fullscreen
- Created the replit
hoosiertransfer:
- Many memory optimizations
- Bug fixes
- Faster lighting engine
Code used within EaglercraftX

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 859 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1007 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 B

View File

@ -18,7 +18,7 @@ gui.all=All
eaglercraft.recording.unsupported=Recording Unsupported!
eaglercraft.recording.stop=Stop Recording
eaglercraft.recording.start=Record Screen...
eaglercraft.soundCategory.voice=Voice
eaglercraft.soundCategory.voice=Recording Voice
eaglercraft.resourcePack.prompt.title=What do you want to do with '%s'?
eaglercraft.resourcePack.prompt.text=Tip: Hold Shift to skip this screen when selecting a resource pack!
@ -43,6 +43,14 @@ eaglercraft.editProfile.username=Username
eaglercraft.editProfile.playerSkin=Player Skin
eaglercraft.editProfile.addSkin=Add Skin
eaglercraft.editProfile.clearSkin=Clear List
eaglercraft.editProfile.capes=Capes
eaglercraft.editProfile.disableFNAW=(Note: go to 'Options...' > 'Skin Customization' to disable FNAW skins)
eaglercraft.editProfile.enableFNAW=(Note: go to 'Options...' > 'Skin Customization' to enable FNAW skins)
eaglercraft.editCape.title=Edit Cape
eaglercraft.editCape.playerCape=Player Cape
eaglercraft.editCape.addCape=Add Cape
eaglercraft.editCape.clearCape=Clear List
eaglercraft.editProfile.importExport=Import/Export
@ -599,6 +607,60 @@ eaglercraft.updateList.refresh=Refresh
eaglercraft.updateList.note.0=Note: Updates are digitally signed, EaglercraftX will block any
eaglercraft.updateList.note.1=updates that were not created by lax1dude or ayunami2000
eaglercraft.voice.title=Voice Channel
eaglercraft.voice.titleNoVoice=Voice is disabled on this server
eaglercraft.voice.titleVoiceUnavailable=Voice is unavailable
eaglercraft.voice.titleVoiceBrowserError=(browser issue)
eaglercraft.voice.ptt=Press '%s' to speak
eaglercraft.voice.pttChangeDesc=(Press Any Key)
eaglercraft.voice.changeKey=Change
eaglercraft.voice.off=OFF
eaglercraft.voice.radius=NEARBY
eaglercraft.voice.global=GLOBAL
eaglercraft.voice.volumeTitle=Change Volume
eaglercraft.voice.volumeListen=Speakers Volume:
eaglercraft.voice.volumeSpeak=Microphone Volume:
eaglercraft.voice.radiusTitle=Change Listener Radius
eaglercraft.voice.radiusLabel=Players Within:
eaglercraft.voice.radiusChange=change
eaglercraft.voice.notConnected=Not Connected
eaglercraft.voice.connecting=Connecting...
eaglercraft.voice.unavailable=Could not connect!
eaglercraft.voice.connectedGlobal=Connected - Global
eaglercraft.voice.connectedRadius=Connected - $f$Within $radius$m
eaglercraft.voice.playersListening=Players Listening:
eaglercraft.voice.muted=Players Muted:
eaglercraft.voice.unmute=unmute
eaglercraft.voice.mute=mute
eaglercraft.voice.apply=Apply
eaglercraft.voice.volumeSpeakerLabel=Speakers:
eaglercraft.voice.volumeMicrophoneLabel=Microphone:
eaglercraft.voice.unsupportedWarning1=Voice Warning
eaglercraft.voice.unsupportedWarning2=Your network's firewall may not support
eaglercraft.voice.unsupportedWarning3=eaglercraft's voice chat.
eaglercraft.voice.unsupportedWarning4=If your game doesn't work it's your issue
eaglercraft.voice.unsupportedWarning5=to solve, not ayunami2000's or lax1dude's.
eaglercraft.voice.unsupportedWarning6=Don't ask them to 'fix' it for you because
eaglercraft.voice.unsupportedWarning7=they won't help you fix a problem that only
eaglercraft.voice.unsupportedWarning8=you or your network's administrator has the
eaglercraft.voice.unsupportedWarning9=ability to correctly resolve.
eaglercraft.voice.unsupportedWarning10=Continue
eaglercraft.voice.unsupportedWarning11=Cancel
eaglercraft.voice.ipGrabWarning1=IP Logger Warning
eaglercraft.voice.ipGrabWarning2=Using Eaglercraft voice chat may allow your
eaglercraft.voice.ipGrabWarning3=IP address to be logged by other players
eaglercraft.voice.ipGrabWarning4=also using voice on the server.
eaglercraft.voice.ipGrabWarning5=This issue will not be fixed, it is an
eaglercraft.voice.ipGrabWarning6=internal browser issue, not a mistake in the
eaglercraft.voice.ipGrabWarning7=game. Fortunately, this can only be done if
eaglercraft.voice.ipGrabWarning8=the other player uses a hacked web browser
eaglercraft.voice.ipGrabWarning9=or has Wireshark to capture the voice
eaglercraft.voice.ipGrabWarning10=packets, as there exists no real javascript
eaglercraft.voice.ipGrabWarning11=method to log IPs using a normal skidded
eaglercraft.voice.ipGrabWarning12=eaglercraft hacked client.
selectServer.title=Select Server
selectServer.empty=empty
selectServer.select=Join Server
@ -799,6 +861,7 @@ options.chat.height.focused=Focused Height
options.chat.height.unfocused=Unfocused Height
options.skinCustomisation=Skin Customization...
options.skinCustomisation.title=Skin Customization
options.skinCustomisation.enableFNAWSkins=Show FNAW Skins
options.modelPart.cape=Cape
options.modelPart.hat=Hat
options.modelPart.jacket=Jacket

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -60,6 +60,9 @@ public class PlatformAssets {
public static final ImageData loadImageFile(InputStream data) {
try {
BufferedImage img = ImageIO.read(data);
if(img == null) {
throw new IOException("Data is not a supported image format!");
}
int w = img.getWidth();
int h = img.getHeight();
boolean a = img.getColorModel().hasAlpha();

View File

@ -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) {

View File

@ -1,13 +1,11 @@
package net.lax1dude.eaglercraft.v1_8.internal;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.vfs2.EaglerFileSystemException;
import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFSIterator2.BreakLoop;
import net.lax1dude.eaglercraft.v1_8.internal.lwjgl.DebugFilesystem;
import net.lax1dude.eaglercraft.v1_8.internal.lwjgl.JDBCFilesystem;
import net.lax1dude.eaglercraft.v1_8.internal.lwjgl.JDBCFilesystemConverter;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
@ -30,183 +28,104 @@ public class PlatformFilesystem {
public static final Logger logger = LogManager.getLogger("PlatformFilesystem");
public static final File filesystemRoot = (new File("filesystem/sp")).getAbsoluteFile();
public static final File debugFilesystemRoot = (new File("filesystem/sp")).getAbsoluteFile();
private static IFilesystemProvider provider = null;
public static String jdbcUri = null;
public static String jdbcDriver = null;
public static void initialize() {
if(!filesystemRoot.isDirectory() && !filesystemRoot.mkdirs()) {
throw new EaglerFileSystemException("Could not create directory for virtual filesystem: " + filesystemRoot.getAbsolutePath());
if(provider == null) {
if(jdbcUri != null && jdbcDriver != null) {
provider = JDBCFilesystem.initialize(jdbcUri, jdbcDriver);
if(((JDBCFilesystem)provider).isNewFilesystem() && debugFilesystemRoot.isDirectory() && debugFilesystemRoot.list().length > 0) {
JDBCFilesystemConverter.convertFilesystem("Converting filesystem, please wait...", debugFilesystemRoot, provider, true);
}
}else {
provider = DebugFilesystem.initialize(debugFilesystemRoot);
}
}
}
public static void setUseJDBC(String uri) {
jdbcUri = uri;
}
public static void setJDBCDriverClass(String driver) {
jdbcDriver = driver;
}
public static interface IFilesystemProvider {
boolean eaglerDelete(String pathName);
ByteBuffer eaglerRead(String pathName);
void eaglerWrite(String pathName, ByteBuffer data);
boolean eaglerExists(String pathName);
boolean eaglerMove(String pathNameOld, String pathNameNew);
int eaglerCopy(String pathNameOld, String pathNameNew);
int eaglerSize(String pathName);
void eaglerIterate(String pathName, VFSFilenameIterator itr, boolean recursive);
}
private static void throwNotInitialized() {
throw new UnsupportedOperationException("Filesystem has not been initialized!");
}
public static boolean eaglerDelete(String pathName) {
File f = getJREFile(pathName);
if(!f.exists()) {
logger.warn("Tried to delete file that doesn't exist: \"{}\"", pathName);
return false;
}
if(f.delete()) {
deleteParentIfEmpty(f);
return true;
}
return false;
if(provider == null) throwNotInitialized();
return provider.eaglerDelete(pathName);
}
public static ByteBuffer eaglerRead(String pathName) {
File f = getJREFile(pathName);
if(f.isFile()) {
long fileSize = f.length();
if(fileSize > 2147483647L) throw new EaglerFileSystemException("Too large: " + fileSize + " @ " + f.getAbsolutePath());
ByteBuffer buf = PlatformRuntime.allocateByteBuffer((int)fileSize);
try(FileInputStream is = new FileInputStream(f)) {
byte[] copyBuffer = new byte[4096];
int i;
while((i = is.read(copyBuffer, 0, copyBuffer.length)) != -1) {
buf.put(copyBuffer, 0, i);
}
if(buf.remaining() > 0) {
throw new EaglerFileSystemException("ERROR: " + buf.remaining() + " bytes are remaining after reading: " + f.getAbsolutePath());
}
buf.flip();
ByteBuffer tmp = buf;
buf = null;
return tmp;
}catch (IOException e) {
throw new EaglerFileSystemException("Failed to read: " + f.getAbsolutePath(), e);
}catch(ArrayIndexOutOfBoundsException ex) {
throw new EaglerFileSystemException("ERROR: Expected " + fileSize + " bytes, buffer overflow reading: " + f.getAbsolutePath(), ex);
}finally {
if(buf != null) {
PlatformRuntime.freeByteBuffer(buf);
}
}
}else {
logger.warn("Tried to read file that doesn't exist: \"{}\"", f.getAbsolutePath());
return null;
}
if(provider == null) throwNotInitialized();
return provider.eaglerRead(pathName);
}
public static void eaglerWrite(String pathName, ByteBuffer data) {
File f = getJREFile(pathName);
File p = f.getParentFile();
if(!p.isDirectory()) {
if(!p.mkdirs()) {
throw new EaglerFileSystemException("Could not create parent directory: " + p.getAbsolutePath());
}
}
try(FileOutputStream fos = new FileOutputStream(f)) {
byte[] copyBuffer = new byte[Math.min(4096, data.remaining())];
int i;
while((i = data.remaining()) > 0) {
if(i > copyBuffer.length) {
i = copyBuffer.length;
}
data.get(copyBuffer, 0, i);
fos.write(copyBuffer, 0, i);
}
}catch (IOException e) {
throw new EaglerFileSystemException("Failed to write: " + f.getAbsolutePath(), e);
}
if(provider == null) throwNotInitialized();
provider.eaglerWrite(pathName, data);
}
public static boolean eaglerExists(String pathName) {
return getJREFile(pathName).isFile();
if(provider == null) throwNotInitialized();
return provider.eaglerExists(pathName);
}
public static boolean eaglerMove(String pathNameOld, String pathNameNew) {
File f1 = getJREFile(pathNameOld);
File f2 = getJREFile(pathNameNew);
if(f2.exists()) {
logger.warn("Tried to rename file \"{}\" to \"{}\" which already exists! File will be replaced");
if(!f2.delete()) {
return false;
}
}
if(f1.renameTo(f2)) {
deleteParentIfEmpty(f1);
return true;
}
return false;
if(provider == null) throwNotInitialized();
return provider.eaglerMove(pathNameOld, pathNameNew);
}
public static int eaglerCopy(String pathNameOld, String pathNameNew) {
File f1 = getJREFile(pathNameOld);
File f2 = getJREFile(pathNameNew);
if(!f1.isFile()) {
return -1;
}
if(f2.isDirectory()) {
throw new EaglerFileSystemException("Destination file is a directory: " + f2.getAbsolutePath());
}
File p = f2.getParentFile();
if(!p.isDirectory()) {
if(!p.mkdirs()) {
throw new EaglerFileSystemException("Could not create parent directory: " + p.getAbsolutePath());
}
}
int sz = 0;
try(FileInputStream is = new FileInputStream(f1)) {
try(FileOutputStream os = new FileOutputStream(f2)) {
byte[] copyBuffer = new byte[4096];
int i;
while((i = is.read(copyBuffer, 0, copyBuffer.length)) != -1) {
os.write(copyBuffer, 0, i);
sz += i;
}
}
}catch (IOException e) {
throw new EaglerFileSystemException("Failed to copy \"" + f1.getAbsolutePath() + "\" to file \"" + f2.getAbsolutePath() + "\"", e);
}
return sz;
if(provider == null) throwNotInitialized();
return provider.eaglerCopy(pathNameOld, pathNameNew);
}
public static int eaglerSize(String pathName) {
File f = getJREFile(pathName);
if(f.isFile()) {
long fileSize = f.length();
if(fileSize > 2147483647L) throw new EaglerFileSystemException("Too large: " + fileSize + " @ " + f.getAbsolutePath());
return (int)fileSize;
}else {
return -1;
}
if(provider == null) throwNotInitialized();
return provider.eaglerSize(pathName);
}
public static void eaglerIterate(String pathName, VFSFilenameIterator itr, boolean recursive) {
try {
iterateFile(pathName, getJREFile(pathName), itr, recursive);
}catch(BreakLoop ex) {
}
if(provider == null) throwNotInitialized();
provider.eaglerIterate(pathName, itr, recursive);
}
private static void iterateFile(String pathName, File f, VFSFilenameIterator itr, boolean recursive) {
if(!f.exists()) {
return;
}
if(!f.isDirectory()) {
itr.next(pathName);
return;
}
File[] fa = f.listFiles();
for(int i = 0; i < fa.length; ++i) {
File ff = fa[i];
String fn = pathName + "/" + ff.getName();
if(ff.isDirectory()) {
if(recursive) {
iterateFile(fn, ff, itr, true);
}
}else {
itr.next(fn);
public static void platformShutdown() {
if(provider != null) {
if(provider instanceof JDBCFilesystem) {
((JDBCFilesystem)provider).shutdown();
}
}
}
private static File getJREFile(String path) {
return new File(filesystemRoot, path);
}
private static void deleteParentIfEmpty(File f) {
String[] s;
while((f = f.getParentFile()) != null && (s = f.list()) != null && s.length == 0) {
f.delete();
provider = null;
}
}
}

View File

@ -57,7 +57,10 @@ public class PlatformInput {
public static boolean lockKeys = false;
private static final List<Character> keyboardCharList = new LinkedList();
private static boolean vsync = true;
private static boolean glfwVSyncState = false;
private static class KeyboardEvent {
protected final int key;
@ -214,8 +217,16 @@ public class PlatformInput {
return glfwWindowShouldClose(win);
}
public static void setVSync(boolean enable) {
vsync = enable;
}
public static void update() {
glfwPollEvents();
if(vsync != glfwVSyncState) {
glfwSwapInterval(vsync ? 1 : 0);
glfwVSyncState = vsync;
}
glfwSwapBuffers(win);
}

View File

@ -7,6 +7,8 @@ import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer;
import static org.lwjgl.opengles.GLES30.*;
import org.lwjgl.opengles.GLESCapabilities;
/**
* Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved.
*
@ -24,6 +26,12 @@ import static org.lwjgl.opengles.GLES30.*;
*/
public class PlatformOpenGL {
private static boolean hasLinearHDR32FSupport = false;
static void setCurrentContext(GLESCapabilities caps) {
hasLinearHDR32FSupport = caps.GL_OES_texture_float_linear;
}
public static final void _wglEnable(int glEnum) {
glEnable(glEnum);
}
@ -269,6 +277,12 @@ public class PlatformOpenGL {
data == null ? 0l : EaglerLWJGLAllocator.getAddress(data));
}
public static final void _wglTexImage2Df32(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 _wglTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height,
int format, int type, ByteBuffer data) {
nglTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
@ -523,4 +537,7 @@ public class PlatformOpenGL {
return true;
}
public static final boolean checkLinearHDR32FSupport() {
return hasLinearHDR32FSupport;
}
}

View File

@ -171,7 +171,7 @@ public class PlatformRuntime {
EGL.createDisplayCapabilities(glfw_eglHandle, major[0], minor[0]);
glfwMakeContextCurrent(windowHandle);
GLES.createCapabilities();
PlatformOpenGL.setCurrentContext(GLES.createCapabilities());
logger.info("OpenGL Version: {}", (glVersion = GLES30.glGetString(GLES30.GL_VERSION)));
logger.info("OpenGL Renderer: {}", (glRenderer = GLES30.glGetString(GLES30.GL_RENDERER)));
@ -245,6 +245,7 @@ public class PlatformRuntime {
public static void destroy() {
PlatformAudio.platformShutdown();
PlatformFilesystem.platformShutdown();
GLES.destroy();
EGL.destroy();
glfwDestroyWindow(windowHandle);
@ -340,15 +341,27 @@ public class PlatformRuntime {
public static class NativeNIO {
public static java.nio.ByteBuffer allocateByteBuffer(int length) {
return MemoryUtil.memByteBuffer(JEmalloc.nje_malloc(length), length);
long ret = JEmalloc.nje_malloc(length);
if(ret == 0l) {
throw new OutOfMemoryError("Native je_malloc call returned null pointer!");
}
return MemoryUtil.memByteBuffer(ret, length);
}
public static java.nio.IntBuffer allocateIntBuffer(int length) {
return MemoryUtil.memIntBuffer(JEmalloc.nje_malloc(length << 2), length);
long ret = JEmalloc.nje_malloc(length << 2);
if(ret == 0l) {
throw new OutOfMemoryError("Native je_malloc call returned null pointer!");
}
return MemoryUtil.memIntBuffer(ret, length);
}
public static java.nio.FloatBuffer allocateFloatBuffer(int length) {
return MemoryUtil.memFloatBuffer(JEmalloc.nje_malloc(length << 2), length);
long ret = JEmalloc.nje_malloc(length << 2);
if(ret == 0l) {
throw new OutOfMemoryError("Native je_malloc call returned null pointer!");
}
return MemoryUtil.memFloatBuffer(ret, length);
}
public static java.nio.IntBuffer getIntBuffer(java.nio.ByteBuffer byteBuffer) {

View File

@ -0,0 +1,116 @@
package net.lax1dude.eaglercraft.v1_8.internal;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelPeerState;
import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelReadyState;
/**
* 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 {
public static void initialize() {
}
public static void initializeDevices() {
}
public static boolean isSupported() {
return false;
}
public static void setVoiceListenVolume(float f) {
}
public static void setVoiceSpeakVolume(float f) {
}
public static void activateVoice(boolean talk) {
}
public static void setICEServers(String[] servs) {
}
public static void signalConnect(EaglercraftUUID user, boolean offer) {
}
public static void signalDisconnect(EaglercraftUUID user, boolean b) {
}
public static void signalICECandidate(EaglercraftUUID user, String ice) {
}
public static void signalDescription(EaglercraftUUID user, String desc) {
}
public static void tickVoiceClient() {
}
public static void updateVoicePosition(EaglercraftUUID uuid, double x, double y, double z) {
}
public static void resetPeerStates() {
}
public static void setVoiceProximity(int prox) {
}
public static void setMicVolume(float f) {
}
public static void mutePeer(EaglercraftUUID uuid, boolean mute) {
}
public static EnumVoiceChannelPeerState getPeerState() {
return EnumVoiceChannelPeerState.LOADING;
}
public static EnumVoiceChannelReadyState getReadyState() {
return EnumVoiceChannelReadyState.NONE;
}
public static EnumVoiceChannelPeerState getPeerStateConnect() {
return EnumVoiceChannelPeerState.LOADING;
}
public static EnumVoiceChannelPeerState getPeerStateInitial() {
return EnumVoiceChannelPeerState.LOADING;
}
public static EnumVoiceChannelPeerState getPeerStateDesc() {
return EnumVoiceChannelPeerState.LOADING;
}
public static EnumVoiceChannelPeerState getPeerStateIce() {
return EnumVoiceChannelPeerState.LOADING;
}
}

View File

@ -3,7 +3,7 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer;
import org.lwjgl.system.jemalloc.JEmalloc;
/**
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
* Copyright (c) 2022-2024 lax1dude. 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
@ -26,19 +26,35 @@ public class EaglerLWJGLAllocator {
}
public static ByteBuffer allocByteBuffer(int len) {
return new EaglerLWJGLByteBuffer(JEmalloc.nje_malloc(len), len, true);
long ret = JEmalloc.nje_malloc(len);
if(ret == 0l) {
throw new OutOfMemoryError("Native je_malloc call returned null pointer!");
}
return new EaglerLWJGLByteBuffer(ret, len, true);
}
public static ShortBuffer allocShortBuffer(int len) {
return new EaglerLWJGLShortBuffer(JEmalloc.nje_malloc(len << 1), len, true);
long ret = JEmalloc.nje_malloc(len << 1);
if(ret == 0l) {
throw new OutOfMemoryError("Native je_malloc call returned null pointer!");
}
return new EaglerLWJGLShortBuffer(ret, len, true);
}
public static IntBuffer allocIntBuffer(int len) {
return new EaglerLWJGLIntBuffer(JEmalloc.nje_malloc(len << 2), len, true);
long ret = JEmalloc.nje_malloc(len << 2);
if(ret == 0l) {
throw new OutOfMemoryError("Native je_malloc call returned null pointer!");
}
return new EaglerLWJGLIntBuffer(ret, len, true);
}
public static FloatBuffer allocFloatBuffer(int len) {
return new EaglerLWJGLFloatBuffer(JEmalloc.nje_malloc(len << 2), len, true);
long ret = JEmalloc.nje_malloc(len << 2);
if(ret == 0l) {
throw new OutOfMemoryError("Native je_malloc call returned null pointer!");
}
return new EaglerLWJGLFloatBuffer(ret, len, true);
}
public static void freeByteBuffer(ByteBuffer buffer) {

View File

@ -1,10 +1,12 @@
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.jemalloc.JEmalloc;
import net.lax1dude.unsafememcpy.UnsafeMemcpy;
import net.lax1dude.unsafememcpy.UnsafeUtils;
/**
* Copyright (c) 2022 lax1dude. All Rights Reserved.
* Copyright (c) 2022-2024 lax1dude. 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
@ -18,7 +20,7 @@ import org.lwjgl.system.jemalloc.JEmalloc;
* POSSIBILITY OF SUCH DAMAGE.
*
*/
public class EaglerLWJGLByteBuffer implements ByteBuffer {
public class EaglerLWJGLFloatBuffer implements FloatBuffer {
final long address;
final boolean original;
@ -28,11 +30,13 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
private int limit;
private int mark;
EaglerLWJGLByteBuffer(long address, int capacity, boolean original) {
private static final int SHIFT = 2;
EaglerLWJGLFloatBuffer(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) {
EaglerLWJGLFloatBuffer(long address, int capacity, int position, int limit, int mark, boolean original) {
this.address = address;
this.capacity = capacity;
this.position = position;
@ -40,7 +44,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
this.mark = mark;
this.original = original;
}
@Override
public int capacity() {
return capacity;
@ -82,85 +86,93 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
}
@Override
public boolean isDirect() {
return true;
public int arrayOffset() {
return position;
}
@Override
public ByteBuffer slice() {
return new EaglerLWJGLByteBuffer(address + position, limit - position, false);
public FloatBuffer slice() {
return new EaglerLWJGLFloatBuffer(address + (position << SHIFT), limit - position, false);
}
@Override
public ByteBuffer duplicate() {
return new EaglerLWJGLByteBuffer(address, capacity, position, limit, mark, false);
public FloatBuffer duplicate() {
return new EaglerLWJGLFloatBuffer(address, capacity, position, limit, mark, false);
}
@Override
public ByteBuffer asReadOnlyBuffer() {
return new EaglerLWJGLByteBuffer(address, capacity, position, limit, mark, false);
public FloatBuffer asReadOnlyBuffer() {
return new EaglerLWJGLFloatBuffer(address, capacity, position, limit, mark, false);
}
@Override
public byte get() {
public float get() {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
return MemoryUtil.memGetByte(address + position++);
return UnsafeUtils.getMemFloat(address + ((position++) << SHIFT));
}
@Override
public ByteBuffer put(byte b) {
public FloatBuffer put(float b) {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutByte(address + position++, b);
UnsafeUtils.setMemFloat(address + ((position++) << SHIFT), b);
return this;
}
@Override
public byte get(int index) {
public float get(int index) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetByte(address + index);
return UnsafeUtils.getMemFloat(address + (index << SHIFT));
}
@Override
public ByteBuffer put(int index, byte b) {
public FloatBuffer put(int index, float b) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutByte(address + index, b);
UnsafeUtils.setMemFloat(address + (index << SHIFT), b);
return this;
}
@Override
public ByteBuffer get(byte[] dst, int offset, int length) {
public float getElement(int index) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
return UnsafeUtils.getMemFloat(address + (index << SHIFT));
}
@Override
public void putElement(int index, float value) {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
UnsafeUtils.setMemFloat(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.memGetByte(address + position + i);
}
UnsafeMemcpy.memcpyAlignDst(dst, offset << SHIFT, address + (position << SHIFT), length);
position += length;
return this;
}
@Override
public ByteBuffer get(byte[] dst) {
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[position + i] = MemoryUtil.memGetByte(address + position + i);
}
UnsafeMemcpy.memcpyAlignDst(dst, 0, address + (position << SHIFT), dst.length);
position += dst.length;
return this;
}
@Override
public ByteBuffer put(ByteBuffer src) {
if(src instanceof EaglerLWJGLByteBuffer) {
EaglerLWJGLByteBuffer c = (EaglerLWJGLByteBuffer)src;
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, address + position, l);
UnsafeMemcpy.memcpy(address + (position << SHIFT), c.address + (c.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.memPutByte(address + position + l, src.get());
UnsafeUtils.setMemFloat(address + ((position + l) << SHIFT), src.get());
}
position += l;
}
@ -168,214 +180,58 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
}
@Override
public ByteBuffer put(byte[] src, int offset, int length) {
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.memPutByte(address + position + i, src[offset + i]);
}
UnsafeMemcpy.memcpyAlignSrc(address + (position << SHIFT), src, offset << SHIFT, length);
position += length;
return this;
}
@Override
public ByteBuffer put(byte[] src) {
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.memPutByte(address + position + i, src[i]);
}
UnsafeMemcpy.memcpyAlignSrc(address + (position << SHIFT), src, 0, src.length);
position += src.length;
return this;
}
@Override
public int arrayOffset() {
public int getArrayOffset() {
return position;
}
@Override
public ByteBuffer compact() {
public FloatBuffer compact() {
if(limit > capacity) throw new ArrayIndexOutOfBoundsException(limit);
if(position > limit) throw new ArrayIndexOutOfBoundsException(position);
if(position == limit) {
return new EaglerLWJGLByteBuffer(0l, 0, false);
return new EaglerLWJGLFloatBuffer(0l, 0, false);
}
int newLen = limit - position;
long newAlloc = JEmalloc.nje_malloc(newLen);
MemoryUtil.memCopy(address + position, newAlloc, newLen);
if(newAlloc == 0l) {
throw new OutOfMemoryError("Native je_malloc call returned null pointer!");
}
UnsafeMemcpy.memcpy(newAlloc, address + (position << SHIFT), newLen << SHIFT);
return new EaglerLWJGLByteBuffer(newAlloc, newLen, true);
return new EaglerLWJGLFloatBuffer(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;
public boolean isDirect() {
return true;
}
@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() {
public FloatBuffer mark() {
mark = position;
return this;
}
@Override
public ByteBuffer reset() {
public FloatBuffer reset() {
int m = mark;
if(m < 0) throw new ArrayIndexOutOfBoundsException("Invalid mark: " + m);
position = m;
@ -383,7 +239,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
}
@Override
public ByteBuffer clear() {
public FloatBuffer clear() {
position = 0;
limit = capacity;
mark = -1;
@ -391,7 +247,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
}
@Override
public ByteBuffer flip() {
public FloatBuffer flip() {
limit = position;
position = 0;
mark = -1;
@ -399,21 +255,21 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
}
@Override
public ByteBuffer rewind() {
public FloatBuffer rewind() {
position = 0;
mark = -1;
return this;
}
@Override
public ByteBuffer limit(int newLimit) {
public FloatBuffer limit(int newLimit) {
if(newLimit < 0 || newLimit > capacity) throw new ArrayIndexOutOfBoundsException(newLimit);
limit = newLimit;
return this;
}
@Override
public ByteBuffer position(int newPosition) {
public FloatBuffer position(int newPosition) {
if(newPosition < 0 || newPosition > limit) throw new ArrayIndexOutOfBoundsException(newPosition);
position = newPosition;
return this;

View File

@ -1,10 +1,12 @@
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.jemalloc.JEmalloc;
import net.lax1dude.unsafememcpy.UnsafeMemcpy;
import net.lax1dude.unsafememcpy.UnsafeUtils;
/**
* Copyright (c) 2022 lax1dude. All Rights Reserved.
* Copyright (c) 2022-2024 lax1dude. 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
@ -18,8 +20,8 @@ import org.lwjgl.system.jemalloc.JEmalloc;
* POSSIBILITY OF SUCH DAMAGE.
*
*/
public class EaglerLWJGLFloatBuffer implements FloatBuffer {
public class EaglerLWJGLIntBuffer implements IntBuffer {
final long address;
final boolean original;
@ -30,11 +32,11 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer {
private static final int SHIFT = 2;
EaglerLWJGLFloatBuffer(long address, int capacity, boolean original) {
EaglerLWJGLIntBuffer(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) {
EaglerLWJGLIntBuffer(long address, int capacity, int position, int limit, int mark, boolean original) {
this.address = address;
this.capacity = capacity;
this.position = position;
@ -89,92 +91,88 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer {
}
@Override
public FloatBuffer slice() {
return new EaglerLWJGLFloatBuffer(address + (position << SHIFT), limit - position, false);
public IntBuffer slice() {
return new EaglerLWJGLIntBuffer(address + (position << SHIFT), limit - position, false);
}
@Override
public FloatBuffer duplicate() {
return new EaglerLWJGLFloatBuffer(address, capacity, position, limit, mark, false);
public IntBuffer duplicate() {
return new EaglerLWJGLIntBuffer(address, capacity, position, limit, mark, false);
}
@Override
public FloatBuffer asReadOnlyBuffer() {
return new EaglerLWJGLFloatBuffer(address, capacity, position, limit, mark, false);
public IntBuffer asReadOnlyBuffer() {
return new EaglerLWJGLIntBuffer(address, capacity, position, limit, mark, false);
}
@Override
public float get() {
public int get() {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
return MemoryUtil.memGetFloat(address + ((position++) << SHIFT));
return UnsafeUtils.getMemInt(address + ((position++) << SHIFT));
}
@Override
public FloatBuffer put(float b) {
public IntBuffer put(int b) {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutFloat(address + ((position++) << SHIFT), b);
UnsafeUtils.setMemInt(address + ((position++) << SHIFT), b);
return this;
}
@Override
public float get(int index) {
public int get(int index) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetFloat(address + (index << SHIFT));
return UnsafeUtils.getMemInt(address + (index << SHIFT));
}
@Override
public FloatBuffer put(int index, float b) {
public IntBuffer put(int index, int b) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutFloat(address + (index << SHIFT), b);
UnsafeUtils.setMemInt(address + (index << SHIFT), b);
return this;
}
@Override
public float getElement(int index) {
public int getElement(int index) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetFloat(address + (index << SHIFT));
return UnsafeUtils.getMemInt(address + (index << SHIFT));
}
@Override
public void putElement(int index, float value) {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutFloat(address + ((position++) << SHIFT), value);
public void putElement(int index, int value) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
UnsafeUtils.setMemInt(address + (index << SHIFT), value);
}
@Override
public FloatBuffer get(float[] dst, int offset, int length) {
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.memGetFloat(address + ((position + i) << SHIFT));
}
UnsafeMemcpy.memcpyAlignDst(dst, offset << SHIFT, address + (position << SHIFT), length);
position += length;
return this;
}
@Override
public FloatBuffer get(float[] dst) {
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.memGetFloat(address + ((position + i) << SHIFT));
}
UnsafeMemcpy.memcpyAlignDst(dst, 0, address + (position << SHIFT), dst.length);
position += dst.length;
return this;
}
@Override
public FloatBuffer put(FloatBuffer src) {
if(src instanceof EaglerLWJGLFloatBuffer) {
EaglerLWJGLFloatBuffer c = (EaglerLWJGLFloatBuffer)src;
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);
UnsafeMemcpy.memcpy(address + (position << SHIFT), c.address + (c.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());
UnsafeUtils.setMemInt(address + ((position + l) << SHIFT), src.get());
}
position += l;
}
@ -182,21 +180,17 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer {
}
@Override
public FloatBuffer put(float[] src, int offset, int length) {
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.memPutFloat(address + ((position + i) << SHIFT), src[offset + i]);
}
UnsafeMemcpy.memcpyAlignSrc(address + (position << SHIFT), src, offset << SHIFT, length);
position += length;
return this;
}
@Override
public FloatBuffer put(float[] src) {
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.memPutFloat(address + ((position + i) << SHIFT), src[i]);
}
UnsafeMemcpy.memcpyAlignSrc(address + (position << SHIFT), src, 0, src.length);
position += src.length;
return this;
}
@ -207,19 +201,22 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer {
}
@Override
public FloatBuffer compact() {
public IntBuffer compact() {
if(limit > capacity) throw new ArrayIndexOutOfBoundsException(limit);
if(position > limit) throw new ArrayIndexOutOfBoundsException(position);
if(position == limit) {
return new EaglerLWJGLFloatBuffer(0l, 0, false);
return new EaglerLWJGLIntBuffer(0l, 0, false);
}
int newLen = limit - position;
long newAlloc = JEmalloc.nje_malloc(newLen);
MemoryUtil.memCopy(address + (position << SHIFT), newAlloc, newLen << SHIFT);
if(newAlloc == 0l) {
throw new OutOfMemoryError("Native je_malloc call returned null pointer!");
}
UnsafeMemcpy.memcpy(newAlloc, address + (position << SHIFT), newLen << SHIFT);
return new EaglerLWJGLFloatBuffer(newAlloc, newLen, true);
return new EaglerLWJGLIntBuffer(newAlloc, newLen, true);
}
@Override
@ -228,13 +225,13 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer {
}
@Override
public FloatBuffer mark() {
public IntBuffer mark() {
mark = position;
return this;
}
@Override
public FloatBuffer reset() {
public IntBuffer reset() {
int m = mark;
if(m < 0) throw new ArrayIndexOutOfBoundsException("Invalid mark: " + m);
position = m;
@ -242,7 +239,7 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer {
}
@Override
public FloatBuffer clear() {
public IntBuffer clear() {
position = 0;
limit = capacity;
mark = -1;
@ -250,7 +247,7 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer {
}
@Override
public FloatBuffer flip() {
public IntBuffer flip() {
limit = position;
position = 0;
mark = -1;
@ -258,21 +255,21 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer {
}
@Override
public FloatBuffer rewind() {
public IntBuffer rewind() {
position = 0;
mark = -1;
return this;
}
@Override
public FloatBuffer limit(int newLimit) {
public IntBuffer limit(int newLimit) {
if(newLimit < 0 || newLimit > capacity) throw new ArrayIndexOutOfBoundsException(newLimit);
limit = newLimit;
return this;
}
@Override
public FloatBuffer position(int newPosition) {
public IntBuffer position(int newPosition) {
if(newPosition < 0 || newPosition > limit) throw new ArrayIndexOutOfBoundsException(newPosition);
position = newPosition;
return this;

View File

@ -1,10 +1,12 @@
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.jemalloc.JEmalloc;
import net.lax1dude.unsafememcpy.UnsafeMemcpy;
import net.lax1dude.unsafememcpy.UnsafeUtils;
/**
* Copyright (c) 2022 lax1dude. All Rights Reserved.
* Copyright (c) 2022-2024 lax1dude. 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
@ -106,47 +108,45 @@ public class EaglerLWJGLIntBuffer implements IntBuffer {
@Override
public int get() {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
return MemoryUtil.memGetInt(address + ((position++) << SHIFT));
return UnsafeUtils.getMemInt(address + ((position++) << SHIFT));
}
@Override
public IntBuffer put(int b) {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutInt(address + ((position++) << SHIFT), b);
UnsafeUtils.setMemInt(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));
return UnsafeUtils.getMemInt(address + (index << SHIFT));
}
@Override
public IntBuffer put(int index, int b) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutInt(address + (index << SHIFT), b);
UnsafeUtils.setMemInt(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));
return UnsafeUtils.getMemInt(address + (index << SHIFT));
}
@Override
public void putElement(int index, int value) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutInt(address + (index << SHIFT), value);
UnsafeUtils.setMemInt(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));
}
UnsafeMemcpy.memcpyAlignDst(dst, offset << SHIFT, address + (position << SHIFT), length);
position += length;
return this;
}
@ -154,9 +154,7 @@ public class EaglerLWJGLIntBuffer 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] = MemoryUtil.memGetInt(address + ((position + i) << SHIFT));
}
UnsafeMemcpy.memcpyAlignDst(dst, 0, address + (position << SHIFT), dst.length);
position += dst.length;
return this;
}
@ -167,14 +165,14 @@ public class EaglerLWJGLIntBuffer implements IntBuffer {
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);
UnsafeMemcpy.memcpy(address + (position << SHIFT), c.address + (c.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());
UnsafeUtils.setMemInt(address + ((position + l) << SHIFT), src.get());
}
position += l;
}
@ -184,9 +182,7 @@ public class EaglerLWJGLIntBuffer 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) {
MemoryUtil.memPutInt(address + ((position + i) << SHIFT), src[offset + i]);
}
UnsafeMemcpy.memcpyAlignSrc(address + (position << SHIFT), src, offset << SHIFT, length);
position += length;
return this;
}
@ -194,9 +190,7 @@ public class EaglerLWJGLIntBuffer 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) {
MemoryUtil.memPutInt(address + ((position + i) << SHIFT), src[i]);
}
UnsafeMemcpy.memcpyAlignSrc(address + (position << SHIFT), src, 0, src.length);
position += src.length;
return this;
}
@ -217,7 +211,10 @@ public class EaglerLWJGLIntBuffer implements IntBuffer {
int newLen = limit - position;
long newAlloc = JEmalloc.nje_malloc(newLen);
MemoryUtil.memCopy(address + (position << SHIFT), newAlloc, newLen << SHIFT);
if(newAlloc == 0l) {
throw new OutOfMemoryError("Native je_malloc call returned null pointer!");
}
UnsafeMemcpy.memcpy(newAlloc, address + (position << SHIFT), newLen << SHIFT);
return new EaglerLWJGLIntBuffer(newAlloc, newLen, true);
}

View File

@ -1,10 +1,12 @@
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.jemalloc.JEmalloc;
import net.lax1dude.unsafememcpy.UnsafeMemcpy;
import net.lax1dude.unsafememcpy.UnsafeUtils;
/**
* Copyright (c) 2022 lax1dude. All Rights Reserved.
* Copyright (c) 2022-2024 lax1dude. 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
@ -106,47 +108,45 @@ public class EaglerLWJGLShortBuffer implements ShortBuffer {
@Override
public short get() {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
return MemoryUtil.memGetShort(address + ((position++) << SHIFT));
return UnsafeUtils.getMemShort(address + ((position++) << SHIFT));
}
@Override
public ShortBuffer put(short b) {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutShort(address + ((position++) << SHIFT), b);
UnsafeUtils.setMemShort(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));
return UnsafeUtils.getMemShort(address + (index << SHIFT));
}
@Override
public ShortBuffer put(int index, short b) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutShort(address + (index << SHIFT), b);
UnsafeUtils.setMemShort(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));
return UnsafeUtils.getMemShort(address + (index << SHIFT));
}
@Override
public void putElement(int index, short value) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutShort(address + (index << SHIFT), value);
UnsafeUtils.setMemShort(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));
}
UnsafeMemcpy.memcpyAlignDst(dst, offset << SHIFT, address + (position << SHIFT), length);
position += length;
return this;
}
@ -154,9 +154,7 @@ public class EaglerLWJGLShortBuffer 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] = MemoryUtil.memGetShort(address + ((position + i) << SHIFT));
}
UnsafeMemcpy.memcpyAlignDst(dst, 0, address + (position << SHIFT), dst.length);
position += dst.length;
return this;
}
@ -167,14 +165,14 @@ public class EaglerLWJGLShortBuffer implements ShortBuffer {
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);
UnsafeMemcpy.memcpy(address + (position << SHIFT), c.address + (c.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());
UnsafeUtils.setMemInt(address + ((position + l) << SHIFT), src.get());
}
position += l;
}
@ -184,9 +182,7 @@ public class EaglerLWJGLShortBuffer 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) {
MemoryUtil.memPutShort(address + ((position + i) << SHIFT), src[offset + i]);
}
UnsafeMemcpy.memcpyAlignSrc(address + (position << SHIFT), src, offset << SHIFT, length);
position += length;
return this;
}
@ -194,9 +190,7 @@ public class EaglerLWJGLShortBuffer 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) {
MemoryUtil.memPutShort(address + ((position + i) << SHIFT), src[i]);
}
UnsafeMemcpy.memcpyAlignSrc(address + (position << SHIFT), src, 0, src.length);
position += src.length;
return this;
}
@ -217,7 +211,10 @@ public class EaglerLWJGLShortBuffer implements ShortBuffer {
int newLen = limit - position;
long newAlloc = JEmalloc.nje_malloc(newLen);
MemoryUtil.memCopy(address + (position << SHIFT), newAlloc, newLen << SHIFT);
if(newAlloc == 0l) {
throw new OutOfMemoryError("Native je_malloc call returned null pointer!");
}
UnsafeMemcpy.memcpy(newAlloc, address + (position << SHIFT), newLen << SHIFT);
return new EaglerLWJGLShortBuffer(newAlloc, newLen, true);
}

View File

@ -0,0 +1,224 @@
package net.lax1dude.eaglercraft.v1_8.internal.lwjgl;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformFilesystem;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.VFSFilenameIterator;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.vfs2.EaglerFileSystemException;
import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFSIterator2.BreakLoop;
/**
* Copyright (c) 2024 lax1dude. 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 DebugFilesystem implements PlatformFilesystem.IFilesystemProvider {
public static DebugFilesystem initialize(File filesystemRoot) {
if(!filesystemRoot.isDirectory() && !filesystemRoot.mkdirs()) {
throw new EaglerFileSystemException("Could not create directory for virtual filesystem: " + filesystemRoot.getAbsolutePath());
}
return new DebugFilesystem(filesystemRoot);
}
private final File filesystemRoot;
private DebugFilesystem(File root) {
this.filesystemRoot = root;
}
@Override
public boolean eaglerDelete(String pathName) {
File f = getJREFile(pathName);
if(!f.exists()) {
PlatformFilesystem.logger.warn("Tried to delete file that doesn't exist: \"{}\"", pathName);
return false;
}
if(f.delete()) {
deleteParentIfEmpty(f);
return true;
}
return false;
}
@Override
public ByteBuffer eaglerRead(String pathName) {
File f = getJREFile(pathName);
if(f.isFile()) {
long fileSize = f.length();
if(fileSize > 2147483647L) throw new EaglerFileSystemException("Too large: " + fileSize + " @ " + f.getAbsolutePath());
ByteBuffer buf = PlatformRuntime.allocateByteBuffer((int)fileSize);
try(FileInputStream is = new FileInputStream(f)) {
byte[] copyBuffer = new byte[4096];
int i;
while((i = is.read(copyBuffer, 0, copyBuffer.length)) != -1) {
buf.put(copyBuffer, 0, i);
}
if(buf.remaining() > 0) {
throw new EaglerFileSystemException("ERROR: " + buf.remaining() + " bytes are remaining after reading: " + f.getAbsolutePath());
}
buf.flip();
ByteBuffer tmp = buf;
buf = null;
return tmp;
}catch (IOException e) {
throw new EaglerFileSystemException("Failed to read: " + f.getAbsolutePath(), e);
}catch(ArrayIndexOutOfBoundsException ex) {
throw new EaglerFileSystemException("ERROR: Expected " + fileSize + " bytes, buffer overflow reading: " + f.getAbsolutePath(), ex);
}finally {
if(buf != null) {
PlatformRuntime.freeByteBuffer(buf);
}
}
}else {
PlatformFilesystem.logger.warn("Tried to read file that doesn't exist: \"{}\"", f.getAbsolutePath());
return null;
}
}
@Override
public void eaglerWrite(String pathName, ByteBuffer data) {
File f = getJREFile(pathName);
File p = f.getParentFile();
if(!p.isDirectory()) {
if(!p.mkdirs()) {
throw new EaglerFileSystemException("Could not create parent directory: " + p.getAbsolutePath());
}
}
try(FileOutputStream fos = new FileOutputStream(f)) {
byte[] copyBuffer = new byte[Math.min(4096, data.remaining())];
int i;
while((i = data.remaining()) > 0) {
if(i > copyBuffer.length) {
i = copyBuffer.length;
}
data.get(copyBuffer, 0, i);
fos.write(copyBuffer, 0, i);
}
}catch (IOException e) {
throw new EaglerFileSystemException("Failed to write: " + f.getAbsolutePath(), e);
}
}
@Override
public boolean eaglerExists(String pathName) {
return getJREFile(pathName).isFile();
}
@Override
public boolean eaglerMove(String pathNameOld, String pathNameNew) {
File f1 = getJREFile(pathNameOld);
File f2 = getJREFile(pathNameNew);
if(f2.exists()) {
PlatformFilesystem.logger.warn("Tried to rename file \"{}\" to \"{}\" which already exists! File will be replaced");
if(!f2.delete()) {
return false;
}
}
if(f1.renameTo(f2)) {
deleteParentIfEmpty(f1);
return true;
}
return false;
}
@Override
public int eaglerCopy(String pathNameOld, String pathNameNew) {
File f1 = getJREFile(pathNameOld);
File f2 = getJREFile(pathNameNew);
if(!f1.isFile()) {
return -1;
}
if(f2.isDirectory()) {
throw new EaglerFileSystemException("Destination file is a directory: " + f2.getAbsolutePath());
}
File p = f2.getParentFile();
if(!p.isDirectory()) {
if(!p.mkdirs()) {
throw new EaglerFileSystemException("Could not create parent directory: " + p.getAbsolutePath());
}
}
int sz = 0;
try(FileInputStream is = new FileInputStream(f1)) {
try(FileOutputStream os = new FileOutputStream(f2)) {
byte[] copyBuffer = new byte[4096];
int i;
while((i = is.read(copyBuffer, 0, copyBuffer.length)) != -1) {
os.write(copyBuffer, 0, i);
sz += i;
}
}
}catch (IOException e) {
throw new EaglerFileSystemException("Failed to copy \"" + f1.getAbsolutePath() + "\" to file \"" + f2.getAbsolutePath() + "\"", e);
}
return sz;
}
@Override
public int eaglerSize(String pathName) {
File f = getJREFile(pathName);
if(f.isFile()) {
long fileSize = f.length();
if(fileSize > 2147483647L) throw new EaglerFileSystemException("Too large: " + fileSize + " @ " + f.getAbsolutePath());
return (int)fileSize;
}else {
return -1;
}
}
@Override
public void eaglerIterate(String pathName, VFSFilenameIterator itr, boolean recursive) {
try {
iterateFile(pathName, getJREFile(pathName), itr, recursive);
}catch(BreakLoop ex) {
}
}
private void iterateFile(String pathName, File f, VFSFilenameIterator itr, boolean recursive) {
if(!f.exists()) {
return;
}
if(!f.isDirectory()) {
itr.next(pathName);
return;
}
File[] fa = f.listFiles();
for(int i = 0; i < fa.length; ++i) {
File ff = fa[i];
String fn = pathName + "/" + ff.getName();
if(ff.isDirectory()) {
if(recursive) {
iterateFile(fn, ff, itr, true);
}
}else {
itr.next(fn);
}
}
}
private File getJREFile(String path) {
return new File(filesystemRoot, path);
}
private void deleteParentIfEmpty(File f) {
String[] s;
while((f = f.getParentFile()) != null && (s = f.list()) != null && s.length == 0) {
f.delete();
}
}
}

View File

@ -124,4 +124,8 @@ public class DesktopClientConfigAdapter implements IClientConfigAdapter {
return false;
}
@Override
public boolean isAllowVoiceClient() {
return false;
}
}

View File

@ -0,0 +1,78 @@
package net.lax1dude.eaglercraft.v1_8.internal.lwjgl;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.Color;
import java.awt.BorderLayout;
import javax.swing.JProgressBar;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
/**
* Copyright (c) 2024 lax1dude. 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 FilesystemConvertingDialog extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private JProgressBar progressBar;
public FilesystemConvertingDialog(String title) {
setIconImage(Toolkit.getDefaultToolkit().getImage("icon32.png"));
setResizable(false);
setAlwaysOnTop(true);
setTitle("EaglercraftX 1.8");
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
setBounds(100, 100, 420, 100);
contentPane = new JPanel();
contentPane.setBackground(new Color(255, 255, 255));
contentPane.setBorder(null);
setContentPane(contentPane);
contentPane.setLayout(new BorderLayout(0, 0));
JPanel panel = new JPanel();
panel.setBorder(new EmptyBorder(10, 10, 10, 10));
panel.setBackground(new Color(255, 255, 255));
contentPane.add(panel, BorderLayout.SOUTH);
panel.setLayout(new BorderLayout(0, 0));
progressBar = new JProgressBar();
progressBar.setIndeterminate(true);
progressBar.setPreferredSize(new Dimension(146, 20));
progressBar.setMinimum(0);
progressBar.setMaximum(512);
panel.add(progressBar, BorderLayout.CENTER);
JLabel lblNewLabel = new JLabel(title);
lblNewLabel.setFont(UIManager.getFont("PopupMenu.font"));
lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
contentPane.add(lblNewLabel, BorderLayout.CENTER);
}
public void setProgressIndeterminate(boolean itr) {
progressBar.setIndeterminate(itr);
}
public void setProgressValue(int val) {
progressBar.setValue(val);
}
}

View File

@ -0,0 +1,441 @@
package net.lax1dude.eaglercraft.v1_8.internal.lwjgl;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collection;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.Properties;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformFilesystem.IFilesystemProvider;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformFilesystem;
import net.lax1dude.eaglercraft.v1_8.internal.VFSFilenameIterator;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.vfs2.EaglerFileSystemException;
import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFSIterator2;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
/**
* Copyright (c) 2024 lax1dude. 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 JDBCFilesystem implements IFilesystemProvider {
public static final Logger logger = LogManager.getLogger("JDBCFilesystem");
private boolean newFilesystem = true;
private static volatile boolean cleanupThreadStarted = false;
private static final Collection<JDBCFilesystem> jdbcFilesystems = new LinkedList();
private final String jdbcUri;
private final String jdbcDriver;
private final Connection conn;
private final PreparedStatement createStatement;
private final PreparedStatement updateStatement;
private final PreparedStatement readStatement;
private final PreparedStatement existsStatement;
private final PreparedStatement sizeStatement;
private final PreparedStatement deleteStatement;
private final PreparedStatement renameStatement;
private final PreparedStatement iterateNonRecursive;
private final PreparedStatement iterateRecursive;
private boolean hasClosed = false;
private final Object mutex = new Object();
public static IFilesystemProvider initialize(String jdbcUri, String jdbcDriver) {
Class driver;
try {
driver = Class.forName(jdbcDriver);
} catch (ClassNotFoundException e) {
throw new EaglerFileSystemException("JDBC driver class not found in JRE: " + jdbcDriver, e);
}
Driver driverObj = null;
Enumeration<Driver> registeredDriversItr = DriverManager.getDrivers();
while(registeredDriversItr.hasMoreElements()) {
Driver drv = registeredDriversItr.nextElement();
if(drv.getClass().equals(driver)) {
driverObj = drv;
break;
}
}
if(driverObj == null) {
logger.warn("The class \"{}\" is not a registered JDBC driver, eaglercraft will try all registered drivers...", jdbcDriver);
}
Properties props = new Properties();
for(Entry<Object, Object> etr : System.getProperties().entrySet()) {
if(etr.getKey() instanceof String) {
String str = (String)etr.getKey();
if(str.startsWith("eagler.jdbc.opts.")) {
props.put(str.substring(17), etr.getValue());
}
}
}
logger.info("Connecting to database: \"{}\"", jdbcUri);
Connection conn;
try {
if(driverObj != null) {
conn = driverObj.connect(jdbcUri, props);
}else {
conn = DriverManager.getConnection(jdbcUri, props);
}
}catch(SQLException ex) {
throw new EaglerFileSystemException("Failed to connect to database: \"" + jdbcUri + "\"", ex);
}
try {
return new JDBCFilesystem(conn, jdbcUri, jdbcDriver);
} catch (SQLException ex) {
try {
conn.close();
}catch(SQLException ex2) {
}
throw new EaglerFileSystemException("Failed to initialize database: \"" + jdbcUri + "\"", ex);
}
}
private JDBCFilesystem(Connection conn, String jdbcUri, String jdbcDriver) throws SQLException {
this.conn = conn;
this.jdbcUri = jdbcUri;
this.jdbcDriver = jdbcDriver;
try(Statement stmt = conn.createStatement()) {
stmt.execute("CREATE TABLE IF NOT EXISTS "
+ "\"eaglercraft_desktop_runtime_filesystem\" ("
+ "\"FileName\" VARCHAR(1024) NOT NULL,"
+ "\"FileSize\" INT NOT NULL,"
+ "\"FileData\" BLOB NOT NULL,"
+ "PRIMARY KEY(\"FileName\"))");
int totalFiles = 0;
try(ResultSet resultSet = stmt.executeQuery("SELECT COUNT(*) AS total_files FROM eaglercraft_desktop_runtime_filesystem")) {
if(resultSet.next()) {
totalFiles = resultSet.getInt(1);
}
}
logger.info("Loaded JDBC filesystem with {} files: \"{}\"", totalFiles, jdbcUri);
if(totalFiles > 0) {
newFilesystem = false;
}
}
this.createStatement = conn.prepareStatement("INSERT INTO eaglercraft_desktop_runtime_filesystem (FileName, FileSize, FileData) VALUES(?,?,?)");
this.updateStatement = conn.prepareStatement("UPDATE eaglercraft_desktop_runtime_filesystem SET FileSize = ?, FileData = ? WHERE FileName = ?");
this.readStatement = conn.prepareStatement("SELECT FileData FROM eaglercraft_desktop_runtime_filesystem WHERE FileName = ? LIMIT 1");
this.existsStatement = conn.prepareStatement("SELECT COUNT(FileName) AS has_object FROM eaglercraft_desktop_runtime_filesystem WHERE FileName = ? LIMIT 1");
this.sizeStatement = conn.prepareStatement("SELECT FileSize FROM eaglercraft_desktop_runtime_filesystem WHERE FileName = ? LIMIT 1");
this.deleteStatement = conn.prepareStatement("DELETE FROM eaglercraft_desktop_runtime_filesystem WHERE FileName = ?");
this.renameStatement = conn.prepareStatement("UPDATE eaglercraft_desktop_runtime_filesystem SET FileName = ? WHERE FileName = ?");
this.iterateNonRecursive = conn.prepareStatement("SELECT FileName FROM eaglercraft_desktop_runtime_filesystem WHERE FileName LIKE ? AND NOT FileName LIKE ?");
this.iterateRecursive = conn.prepareStatement("SELECT FileName FROM eaglercraft_desktop_runtime_filesystem WHERE FileName LIKE ?");
startCleanupThread();
synchronized(jdbcFilesystems) {
jdbcFilesystems.add(this);
}
}
public boolean isNewFilesystem() {
return newFilesystem;
}
private static void startCleanupThread() {
if(!cleanupThreadStarted) {
cleanupThreadStarted = true;
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
synchronized(jdbcFilesystems) {
if(!jdbcFilesystems.isEmpty()) {
for(JDBCFilesystem fs : jdbcFilesystems) {
fs.shutdown0();
}
jdbcFilesystems.clear();
}
}
}, "JDBCFilesystemCleanup"));
}
}
public void shutdown() {
shutdown0();
synchronized(jdbcFilesystems) {
jdbcFilesystems.remove(this);
}
}
private void shutdown0() {
synchronized(mutex) {
if(!hasClosed) {
hasClosed = true;
logger.info("Disconnecting from database: \"{}\"", jdbcUri);
try {
shutdown1();
}catch(Throwable t) {
logger.error("Failed to disconnect from database: \"{}\"");
logger.error(t);
}
}
}
}
private void shutdown1() throws SQLException {
if(!conn.isClosed()) {
quietClose(createStatement);
quietClose(updateStatement);
quietClose(readStatement);
quietClose(existsStatement);
quietClose(sizeStatement);
quietClose(deleteStatement);
quietClose(renameStatement);
quietClose(iterateNonRecursive);
quietClose(iterateRecursive);
conn.close();
}
}
private static void quietClose(Statement stmt) {
try {
stmt.close();
}catch(Throwable t) {
}
}
@Override
public boolean eaglerDelete(String pathName) {
try {
synchronized(mutex) {
if(hasClosed || conn.isClosed()) {
throw new SQLException("Filesystem database connection is closed!");
}
deleteStatement.setString(1, pathName);
int ret = deleteStatement.executeUpdate();
if(ret == 0) {
PlatformFilesystem.logger.warn("Tried to delete file that doesn't exist: \"{}\"", pathName);
}
return ret > 0;
}
}catch(SQLException ex) {
throw new EaglerFileSystemException("JDBC exception thrown while executing delete!", ex);
}
}
@Override
public ByteBuffer eaglerRead(String pathName) {
try {
synchronized(mutex) {
if(hasClosed || conn.isClosed()) {
throw new SQLException("Filesystem database connection is closed!");
}
readStatement.setString(1, pathName);
byte[] has = null;
try(ResultSet resultSet = readStatement.executeQuery()) {
if(resultSet.next()) {
has = resultSet.getBytes(1);
}
}
if(has == null) {
PlatformFilesystem.logger.warn("Tried to read file that doesn't exist: \"{}\"", pathName);
return null;
}
ByteBuffer byteBuf = PlatformRuntime.allocateByteBuffer(has.length);
byteBuf.put(has);
byteBuf.flip();
return byteBuf;
}
}catch(SQLException ex) {
throw new EaglerFileSystemException("JDBC exception thrown while executing read!", ex);
}
}
@Override
public void eaglerWrite(String pathName, ByteBuffer data) {
try {
synchronized(mutex) {
if(hasClosed || conn.isClosed()) {
throw new SQLException("Filesystem database connection is closed!");
}
existsStatement.setString(1, pathName);
boolean exists;
try(ResultSet resultSet = existsStatement.executeQuery()) {
if(resultSet.next()) {
exists = resultSet.getInt(1) > 0;
}else {
exists = false;
}
}
byte[] cp = new byte[data.remaining()];
data.get(cp);
if(exists) {
updateStatement.setInt(1, cp.length);
updateStatement.setBytes(2, cp);
updateStatement.setString(3, pathName);
if(updateStatement.executeUpdate() == 0) {
throw new EaglerFileSystemException("SQL file update query did not update any rows!");
}
}else {
createStatement.setString(1, pathName);
createStatement.setInt(2, cp.length);
createStatement.setBytes(3, cp);
createStatement.executeUpdate();
}
}
}catch(SQLException ex) {
throw new EaglerFileSystemException("JDBC exception thrown while executing write!", ex);
}
}
@Override
public boolean eaglerExists(String pathName) {
try {
synchronized(mutex) {
if(hasClosed || conn.isClosed()) {
throw new SQLException("Filesystem database connection is closed!");
}
existsStatement.setString(1, pathName);
try(ResultSet resultSet = existsStatement.executeQuery()) {
if(resultSet.next()) {
return resultSet.getInt(1) > 0;
}else {
return false;
}
}
}
}catch(SQLException ex) {
throw new EaglerFileSystemException("JDBC exception thrown while executing exists!", ex);
}
}
@Override
public boolean eaglerMove(String pathNameOld, String pathNameNew) {
try {
synchronized(mutex) {
if(hasClosed || conn.isClosed()) {
throw new SQLException("Filesystem database connection is closed!");
}
renameStatement.setString(1, pathNameNew);
renameStatement.setString(2, pathNameOld);
return renameStatement.executeUpdate() > 0;
}
}catch(SQLException ex) {
throw new EaglerFileSystemException("JDBC exception thrown while executing move!", ex);
}
}
@Override
public int eaglerCopy(String pathNameOld, String pathNameNew) {
try {
synchronized(mutex) {
if(hasClosed || conn.isClosed()) {
throw new SQLException("Filesystem database connection is closed!");
}
readStatement.setString(1, pathNameOld);
try(ResultSet resultSet = readStatement.executeQuery()) {
byte[] has = null;
if(resultSet.next()) {
has = resultSet.getBytes(1);
}
if(has == null) {
return -1;
}
existsStatement.setString(1, pathNameNew);
boolean exists;
try(ResultSet resultSet2 = existsStatement.executeQuery()) {
if(resultSet2.next()) {
exists = resultSet2.getInt(1) > 0;
}else {
exists = false;
}
}
if(exists) {
updateStatement.setInt(1, has.length);
updateStatement.setBytes(2, has);
updateStatement.setString(3, pathNameNew);
if(updateStatement.executeUpdate() == 0) {
throw new EaglerFileSystemException("SQL file update query did not update any rows!");
}
}else {
createStatement.setString(1, pathNameNew);
createStatement.setInt(2, has.length);
createStatement.setBytes(3, has);
createStatement.executeUpdate();
}
return has.length;
}
}
}catch(SQLException ex) {
throw new EaglerFileSystemException("JDBC exception thrown while executing copy!", ex);
}
}
@Override
public int eaglerSize(String pathName) {
try {
synchronized(mutex) {
if(hasClosed || conn.isClosed()) {
throw new SQLException("Filesystem database connection is closed!");
}
sizeStatement.setString(1, pathName);
try(ResultSet resultSet = sizeStatement.executeQuery()) {
if(resultSet.next()) {
return resultSet.getInt(1);
}else {
return -1;
}
}
}
}catch(SQLException ex) {
throw new EaglerFileSystemException("JDBC exception thrown while executing size!", ex);
}
}
@Override
public void eaglerIterate(String pathName, VFSFilenameIterator itr, boolean recursive) {
try {
synchronized(mutex) {
if(hasClosed || conn.isClosed()) {
throw new SQLException("Filesystem database connection is closed!");
}
PreparedStatement stmt;
if(recursive) {
stmt = iterateRecursive;
stmt.setString(1, pathName + (!pathName.endsWith("/") ? "/%" : "%"));;
}else {
stmt = iterateNonRecursive;
if(!pathName.endsWith("/")) {
pathName += "/";
}
stmt.setString(1, pathName + "%");
stmt.setString(2, pathName + "%/%");
}
try(ResultSet resultSet = stmt.executeQuery()) {
while(resultSet.next()) {
try {
itr.next(resultSet.getString(1));
}catch(VFSIterator2.BreakLoop exx) {
break;
}
}
}
}
}catch(SQLException ex) {
throw new EaglerFileSystemException("JDBC exception thrown while executing iterate!", ex);
}
}
}

View File

@ -0,0 +1,130 @@
package net.lax1dude.eaglercraft.v1_8.internal.lwjgl;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformFilesystem.IFilesystemProvider;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.vfs2.EaglerFileSystemException;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
/**
* Copyright (c) 2024 lax1dude. 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 JDBCFilesystemConverter {
private static final Logger logger = LogManager.getLogger("JDBCFilesystemConverter");
public static void convertFilesystem(String title, File oldFS, IFilesystemProvider newFS, boolean deleteOld) {
FilesystemConvertingDialog progressDialog = new FilesystemConvertingDialog(title);
try {
progressDialog.setProgressIndeterminate(true);
progressDialog.setLocationRelativeTo(null);
progressDialog.setVisible(true);
String slug = oldFS.getAbsolutePath();
List<String> filesToCopy = new ArrayList();
logger.info("Discovering files to convert...");
iterateFolder(slug.length(), oldFS, filesToCopy);
logger.info("Found {} files in the old directory", filesToCopy.size());
progressDialog.setProgressIndeterminate(false);
progressDialog.setProgressValue(0);
int progCounter = 0;
int lastProgUpdate = 0;
byte[] copyArray = new byte[4096];
int l = filesToCopy.size();
for(int i = 0; i < l; ++i) {
String str = filesToCopy.get(i);
File f = new File(oldFS, str);
try(InputStream is = new FileInputStream(f)) {
ByteBuffer copyBuffer = PlatformRuntime.allocateByteBuffer((int)f.length());
try {
int j;
while(copyBuffer.hasRemaining() && (j = is.read(copyArray, 0, copyArray.length)) != -1) {
copyBuffer.put(copyArray, 0, j);
}
copyBuffer.flip();
progCounter += copyBuffer.remaining();
newFS.eaglerWrite(str, copyBuffer);
}finally {
PlatformRuntime.freeByteBuffer(copyBuffer);
}
if(progCounter - lastProgUpdate > 25000) {
lastProgUpdate = progCounter;
logger.info("Converted {}/{} files, {} bytes to JDBC format...", (i + 1), l, progCounter);
}
}catch(IOException ex) {
throw new EaglerFileSystemException("Failed to convert file: \"" + f.getAbsolutePath() + "\"", ex);
}
progressDialog.setProgressValue(i * 512 / (l - 1));
}
logger.info("Converted {}/{} files successfully!", l, l);
if(deleteOld) {
logger.info("Deleting old filesystem...");
progressDialog.setProgressIndeterminate(true);
deleteOldFolder(oldFS);
logger.info("Delete complete!");
}
}finally {
progressDialog.setVisible(false);
progressDialog.dispose();
}
}
private static void iterateFolder(int slug, File file, List<String> ret) {
File[] f = file.listFiles();
if(f == null) {
return;
}
for(int i = 0; i < f.length; ++i) {
File ff = f[i];
if(ff.isDirectory()) {
iterateFolder(slug, ff, ret);
}else {
String str = ff.getAbsolutePath();
if(str.length() > slug) {
str = str.substring(slug).replace('\\', '/');
if(str.startsWith("/")) {
str = str.substring(1);
}
ret.add(str);
}
}
}
}
private static void deleteOldFolder(File file) {
File[] f = file.listFiles();
for(int i = 0; i < f.length; ++i) {
if(f[i].isDirectory()) {
deleteOldFolder(f[i]);
}else {
f[i].delete();
}
}
file.delete();
}
}

View File

@ -6,6 +6,7 @@ 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.PlatformFilesystem;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformInput;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.ShaderSource;
@ -43,15 +44,9 @@ public class LWJGLEntryPoint {
boolean hideRenderDocDialog = false;
for(int i = 0; i < args.length; ++i) {
if(args[i].equalsIgnoreCase("highp")) {
ShaderSource.setHighP(true);
}
if(args[i].equalsIgnoreCase("hide-renderdoc")) {
hideRenderDocDialog = true;
}
if(args[i].equalsIgnoreCase("fullscreen")) {
PlatformInput.setStartupFullscreen(true);
}
}
if(!hideRenderDocDialog) {
@ -66,7 +61,7 @@ public class LWJGLEntryPoint {
lr.dispose();
}
getANGLEPlatformFromArgs(args);
getPlatformOptionsFromArgs(args);
RelayManager.relayManager.load(EagRuntime.getStorage("r"));
@ -81,12 +76,22 @@ public class LWJGLEntryPoint {
}
private static void getANGLEPlatformFromArgs(String[] args) {
private static void getPlatformOptionsFromArgs(String[] args) {
for(int i = 0; i < args.length; ++i) {
EnumPlatformANGLE angle = EnumPlatformANGLE.fromId(args[i]);
if(angle != EnumPlatformANGLE.DEFAULT) {
PlatformRuntime.requestANGLE(angle);
break;
if(args[i].equalsIgnoreCase("fullscreen")) {
PlatformInput.setStartupFullscreen(true);
}else if(args[i].equalsIgnoreCase("highp")) {
ShaderSource.setHighP(true);
}else if(args[i].startsWith("jdbc:")) {
if(i < args.length - 1) {
PlatformFilesystem.setUseJDBC(args[i]);
PlatformFilesystem.setJDBCDriverClass(args[++i]);
}
}else {
EnumPlatformANGLE angle = EnumPlatformANGLE.fromId(args[i]);
if(angle != EnumPlatformANGLE.DEFAULT) {
PlatformRuntime.requestANGLE(angle);
}
}
}
}

View File

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

View File

@ -28,4 +28,8 @@ public class Config {
public static boolean audioEnabled() {
return Minecraft.getMinecraft().gameSettings.enableSound;
}
public static boolean animateTick() {
return false;
}
}

View File

@ -45,6 +45,10 @@ public class Display {
return PlatformInput.isCloseRequested();
}
public static void setVSync(boolean enable) {
PlatformInput.setVSync(enable);
}
public static void update() {
PlatformInput.update();
}

View File

@ -9,9 +9,9 @@ public class EaglercraftVersion {
/// Customize these to fit your fork:
public static final String projectForkName = "EaglercraftX";
public static final String projectForkVersion = "u27";
public static final String projectForkVendor = "lax1dude";
public static final String projectForkName = "EaglerfastX";
public static final String projectForkVersion = "u29";
public static final String projectForkVendor = "hoosiertransfer";
public static final String projectForkURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8";
@ -20,7 +20,7 @@ public class EaglercraftVersion {
public static final String projectOriginName = "EaglercraftX";
public static final String projectOriginAuthor = "lax1dude";
public static final String projectOriginRevision = "1.8";
public static final String projectOriginVersion = "u27";
public static final String projectOriginVersion = "u29";
public static final String projectOriginURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; // rest in peace
@ -31,7 +31,7 @@ public class EaglercraftVersion {
public static final boolean enableUpdateService = false;
public static final String updateBundlePackageName = "net.lax1dude.eaglercraft.v1_8.client";
public static final int updateBundlePackageVersionInt = 24;
public static final int updateBundlePackageVersionInt = 29;
public static final String updateLatestLocalStorageKey = "latestUpdate_" + updateBundlePackageName;

View File

@ -67,4 +67,6 @@ public interface IClientConfigAdapter {
boolean isCheckRelaysForUpdates();
boolean isEnableSignatureBadge();
boolean isAllowVoiceClient();
}

View File

@ -0,0 +1,172 @@
package net.lax1dude.eaglercraft.v1_8.opengl;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.IResourceManagerReloadListener;
import net.minecraft.util.ResourceLocation;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
/**
* Copyright (c) 2024 lax1dude. 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 EaglerMeshLoader implements IResourceManagerReloadListener {
private static final Logger logger = LogManager.getLogger("EaglerMeshLoader");
private static final Map<ResourceLocation, HighPolyMesh> meshCache = new HashMap();
public static HighPolyMesh getEaglerMesh(ResourceLocation meshLoc) {
if(meshLoc.cachedPointerType == ResourceLocation.CACHED_POINTER_EAGLER_MESH) {
return (HighPolyMesh)meshLoc.cachedPointer;
}
HighPolyMesh theMesh = meshCache.get(meshLoc);
if(theMesh == null) {
theMesh = new HighPolyMesh();
reloadMesh(meshLoc, theMesh, Minecraft.getMinecraft().getResourceManager());
}
meshLoc.cachedPointerType = ResourceLocation.CACHED_POINTER_EAGLER_MESH;
meshLoc.cachedPointer = theMesh;
return theMesh;
}
private static void reloadMesh(ResourceLocation meshLoc, HighPolyMesh meshStruct, IResourceManager resourceManager) {
IntBuffer up1 = null;
try {
int intsOfVertex, intsOfIndex, intsTotal, stride;
try(DataInputStream dis = new DataInputStream(resourceManager.getResource(meshLoc).getInputStream())) {
byte[] header = new byte[8];
dis.read(header);
if(!Arrays.equals(header, new byte[] { (byte) 33, (byte) 69, (byte) 65, (byte) 71, (byte) 36,
(byte) 109, (byte) 100, (byte) 108 })) {
throw new IOException("File is not an eaglercraft high-poly mesh!");
}
char CT = (char)dis.read();
if(CT == 'C') {
meshStruct.hasTexture = false;
}else if(CT == 'T') {
meshStruct.hasTexture = true;
}else {
throw new IOException("Unsupported mesh type '" + CT + "'!");
}
dis.skipBytes(dis.readUnsignedShort());
meshStruct.vertexCount = dis.readInt();
meshStruct.indexCount = dis.readInt();
int byteIndexCount = meshStruct.indexCount;
if(byteIndexCount % 2 != 0) { // must round up to int
byteIndexCount += 1;
}
stride = meshStruct.hasTexture ? 24 : 16;
intsOfVertex = meshStruct.vertexCount * stride / 4;
intsOfIndex = byteIndexCount / 2;
intsTotal = intsOfIndex + intsOfVertex;
up1 = EagRuntime.allocateIntBuffer(intsTotal);
for(int i = 0; i < intsTotal; ++i) {
int ch1 = dis.read();
int ch2 = dis.read();
int ch3 = dis.read();
int ch4 = dis.read();
if ((ch1 | ch2 | ch3 | ch4) < 0) throw new EOFException(); // rip
up1.put((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));
}
}
if(meshStruct.vertexArray == null) {
meshStruct.vertexArray = _wglGenVertexArrays();
}
if(meshStruct.vertexBuffer == null) {
meshStruct.vertexBuffer = _wglGenBuffers();
}
if(meshStruct.indexBuffer == null) {
meshStruct.indexBuffer = _wglGenBuffers();
}
up1.position(0).limit(intsOfVertex);
EaglercraftGPU.bindGLArrayBuffer(meshStruct.vertexBuffer);
_wglBufferData(GL_ARRAY_BUFFER, up1, GL_STATIC_DRAW);
EaglercraftGPU.bindGLBufferArray(meshStruct.vertexArray);
up1.position(intsOfVertex).limit(intsTotal);
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshStruct.indexBuffer);
_wglBufferData(GL_ELEMENT_ARRAY_BUFFER, up1, GL_STATIC_DRAW);
_wglEnableVertexAttribArray(0);
_wglVertexAttribPointer(0, 3, GL_FLOAT, false, stride, 0);
if(meshStruct.hasTexture) {
_wglEnableVertexAttribArray(1);
_wglVertexAttribPointer(1, 2, GL_FLOAT, false, stride, 16);
}
_wglEnableVertexAttribArray(meshStruct.hasTexture ? 2 : 1);
_wglVertexAttribPointer(meshStruct.hasTexture ? 2 : 1, 4, GL_BYTE, true, stride, 12);
}catch(Throwable ex) {
if(meshStruct.vertexArray != null) {
_wglDeleteVertexArrays(meshStruct.vertexArray);
meshStruct.vertexArray = null;
}
if(meshStruct.vertexBuffer != null) {
_wglDeleteBuffers(meshStruct.vertexBuffer);
meshStruct.vertexBuffer = null;
}
if(meshStruct.indexBuffer != null) {
_wglDeleteBuffers(meshStruct.indexBuffer);
meshStruct.indexBuffer = null;
}
meshStruct.vertexCount = 0;
meshStruct.indexCount = 0;
meshStruct.hasTexture = false;
logger.error("Failed to load eaglercraft high-poly mesh: \"{}\"", meshLoc);
logger.error(ex);
}finally {
if(up1 != null) {
EagRuntime.freeIntBuffer(up1);
}
}
}
@Override
public void onResourceManagerReload(IResourceManager var1) {
for(Entry<ResourceLocation, HighPolyMesh> meshEntry : meshCache.entrySet()) {
reloadMesh(meshEntry.getKey(), meshEntry.getValue(), var1);
}
}
}

View File

@ -152,7 +152,7 @@ public class EaglercraftGPU {
currentList = null;
}
public static void glCallList(int displayList) {
public static final void glCallList(int displayList) {
DisplayList dp = mapDisplayListsGL.get(displayList);
if(dp == null) {
throw new NullPointerException("Tried to call a display list that does not exist: " + displayList);
@ -488,14 +488,24 @@ public class EaglercraftGPU {
return mapTexturesGL.get(tex);
}
public static final void drawHighPoly(HighPolyMesh mesh) {
if(mesh.vertexCount == 0 || mesh.indexCount == 0 || mesh.vertexArray == null) {
return;
}
FixedFunctionPipeline p = FixedFunctionPipeline.setupRenderDisplayList(mesh.getAttribBits()).update();
EaglercraftGPU.bindGLBufferArray(mesh.vertexArray);
p.drawElements(GL_TRIANGLES, mesh.indexCount, GL_UNSIGNED_SHORT, 0);
}
static boolean hasFramebufferHDR16FSupport = false;
static boolean hasFramebufferHDR32FSupport = false;
static boolean hasLinearHDR32FSupport = false;
public static void createFramebufferHDR16FTexture(int target, int level, int w, int h, int format, boolean allow32bitFallback) {
public static final void createFramebufferHDR16FTexture(int target, int level, int w, int h, int format, boolean allow32bitFallback) {
createFramebufferHDR16FTexture(target, level, w, h, format, allow32bitFallback, null);
}
public static void createFramebufferHDR16FTexture(int target, int level, int w, int h, int format, ByteBuffer pixelData) {
public static final void createFramebufferHDR16FTexture(int target, int level, int w, int h, int format, ByteBuffer pixelData) {
createFramebufferHDR16FTexture(target, level, w, h, format, false, pixelData);
}
@ -530,15 +540,15 @@ public class EaglercraftGPU {
}
}
public static void createFramebufferHDR32FTexture(int target, int level, int w, int h, int format, boolean allow16bitFallback) {
public static final void createFramebufferHDR32FTexture(int target, int level, int w, int h, int format, boolean allow16bitFallback) {
createFramebufferHDR32FTexture(target, level, w, h, format, allow16bitFallback, null);
}
public static void createFramebufferHDR32FTexture(int target, int level, int w, int h, int format, ByteBuffer pixelData) {
public static final void createFramebufferHDR32FTexture(int target, int level, int w, int h, int format, ByteBuffer pixelData) {
createFramebufferHDR32FTexture(target, level, w, h, format, false, pixelData);
}
private static void createFramebufferHDR32FTexture(int target, int level, int w, int h, int format, boolean allow16bitFallback, ByteBuffer pixelData) {
private static final void createFramebufferHDR32FTexture(int target, int level, int w, int h, int format, boolean allow16bitFallback, ByteBuffer pixelData) {
if(hasFramebufferHDR32FSupport) {
int internalFormat;
switch(format) {
@ -555,7 +565,7 @@ public class EaglercraftGPU {
default:
throw new UnsupportedOperationException("Unknown format: " + format);
}
_wglTexImage2D(target, level, internalFormat, w, h, 0, format, GL_FLOAT, pixelData);
_wglTexImage2Df32(target, level, internalFormat, w, h, 0, format, GL_FLOAT, pixelData);
}else {
if(allow16bitFallback) {
if(hasFramebufferHDR16FSupport) {
@ -585,7 +595,13 @@ public class EaglercraftGPU {
}else {
logger.error("32-bit HDR render target support: false");
}
if(!checkHasHDRFramebufferSupport()) {
hasLinearHDR32FSupport = PlatformOpenGL.checkLinearHDR32FSupport();
if(hasLinearHDR32FSupport) {
logger.info("32-bit HDR linear filter support: true");
}else {
logger.error("32-bit HDR linear filter support: false");
}
if(!checkHasHDRFramebufferSupportWithFilter()) {
logger.error("No HDR render target support was detected! Shaders will be disabled.");
}
DrawUtils.init();
@ -612,4 +628,12 @@ public class EaglercraftGPU {
public static final boolean checkHasHDRFramebufferSupport() {
return hasFramebufferHDR16FSupport || hasFramebufferHDR32FSupport;
}
public static final boolean checkHasHDRFramebufferSupportWithFilter() {
return hasFramebufferHDR16FSupport || (hasFramebufferHDR32FSupport && hasLinearHDR32FSupport);
}
public static final boolean checkLinearHDR32FSupport() {
return hasLinearHDR32FSupport;
}
}

View File

@ -983,6 +983,30 @@ public class GlStateManager {
Matrix4f.mul(modeMatrix, paramMatrix, modeMatrix);
}
public static final void multMatrix(Matrix4f matrix) {
Matrix4f modeMatrix;
switch(stateMatrixMode) {
case GL_MODELVIEW:
default:
modeMatrix = modelMatrixStack[modelMatrixStackPointer];
modelMatrixStackAccessSerial[modelMatrixStackPointer] = ++modelMatrixAccessSerial;
break;
case GL_PROJECTION:
modeMatrix = projectionMatrixStack[projectionMatrixStackPointer];
projectionMatrixStackAccessSerial[projectionMatrixStackPointer] = ++projectionMatrixAccessSerial;
break;
case GL_TEXTURE:
int ptr = textureMatrixStackPointer[activeTexture];
modeMatrix = textureMatrixStack[activeTexture][ptr];
textureMatrixStackAccessSerial[activeTexture][textureMatrixStackPointer[activeTexture]] =
++textureMatrixAccessSerial[activeTexture];
break;
}
Matrix4f.mul(modeMatrix, matrix, modeMatrix);
}
public static final void color(float colorRed, float colorGreen, float colorBlue, float colorAlpha) {
stateColorR = colorRed;
stateColorG = colorGreen;

View File

@ -0,0 +1,66 @@
package net.lax1dude.eaglercraft.v1_8.opengl;
import net.lax1dude.eaglercraft.v1_8.internal.IBufferArrayGL;
import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL;
import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionState;
/**
* Copyright (c) 2024 lax1dude. 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 HighPolyMesh {
IBufferArrayGL vertexArray;
IBufferGL vertexBuffer;
IBufferGL indexBuffer;
int vertexCount;
int indexCount;
boolean hasTexture;
public HighPolyMesh(IBufferArrayGL vertexArray, IBufferGL vertexBuffer, IBufferGL indexBuffer, int vertexCount,
int indexCount, boolean hasTexture) {
this.vertexArray = vertexArray;
this.vertexBuffer = vertexBuffer;
this.indexBuffer = indexBuffer;
this.vertexCount = vertexCount;
this.indexCount = indexCount;
this.hasTexture = hasTexture;
}
HighPolyMesh() {
}
public boolean isNull() {
return vertexArray == null;
}
public int getVertexCount() {
return vertexCount;
}
public int getIndexCount() {
return indexCount;
}
public boolean getHasTexture() {
return hasTexture;
}
public int getAttribBits() {
return hasTexture ? (FixedFunctionState.STATE_HAS_ATTRIB_TEXTURE | FixedFunctionState.STATE_HAS_ATTRIB_NORMAL) : FixedFunctionState.STATE_HAS_ATTRIB_NORMAL;
}
}

View File

@ -3984,11 +3984,11 @@ public class EaglerDeferredPipeline {
}
public static final boolean isSupported() {
return EaglercraftGPU.checkHasHDRFramebufferSupport();
return EaglercraftGPU.checkHasHDRFramebufferSupportWithFilter();
}
public static final String getReasonUnsupported() {
if(!EaglercraftGPU.checkHasHDRFramebufferSupport()) {
if(!EaglercraftGPU.checkHasHDRFramebufferSupportWithFilter()) {
return I18n.format("shaders.gui.unsupported.reason.hdrFramebuffer");
}else {
return null;

View File

@ -0,0 +1,83 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import java.io.IOException;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.netty.Unpooled;
import net.minecraft.network.PacketBuffer;
/**
* Copyright (c) 2024 lax1dude. 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 CapePackets {
public static final int PACKET_MY_CAPE_PRESET = 0x01;
public static final int PACKET_MY_CAPE_CUSTOM = 0x02;
public static final int PACKET_GET_OTHER_CAPE = 0x03;
public static final int PACKET_OTHER_CAPE_PRESET = 0x04;
public static final int PACKET_OTHER_CAPE_CUSTOM = 0x05;
public static void readPluginMessage(PacketBuffer buffer, ServerCapeCache capeCache) throws IOException {
try {
int type = (int)buffer.readByte() & 0xFF;
switch(type) {
case PACKET_OTHER_CAPE_PRESET: {
EaglercraftUUID responseUUID = buffer.readUuid();
int responsePreset = buffer.readInt();
if(buffer.isReadable()) {
throw new IOException("PACKET_OTHER_CAPE_PRESET had " + buffer.readableBytes() + " remaining bytes!");
}
capeCache.cacheCapePreset(responseUUID, responsePreset);
break;
}
case PACKET_OTHER_CAPE_CUSTOM: {
EaglercraftUUID responseUUID = buffer.readUuid();
byte[] readCape = new byte[1173];
buffer.readBytes(readCape);
if(buffer.isReadable()) {
throw new IOException("PACKET_OTHER_CAPE_CUSTOM had " + buffer.readableBytes() + " remaining bytes!");
}
capeCache.cacheCapeCustom(responseUUID, readCape);
break;
}
default:
throw new IOException("Unknown skin packet type: " + type);
}
}catch(IOException ex) {
throw ex;
}catch(Throwable t) {
throw new IOException("Failed to parse cape packet!", t);
}
}
public static byte[] writeMyCapePreset(int capeId) {
return new byte[] { (byte) PACKET_MY_CAPE_PRESET, (byte) (capeId >> 24), (byte) (capeId >> 16),
(byte) (capeId >> 8), (byte) (capeId & 0xFF) };
}
public static byte[] writeMyCapeCustom(CustomCape customCape) {
byte[] packet = new byte[1 + customCape.texture.length];
packet[0] = (byte) PACKET_MY_CAPE_CUSTOM;
System.arraycopy(customCape.texture, 0, packet, 1, customCape.texture.length);
return packet;
}
public static PacketBuffer writeGetOtherCape(EaglercraftUUID playerId) throws IOException {
PacketBuffer ret = new PacketBuffer(Unpooled.buffer(17, 17));
ret.writeByte(PACKET_GET_OTHER_CAPE);
ret.writeUuid(playerId);
return ret;
}
}

View File

@ -0,0 +1,58 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import net.minecraft.client.Minecraft;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2024 lax1dude. 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 CustomCape {
public final String name;
public final byte[] texture;
private EaglerSkinTexture textureInstance;
private ResourceLocation resourceLocation;
private static int texId = 0;
public CustomCape(String name, byte[] texture) {
this.name = name;
this.texture = texture;
byte[] texture2 = new byte[4096];
SkinConverter.convertCape23x17RGBto32x32RGBA(texture, texture2);
this.textureInstance = new EaglerSkinTexture(texture2, 32, 32);
this.resourceLocation = null;
}
public void load() {
if(resourceLocation == null) {
resourceLocation = new ResourceLocation("eagler:capes/custom/tex_" + texId++);
Minecraft.getMinecraft().getTextureManager().loadTexture(resourceLocation, textureInstance);
}
}
public ResourceLocation getResource() {
return resourceLocation;
}
public void delete() {
if(resourceLocation != null) {
Minecraft.getMinecraft().getTextureManager().deleteTexture(resourceLocation);
resourceLocation = null;
}
}
}

View File

@ -0,0 +1,75 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2024 lax1dude. 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 enum DefaultCapes {
NO_CAPE(0, "No Cape", null),
MINECON_2011(1, "Minecon 2011", new ResourceLocation("eagler:capes/01.minecon_2011.png")),
MINECON_2012(2, "Minecon 2012", new ResourceLocation("eagler:capes/02.minecon_2012.png")),
MINECON_2013(3, "Minecon 2013", new ResourceLocation("eagler:capes/03.minecon_2013.png")),
MINECON_2015(4, "Minecon 2015", new ResourceLocation("eagler:capes/04.minecon_2015.png")),
MINECON_2016(5, "Minecon 2016", new ResourceLocation("eagler:capes/05.minecon_2016.png")),
MICROSOFT_ACCOUNT(6, "Microsoft Account", new ResourceLocation("eagler:capes/06.microsoft_account.png")),
MAPMAKER(7, "Realms Mapmaker", new ResourceLocation("eagler:capes/07.mapmaker.png")),
MOJANG_OLD(8, "Mojang Old", new ResourceLocation("eagler:capes/08.mojang_old.png")),
MOJANG_NEW(9, "Mojang New", new ResourceLocation("eagler:capes/09.mojang_new.png")),
JIRA_MOD(10, "Jira Moderator", new ResourceLocation("eagler:capes/10.jira_mod.png")),
MOJANG_VERY_OLD(11, "Mojang Very Old", new ResourceLocation("eagler:capes/11.mojang_very_old.png")),
SCROLLS(12, "Scrolls", new ResourceLocation("eagler:capes/12.scrolls.png")),
COBALT(13, "Cobalt", new ResourceLocation("eagler:capes/13.cobalt.png")),
TRANSLATOR(14, "Lang Translator", new ResourceLocation("eagler:capes/14.translator.png")),
MILLIONTH_ACCOUNT(15, "Millionth Player", new ResourceLocation("eagler:capes/15.millionth_account.png")),
PRISMARINE(16, "Prismarine", new ResourceLocation("eagler:capes/16.prismarine.png")),
SNOWMAN(17, "Snowman", new ResourceLocation("eagler:capes/17.snowman.png")),
SPADE(18, "Spade", new ResourceLocation("eagler:capes/18.spade.png")),
BIRTHDAY(19, "Birthday", new ResourceLocation("eagler:capes/19.birthday.png")),
DB(20, "dB", new ResourceLocation("eagler:capes/20.db.png"));
public static final DefaultCapes[] defaultCapesMap = new DefaultCapes[21];
public final int id;
public final String name;
public final ResourceLocation location;
private DefaultCapes(int id, String name, ResourceLocation location) {
this.id = id;
this.name = name;
this.location = location;
}
public static DefaultCapes getCapeFromId(int id) {
DefaultCapes e = null;
if(id >= 0 && id < defaultCapesMap.length) {
e = defaultCapesMap[id];
}
if(e != null) {
return e;
}else {
return NO_CAPE;
}
}
static {
DefaultCapes[] capes = values();
for(int i = 0; i < capes.length; ++i) {
defaultCapesMap[capes[i].id] = capes[i];
}
}
}

View File

@ -43,7 +43,14 @@ public enum DefaultSkins {
ZOMBIE(21, "Zombie", new ResourceLocation("eagler:skins/22.zombie.png"), SkinModel.ZOMBIE),
PIG(22, "Pig", new ResourceLocation("eagler:skins/23.pig.png"), SkinModel.STEVE),
MOOSHROOM(23, "Mooshroom", new ResourceLocation("eagler:skins/24.mooshroom.png"), SkinModel.STEVE);
// LONG_ARMS(24, "Long Arms", new ResourceLocation("eagler:mesh/longarms.fallback.png"), SkinModel.LONG_ARMS),
// WEIRD_CLIMBER_DUDE(25, "Weird Climber Dude", new ResourceLocation("eagler:mesh/weirdclimber.fallback.png"), SkinModel.WEIRD_CLIMBER_DUDE),
// LAXATIVE_DUDE(26, "Laxative Dude", new ResourceLocation("eagler:mesh/laxativedude.fallback.png"), SkinModel.LAXATIVE_DUDE),
// BABY_CHARLES(27, "Baby Charles", new ResourceLocation("eagler:mesh/charles.fallback.png"), SkinModel.BABY_CHARLES),
// BABY_WINSTON(28, "Baby Winston", new ResourceLocation("eagler:mesh/winston.fallback.png"), SkinModel.BABY_WINSTON);
// public static final DefaultSkins[] defaultSkinsMap = new DefaultSkins[29];
public static final DefaultSkins[] defaultSkinsMap = new DefaultSkins[24];
public final int id;

View File

@ -38,8 +38,13 @@ public class EaglerProfile {
public static int presetSkinId;
public static int customSkinId;
public static int presetCapeId;
public static int customCapeId;
public static final List<CustomSkin> customSkins = new ArrayList();
public static final List<CustomCape> customCapes = new ArrayList();
public static final EaglercraftRandom rand;
@ -81,6 +86,25 @@ public class EaglerProfile {
}
}
public static ResourceLocation getActiveCapeResourceLocation() {
if(presetCapeId == -1) {
if(customCapeId >= 0 && customCapeId < customCapes.size()) {
return customCapes.get(customCapeId).getResource();
}else {
customCapeId = -1;
presetCapeId = 0;
return DefaultCapes.defaultCapesMap[0].location;
}
}else {
if(presetCapeId >= 0 && presetCapeId < DefaultCapes.defaultCapesMap.length) {
return DefaultCapes.defaultCapesMap[presetCapeId].location;
}else {
presetCapeId = 0;
return DefaultCapes.defaultCapesMap[0].location;
}
}
}
public static EaglercraftUUID getPlayerUUID() {
return Minecraft.getMinecraft().getSession().getProfile().getId();
}
@ -116,6 +140,25 @@ public class EaglerProfile {
}
}
public static byte[] getCapePacket() {
if(presetCapeId == -1) {
if(customCapeId >= 0 && customCapeId < customCapes.size()) {
return CapePackets.writeMyCapeCustom(customCapes.get(customCapeId));
}else {
customCapeId = -1;
presetCapeId = 0;
return CapePackets.writeMyCapePreset(0);
}
}else {
if(presetCapeId >= 0 && presetCapeId < DefaultCapes.defaultCapesMap.length) {
return CapePackets.writeMyCapePreset(presetCapeId);
}else {
presetCapeId = 0;
return CapePackets.writeMyCapePreset(0);
}
}
}
private static boolean doesSkinExist(String name) {
for(int i = 0, l = customSkins.size(); i < l; ++i) {
if(customSkins.get(i).name.equalsIgnoreCase(name)) {
@ -125,6 +168,15 @@ public class EaglerProfile {
return false;
}
private static boolean doesCapeExist(String name) {
for(int i = 0, l = customCapes.size(); i < l; ++i) {
if(customCapes.get(i).name.equalsIgnoreCase(name)) {
return true;
}
}
return false;
}
public static int addCustomSkin(String fileName, byte[] rawSkin) {
if(doesSkinExist(fileName)) {
String newName;
@ -141,6 +193,22 @@ public class EaglerProfile {
return r;
}
public static int addCustomCape(String fileName, byte[] rawCape23x17RGB) {
if(doesCapeExist(fileName)) {
String newName;
int i = 2;
while(doesCapeExist(newName = fileName + " (" + i + ")")) {
++i;
}
fileName = newName;
}
CustomCape newCape = new CustomCape(fileName, rawCape23x17RGB);
newCape.load();
int r = customCapes.size();
customCapes.add(newCape);
return r;
}
public static void clearCustomSkins() {
for(int i = 0, l = customSkins.size(); i < l; ++i) {
customSkins.get(i).delete();
@ -148,6 +216,13 @@ public class EaglerProfile {
customSkins.clear();
}
public static void clearCustomCapes() {
for(int i = 0, l = customCapes.size(); i < l; ++i) {
customCapes.get(i).delete();
}
customCapes.clear();
}
public static void read() {
read(EagRuntime.getStorage("p"));
}
@ -195,6 +270,9 @@ public class EaglerProfile {
presetSkinId = profile.getInteger("presetSkin");
customSkinId = profile.getInteger("customSkin");
if(profile.hasKey("presetCape", 99)) presetCapeId = profile.getInteger("presetCape");
if(profile.hasKey("customCape", 99)) customCapeId = profile.getInteger("customCape");
String loadUsername = profile.getString("username").trim();
if(!loadUsername.isEmpty()) {
@ -220,6 +298,20 @@ public class EaglerProfile {
newSkin.load();
customSkins.add(newSkin);
}
if(profile.hasKey("capes", 9)) {
clearCustomCapes();
NBTTagList capesList = profile.getTagList("capes", 10);
for(int i = 0, l = capesList.tagCount(); i < l; ++i) {
NBTTagCompound cape = capesList.getCompoundTagAt(i);
String capeName = cape.getString("name");
byte[] capeData = cape.getByteArray("data");
if(capeData.length != 1173) continue;
CustomCape newCape = new CustomCape(capeName, capeData);
newCape.load();
customCapes.add(newCape);
}
}
if(presetSkinId == -1) {
if(customSkinId < 0 || customSkinId >= customSkins.size()) {
@ -239,6 +331,8 @@ public class EaglerProfile {
NBTTagCompound profile = new NBTTagCompound();
profile.setInteger("presetSkin", presetSkinId);
profile.setInteger("customSkin", customSkinId);
profile.setInteger("presetCape", presetCapeId);
profile.setInteger("customCape", customCapeId);
profile.setString("username", username);
NBTTagList skinsList = new NBTTagList();
for(int i = 0, l = customSkins.size(); i < l; ++i) {
@ -250,6 +344,15 @@ public class EaglerProfile {
skinsList.appendTag(skin);
}
profile.setTag("skins", skinsList);
NBTTagList capesList = new NBTTagList();
for(int i = 0, l = customCapes.size(); i < l; ++i) {
CustomCape cp = customCapes.get(i);
NBTTagCompound cape = new NBTTagCompound();
cape.setString("name", cp.name);
cape.setByteArray("data", cp.texture);
capesList.appendTag(cape);
}
profile.setTag("capes", capesList);
EaglerOutputStream bao = new EaglerOutputStream();
try {
CompressedStreamTools.writeCompressed(profile, bao);
@ -280,9 +383,13 @@ public class EaglerProfile {
setName(username);
presetSkinId = rand.nextInt(DefaultSkins.defaultSkinsMap.length);
do {
presetSkinId = rand.nextInt(DefaultSkins.defaultSkinsMap.length);
}while(DefaultSkins.defaultSkinsMap[presetSkinId].model.highPoly != null);
customSkinId = -1;
presetCapeId = 0;
customCapeId = -1;
}
}

View File

@ -0,0 +1,359 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.Keyboard;
import net.lax1dude.eaglercraft.v1_8.Mouse;
import net.lax1dude.eaglercraft.v1_8.internal.EnumCursorType;
import net.lax1dude.eaglercraft.v1_8.internal.FileChooserResult;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.lax1dude.eaglercraft.v1_8.opengl.ImageData;
import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
import java.io.IOException;
/**
* Copyright (c) 2022-2024 lax1dude. 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 GuiScreenEditCape extends GuiScreen {
private final GuiScreenEditProfile parent;
private boolean dropDownOpen = false;
private String[] dropDownOptions;
private int slotsVisible = 0;
protected int selectedSlot = 0;
private int scrollPos = -1;
private int skinsHeight = 0;
private boolean dragging = false;
private int mousex = 0;
private int mousey = 0;
private static final ResourceLocation eaglerGui = new ResourceLocation("eagler:gui/eagler_gui.png");
protected String screenTitle = "Edit Cape";
public GuiScreenEditCape(GuiScreenEditProfile parent) {
this.parent = parent;
updateOptions();
}
public void initGui() {
Keyboard.enableRepeatEvents(true);
screenTitle = I18n.format("editCape.title");
selectedSlot = EaglerProfile.presetCapeId == -1 ? EaglerProfile.customCapeId : (EaglerProfile.presetCapeId + EaglerProfile.customCapes.size());
buttonList.add(new GuiButton(0, width / 2 - 100, height / 6 + 168, I18n.format("gui.done")));
buttonList.add(new GuiButton(1, width / 2 - 21, height / 6 + 80, 71, 20, I18n.format("editCape.addCape")));
buttonList.add(new GuiButton(2, width / 2 - 21 + 71, height / 6 + 80, 72, 20, I18n.format("editCape.clearCape")));
}
private void updateOptions() {
int numCustom = EaglerProfile.customCapes.size();
String[] n = new String[numCustom + DefaultCapes.defaultCapesMap.length];
for(int i = 0; i < numCustom; ++i) {
n[i] = EaglerProfile.customCapes.get(i).name;
}
int numDefault = DefaultCapes.defaultCapesMap.length;
for(int j = 0; j < numDefault; ++j) {
n[numCustom + j] = DefaultCapes.defaultCapesMap[j].name;
}
dropDownOptions = n;
}
public void drawScreen(int mx, int my, float partialTicks) {
drawDefaultBackground();
drawCenteredString(fontRendererObj, screenTitle, width / 2, 15, 16777215);
drawString(fontRendererObj, I18n.format("editCape.playerCape"), width / 2 - 20, height / 6 + 36, 10526880);
mousex = mx;
mousey = my;
int skinX = width / 2 - 120;
int skinY = height / 6 + 8;
int skinWidth = 80;
int skinHeight = 130;
drawRect(skinX, skinY, skinX + skinWidth, skinY + skinHeight, 0xFFA0A0A0);
drawRect(skinX + 1, skinY + 1, skinX + skinWidth - 1, skinY + skinHeight - 1, 0xFF000015);
int skid = selectedSlot - EaglerProfile.customCapes.size();
if(skid < 0) {
skid = 0;
}
if(dropDownOpen) {
super.drawScreen(0, 0, partialTicks);
}else {
super.drawScreen(mx, my, partialTicks);
}
int numberOfCustomSkins = EaglerProfile.customSkins.size();
int numberOfCustomCapes = EaglerProfile.customCapes.size();
ResourceLocation skinTexture;
SkinModel model;
if(parent.selectedSlot < numberOfCustomSkins) {
CustomSkin customSkin = EaglerProfile.customSkins.get(parent.selectedSlot);
skinTexture = customSkin.getResource();
model = customSkin.model;
}else {
DefaultSkins defaultSkin = DefaultSkins.getSkinFromId(parent.selectedSlot - numberOfCustomSkins);
skinTexture = defaultSkin.location;
model = defaultSkin.model;
}
if(model.highPoly != null) {
drawCenteredString(fontRendererObj, I18n.format(this.mc.gameSettings.enableFNAWSkins ? "editProfile.disableFNAW" : "editProfile.enableFNAW"), width / 2, height / 6 + 150, 10526880);
}
skinX = width / 2 - 20;
skinY = height / 6 + 52;
skinWidth = 140;
skinHeight = 22;
drawRect(skinX, skinY, skinX + skinWidth, skinY + skinHeight, -6250336);
drawRect(skinX + 1, skinY + 1, skinX + skinWidth - 21, skinY + skinHeight - 1, -16777216);
drawRect(skinX + skinWidth - 20, skinY + 1, skinX + skinWidth - 1, skinY + skinHeight - 1, -16777216);
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
mc.getTextureManager().bindTexture(eaglerGui);
drawTexturedModalRect(skinX + skinWidth - 18, skinY + 3, 0, 0, 16, 16);
drawString(fontRendererObj, dropDownOptions[selectedSlot], skinX + 5, skinY + 7, 14737632);
skinX = width / 2 - 20;
skinY = height / 6 + 73;
skinWidth = 140;
skinHeight = (height - skinY - 10);
slotsVisible = (skinHeight / 10);
if(slotsVisible > dropDownOptions.length) slotsVisible = dropDownOptions.length;
skinHeight = slotsVisible * 10 + 7;
skinsHeight = skinHeight;
if(scrollPos == -1) {
scrollPos = selectedSlot - 2;
}
if(scrollPos > (dropDownOptions.length - slotsVisible)) {
scrollPos = (dropDownOptions.length - slotsVisible);
}
if(scrollPos < 0) {
scrollPos = 0;
}
if(dropDownOpen) {
drawRect(skinX, skinY, skinX + skinWidth, skinY + skinHeight, -6250336);
drawRect(skinX + 1, skinY + 1, skinX + skinWidth - 1, skinY + skinHeight - 1, -16777216);
for(int i = 0; i < slotsVisible; i++) {
if(i + scrollPos < dropDownOptions.length) {
if(selectedSlot == i + scrollPos) {
drawRect(skinX + 1, skinY + i*10 + 4, skinX + skinWidth - 1, skinY + i*10 + 14, 0x77ffffff);
}else if(mx >= skinX && mx < (skinX + skinWidth - 10) && my >= (skinY + i*10 + 5) && my < (skinY + i*10 + 15)) {
drawRect(skinX + 1, skinY + i*10 + 4, skinX + skinWidth - 1, skinY + i*10 + 14, 0x55ffffff);
}
drawString(fontRendererObj, dropDownOptions[i + scrollPos], skinX + 5, skinY + 5 + i*10, 14737632);
}
}
int scrollerSize = skinHeight * slotsVisible / dropDownOptions.length;
int scrollerPos = skinHeight * scrollPos / dropDownOptions.length;
drawRect(skinX + skinWidth - 4, skinY + scrollerPos + 1, skinX + skinWidth - 1, skinY + scrollerPos + scrollerSize, 0xff888888);
}
if(!EagRuntime.getConfiguration().isDemo()) {
GlStateManager.pushMatrix();
GlStateManager.scale(0.75f, 0.75f, 0.75f);
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
String text = I18n.format("editProfile.importExport");
int w = mc.fontRendererObj.getStringWidth(text);
boolean hover = mx > 1 && my > 1 && mx < (w * 3 / 4) + 7 && my < 12;
if(hover) {
Mouse.showCursor(EnumCursorType.HAND);
}
drawString(mc.fontRendererObj, EnumChatFormatting.UNDERLINE + text, 5, 5, hover ? 0xFFEEEE22 : 0xFFCCCCCC);
GlStateManager.popMatrix();
}
int xx = width / 2 - 80;
int yy = height / 6 + 130;
skinX = this.width / 2 - 120;
skinY = this.height / 6 + 8;
skinWidth = 80;
skinHeight = 130;
ResourceLocation capeTexture;
if(selectedSlot < numberOfCustomCapes) {
capeTexture = EaglerProfile.customCapes.get(selectedSlot).getResource();
}else {
capeTexture = DefaultCapes.getCapeFromId(selectedSlot - numberOfCustomCapes).location;
}
SkinPreviewRenderer.renderPreview(xx, yy, mx, my, true, model, skinTexture, capeTexture);
}
public void handleMouseInput() throws IOException {
super.handleMouseInput();
if(dropDownOpen) {
int var1 = Mouse.getEventDWheel();
if(var1 < 0) {
scrollPos += 3;
}
if(var1 > 0) {
scrollPos -= 3;
if(scrollPos < 0) {
scrollPos = 0;
}
}
}
}
protected void actionPerformed(GuiButton par1GuiButton) {
if(!dropDownOpen) {
if(par1GuiButton.id == 0) {
safeProfile();
this.mc.displayGuiScreen((GuiScreen) parent);
}else if(par1GuiButton.id == 1) {
EagRuntime.displayFileChooser("image/png", "png");
}else if(par1GuiButton.id == 2) {
EaglerProfile.clearCustomCapes();
safeProfile();
updateOptions();
selectedSlot = 0;
}
}
}
public void updateScreen() {
if(EagRuntime.fileChooserHasResult()) {
FileChooserResult result = EagRuntime.getFileChooserResult();
if(result != null) {
ImageData loadedCape = ImageData.loadImageFile(result.fileData);
if(loadedCape != null) {
if((loadedCape.width == 32 || loadedCape.width == 64) && loadedCape.height == 32) {
byte[] resized = new byte[1173];
SkinConverter.convertCape32x32RGBAto23x17RGB(loadedCape, resized);
int k;
if((k = EaglerProfile.addCustomCape(result.fileName, resized)) != -1) {
selectedSlot = k;
updateOptions();
safeProfile();
}
}else {
EagRuntime.showPopup("The selected image '" + result.fileName + "' is not the right size!\nEaglercraft only supports 32x32 or 64x32 capes");
}
}else {
EagRuntime.showPopup("The selected file '" + result.fileName + "' is not a PNG file!");
}
}
}
if(dropDownOpen) {
if(Mouse.isButtonDown(0)) {
int skinX = width / 2 - 20;
int skinY = height / 6 + 73;
int skinWidth = 140;
if(mousex >= (skinX + skinWidth - 10) && mousex < (skinX + skinWidth) && mousey >= skinY && mousey < (skinY + skinsHeight)) {
dragging = true;
}
if(dragging) {
int scrollerSize = skinsHeight * slotsVisible / dropDownOptions.length;
scrollPos = (mousey - skinY - (scrollerSize / 2)) * dropDownOptions.length / skinsHeight;
}
}else {
dragging = false;
}
}else {
dragging = false;
}
}
public void onGuiClosed() {
Keyboard.enableRepeatEvents(false);
}
protected void keyTyped(char c, int k) {
if(k == 200 && selectedSlot > 0) {
--selectedSlot;
scrollPos = selectedSlot - 2;
}
if(k == 208 && selectedSlot < (dropDownOptions.length - 1)) {
++selectedSlot;
scrollPos = selectedSlot - 2;
}
}
protected void mouseClicked(int mx, int my, int button) {
if (button == 0) {
if(!EagRuntime.getConfiguration().isDemo()) {
int w = mc.fontRendererObj.getStringWidth(I18n.format("editProfile.importExport"));
if(mx > 1 && my > 1 && mx < (w * 3 / 4) + 7 && my < 12) {
safeProfile();
mc.displayGuiScreen(new GuiScreenImportExportProfile(parent));
mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
return;
}
}
int skinX = width / 2 + 140 - 40;
int skinY = height / 6 + 52;
if(mx >= skinX && mx < (skinX + 20) && my >= skinY && my < (skinY + 22)) {
dropDownOpen = !dropDownOpen;
return;
}
skinX = width / 2 - 20;
skinY = height / 6 + 52;
int skinWidth = 140;
int skinHeight = skinsHeight;
if(!(mx >= skinX && mx < (skinX + skinWidth) && my >= skinY && my < (skinY + skinHeight + 22))) {
dragging = false;
if(dropDownOpen) {
dropDownOpen = false;
return;
}
}else if(dropDownOpen && !dragging) {
skinY += 21;
for(int i = 0; i < slotsVisible; i++) {
if(i + scrollPos < dropDownOptions.length) {
if(mx >= skinX && mx < (skinX + skinWidth - 10) && my >= (skinY + i * 10 + 5) && my < (skinY + i * 10 + 15) && selectedSlot != i + scrollPos) {
selectedSlot = i + scrollPos;
dropDownOpen = false;
dragging = false;
return;
}
}
}
}
}
super.mouseClicked(mx, my, button);
}
protected void safeProfile() {
int customLen = EaglerProfile.customCapes.size();
if(selectedSlot < customLen) {
EaglerProfile.presetCapeId = -1;
EaglerProfile.customCapeId = selectedSlot;
}else {
EaglerProfile.presetCapeId = selectedSlot - customLen;
EaglerProfile.customCapeId = -1;
}
}
}

View File

@ -42,7 +42,7 @@ public class GuiScreenEditProfile extends GuiScreen {
private boolean dropDownOpen = false;
private String[] dropDownOptions;
private int slotsVisible = 0;
private int selectedSlot = 0;
protected int selectedSlot = 0;
private int scrollPos = -1;
private int skinsHeight = 0;
private boolean dragging = false;
@ -102,10 +102,24 @@ public class GuiScreenEditProfile extends GuiScreen {
drawRect(skinX, skinY, skinX + skinWidth, skinY + skinHeight, 0xFFA0A0A0);
drawRect(skinX + 1, skinY + 1, skinX + skinWidth - 1, skinY + skinHeight - 1, 0xFF000015);
int skid = selectedSlot - EaglerProfile.customSkins.size();
if(skid < 0) {
skid = 0;
GlStateManager.pushMatrix();
GlStateManager.translate(skinX + 2, skinY - 9, 0.0f);
GlStateManager.scale(0.75f, 0.75f, 0.75f);
int numberOfCustomSkins = EaglerProfile.customSkins.size();
int skid = selectedSlot - numberOfCustomSkins;
SkinModel selectedSkinModel = skid < 0 ? EaglerProfile.customSkins.get(selectedSlot).model : DefaultSkins.getSkinFromId(skid).model;
if(selectedSkinModel == SkinModel.STEVE || selectedSkinModel == SkinModel.ALEX || (selectedSkinModel.highPoly != null && !this.mc.gameSettings.enableFNAWSkins)) {
String capesText = I18n.format("editProfile.capes");
int color = 10526880;
if(mx > skinX - 10 && my > skinY - 16 && mx < skinX + (fontRendererObj.getStringWidth(capesText) * 0.75f) + 10 && my < skinY + 7) {
color = 0xFFCCCC44;
Mouse.showCursor(EnumCursorType.HAND);
}
this.drawString(this.fontRendererObj, EnumChatFormatting.UNDERLINE + capesText, 0, 0, color);
}
GlStateManager.popMatrix();
usernameField.drawTextBox();
if(dropDownOpen || newSkinWaitSteveOrAlex) {
@ -113,6 +127,10 @@ public class GuiScreenEditProfile extends GuiScreen {
}else {
super.drawScreen(mx, my, partialTicks);
}
if(selectedSkinModel.highPoly != null) {
drawCenteredString(fontRendererObj, I18n.format(this.mc.gameSettings.enableFNAWSkins ? "editProfile.disableFNAW" : "editProfile.enableFNAW"), width / 2, height / 6 + 150, 10526880);
}
skinX = width / 2 - 20;
skinY = height / 6 + 82;
@ -184,7 +202,6 @@ public class GuiScreenEditProfile extends GuiScreen {
int xx = width / 2 - 80;
int yy = height / 6 + 130;
int numberOfCustomSkins = EaglerProfile.customSkins.size();
if(newSkinWaitSteveOrAlex && selectedSlot < numberOfCustomSkins) {
skinWidth = 70;
@ -217,8 +234,8 @@ public class GuiScreenEditProfile extends GuiScreen {
drawCenteredString(fontRendererObj, "Steve", skinX + skinWidth / 2, skinY + skinHeight + 6, cc);
}
mc.getTextureManager().bindTexture(newSkin.getResource());
SkinPreviewRenderer.renderBiped(xx, yy, mx, my, SkinModel.STEVE);
SkinPreviewRenderer.renderPreview(xx, yy, mx, my, false, SkinModel.STEVE, newSkin.getResource(),
EaglerProfile.getActiveCapeResourceLocation());
skinX = width / 2 + 20;
skinY = height / 4;
@ -242,8 +259,8 @@ public class GuiScreenEditProfile extends GuiScreen {
drawCenteredString(fontRendererObj, "Alex", skinX + skinWidth / 2, skinY + skinHeight + 8, cc);
}
mc.getTextureManager().bindTexture(newSkin.getResource());
SkinPreviewRenderer.renderBiped(xx, yy, mx, my, SkinModel.ALEX);
SkinPreviewRenderer.renderPreview(xx, yy, mx, my, false, SkinModel.ALEX, newSkin.getResource(),
EaglerProfile.getActiveCapeResourceLocation());
}else {
skinX = this.width / 2 - 120;
skinY = this.height / 6 + 8;
@ -251,20 +268,17 @@ public class GuiScreenEditProfile extends GuiScreen {
skinHeight = 130;
ResourceLocation texture;
SkinModel model;
if(selectedSlot < numberOfCustomSkins) {
CustomSkin customSkin = EaglerProfile.customSkins.get(selectedSlot);
texture = customSkin.getResource();
model = customSkin.model;
if(skid < 0) {
texture = EaglerProfile.customSkins.get(selectedSlot).getResource();
}else {
DefaultSkins defaultSkin = DefaultSkins.defaultSkinsMap[selectedSlot - numberOfCustomSkins];
texture = defaultSkin.location;
model = defaultSkin.model;
texture = DefaultSkins.getSkinFromId(skid).location;
}
mc.getTextureManager().bindTexture(texture);
SkinPreviewRenderer.renderBiped(xx, yy, newSkinWaitSteveOrAlex ? width / 2 : mx, newSkinWaitSteveOrAlex ? height / 2 : my, model);
SkinPreviewRenderer.renderPreview(xx, yy, newSkinWaitSteveOrAlex ? width / 2 : mx,
newSkinWaitSteveOrAlex ? height / 2 : my, false, selectedSkinModel, texture,
EaglerProfile.getActiveCapeResourceLocation());
}
}
public void handleMouseInput() throws IOException {
@ -287,12 +301,14 @@ public class GuiScreenEditProfile extends GuiScreen {
if(!dropDownOpen) {
if(par1GuiButton.id == 0) {
safeProfile();
EaglerProfile.save();
this.mc.displayGuiScreen((GuiScreen) parent);
}else if(par1GuiButton.id == 1) {
EagRuntime.displayFileChooser("image/png", "png");
}else if(par1GuiButton.id == 2) {
EaglerProfile.clearCustomSkins();
safeProfile();
EaglerProfile.save();
updateOptions();
selectedSlot = 0;
}
@ -335,6 +351,7 @@ public class GuiScreenEditProfile extends GuiScreen {
newSkinWaitSteveOrAlex = true;
updateOptions();
safeProfile();
EaglerProfile.save();
}
}else {
EagRuntime.showPopup("The selected image '" + result.fileName + "' is not the right size!\nEaglercraft only supports 64x32 or 64x64 skins");
@ -387,21 +404,37 @@ public class GuiScreenEditProfile extends GuiScreen {
}
protected void mouseClicked(int mx, int my, int button) {
super.mouseClicked(mx, my, button);
usernameField.mouseClicked(mx, my, button);
if (button == 0) {
if(!EagRuntime.getConfiguration().isDemo()) {
int w = mc.fontRendererObj.getStringWidth(I18n.format("editProfile.importExport"));
if(mx > 1 && my > 1 && mx < (w * 3 / 4) + 7 && my < 12) {
safeProfile();
EaglerProfile.save();
mc.displayGuiScreen(new GuiScreenImportExportProfile(this));
mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
return;
}
}
int skinX, skinY;
int skid = selectedSlot - EaglerProfile.customSkins.size();
SkinModel selectedSkinModel = skid < 0 ? EaglerProfile.customSkins.get(selectedSlot).model : DefaultSkins.getSkinFromId(skid).model;
if(selectedSkinModel == SkinModel.STEVE || selectedSkinModel == SkinModel.ALEX || (selectedSkinModel.highPoly != null && !this.mc.gameSettings.enableFNAWSkins)) {
skinX = this.width / 2 - 120;
skinY = this.height / 6 + 8;
String capesText = I18n.format("editProfile.capes");
if(mx > skinX - 10 && my > skinY - 16 && mx < skinX + (fontRendererObj.getStringWidth(capesText) * 0.75f) + 10 && my < skinY + 7) {
safeProfile();
this.mc.displayGuiScreen(new GuiScreenEditCape(this));
mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
return;
}
}
if(newSkinWaitSteveOrAlex) {
int skinX = width / 2 - 90;
int skinY = height / 4;
skinX = width / 2 - 90;
skinY = height / 4;
int skinWidth = 70;
int skinHeight = 120;
if(mx >= skinX && my >= skinY && mx < skinX + skinWidth && my < skinY + skinHeight) {
@ -423,8 +456,8 @@ public class GuiScreenEditProfile extends GuiScreen {
}
return;
}else if(selectedSlot < EaglerProfile.customSkins.size()) {
int skinX = width / 2 - 120;
int skinY = height / 6 + 18;
skinX = width / 2 - 120;
skinY = height / 6 + 18;
int skinWidth = 80;
int skinHeight = 120;
if(mx >= skinX && my >= skinY && mx < skinX + skinWidth && my < skinY + skinHeight) {
@ -434,8 +467,8 @@ public class GuiScreenEditProfile extends GuiScreen {
}
}
}
int skinX = width / 2 + 140 - 40;
int skinY = height / 6 + 82;
skinX = width / 2 + 140 - 40;
skinY = height / 6 + 82;
if(mx >= skinX && mx < (skinX + 20) && my >= skinY && my < (skinY + 22)) {
dropDownOpen = !dropDownOpen;
@ -448,27 +481,26 @@ public class GuiScreenEditProfile extends GuiScreen {
int skinHeight = skinsHeight;
if(!(mx >= skinX && mx < (skinX + skinWidth) && my >= skinY && my < (skinY + skinHeight + 22))) {
dropDownOpen = false;
dragging = false;
return;
}
skinY += 21;
if(dropDownOpen && !dragging) {
if(dropDownOpen) {
dropDownOpen = false;
return;
}
}else if(dropDownOpen && !dragging) {
skinY += 21;
for(int i = 0; i < slotsVisible; i++) {
if(i + scrollPos < dropDownOptions.length) {
if(selectedSlot != i + scrollPos) {
if(mx >= skinX && mx < (skinX + skinWidth - 10) && my >= (skinY + i * 10 + 5) && my < (skinY + i * 10 + 15) && selectedSlot != i + scrollPos) {
selectedSlot = i + scrollPos;
dropDownOpen = false;
dragging = false;
}
if(mx >= skinX && mx < (skinX + skinWidth - 10) && my >= (skinY + i * 10 + 5) && my < (skinY + i * 10 + 15)) {
selectedSlot = i + scrollPos;
dropDownOpen = false;
dragging = false;
return;
}
}
}
}
}
super.mouseClicked(mx, my, button);
}
protected void safeProfile() {
@ -488,7 +520,6 @@ public class GuiScreenEditProfile extends GuiScreen {
name = name.substring(0, 16);
}
EaglerProfile.setName(name);
EaglerProfile.save();
}
}

View File

@ -0,0 +1,119 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2022-2024 lax1dude. 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 enum HighPolySkin {
// disable fnaw skins
LONG_ARMS(null, null, null, null, null, null, 0.0f, null),
WEIRD_CLIMBER_DUDE(null, null, null, null, null, null, 0.0f, null),
LAXATIVE_DUDE(null, null, null, null, null, null, 0.0f, null),
BABY_CHARLES(null, null, null, null, null, null, 0.0f, null),
BABY_WINSTON(null, null, null, null, null, null, 0.0f, null);
// LONG_ARMS(
// new ResourceLocation("eagler:mesh/longarms.png"),
// new ResourceLocation("eagler:mesh/longarms0.mdl"),
// null,
// new ResourceLocation("eagler:mesh/longarms2.mdl"),
// new ResourceLocation[] {
// new ResourceLocation("eagler:mesh/longarms1.mdl")
// },
// new float[] {
// 1.325f
// },
// 0.0f,
// new ResourceLocation("eagler:mesh/longarms.fallback.png")
// ),
// WEIRD_CLIMBER_DUDE(
// new ResourceLocation("eagler:mesh/weirdclimber.png"),
// new ResourceLocation("eagler:mesh/weirdclimber0.mdl"),
// null,
// new ResourceLocation("eagler:mesh/weirdclimber2.mdl"),
// new ResourceLocation[] {
// new ResourceLocation("eagler:mesh/weirdclimber1.mdl")
// },
// new float[] {
// 2.62f
// },
// -90.0f,
// new ResourceLocation("eagler:mesh/weirdclimber.fallback.png")
// ),
// LAXATIVE_DUDE(
// new ResourceLocation("eagler:mesh/laxativedude.png"),
// new ResourceLocation("eagler:mesh/laxativedude0.mdl"),
// null,
// new ResourceLocation("eagler:mesh/laxativedude3.mdl"),
// new ResourceLocation[] {
// new ResourceLocation("eagler:mesh/laxativedude1.mdl"),
// new ResourceLocation("eagler:mesh/laxativedude2.mdl")
// },
// new float[] {
// 2.04f
// },
// 0.0f,
// new ResourceLocation("eagler:mesh/laxativedude.fallback.png")
// ),
// BABY_CHARLES(
// new ResourceLocation("eagler:mesh/charles.png"),
// new ResourceLocation("eagler:mesh/charles0.mdl"),
// new ResourceLocation("eagler:mesh/charles1.mdl"),
// new ResourceLocation("eagler:mesh/charles2.mdl"),
// new ResourceLocation[] {},
// new float[] {},
// 0.0f,
// new ResourceLocation("eagler:mesh/charles.fallback.png")
// ),
// BABY_WINSTON(
// new ResourceLocation("eagler:mesh/winston.png"),
// new ResourceLocation("eagler:mesh/winston0.mdl"),
// null,
// new ResourceLocation("eagler:mesh/winston1.mdl"),
// new ResourceLocation[] {},
// new float[] {},
// 0.0f,
// new ResourceLocation("eagler:mesh/winston.fallback.png")
// );
public static float highPolyScale = 0.5f;
public final ResourceLocation texture;
public final ResourceLocation bodyModel;
public final ResourceLocation headModel;
public final ResourceLocation eyesModel;
public final ResourceLocation[] limbsModel;
public final float[] limbsOffset;
public final float limbsInitialRotation;
public final ResourceLocation fallbackTexture;
HighPolySkin(ResourceLocation texture, ResourceLocation bodyModel, ResourceLocation headModel, ResourceLocation eyesModel,
ResourceLocation[] limbsModel, float[] limbsOffset, float limbsInitialRotation, ResourceLocation fallbackTexture) {
this.texture = texture;
this.bodyModel = bodyModel;
this.headModel = headModel;
this.eyesModel = eyesModel;
this.limbsModel = limbsModel;
this.limbsOffset = limbsOffset;
this.limbsInitialRotation = limbsInitialRotation;
this.fallbackTexture = fallbackTexture;
}
}

View File

@ -0,0 +1,471 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.opengl.EaglerMeshLoader;
import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.lax1dude.eaglercraft.v1_8.opengl.OpenGlHelper;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager;
import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.AbstractClientPlayer;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.entity.RenderPlayer;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.MathHelper;
/**
* Copyright (c) 2022-2024 lax1dude. 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 RenderHighPoly extends RenderPlayer {
private static final Logger logger = LogManager.getLogger("RenderHighPoly");
public RenderHighPoly(RenderManager renderManager, ModelBase fallbackModel, float fallbackScale) {
super(renderManager, fallbackModel, fallbackScale);
}
private static final Matrix4f tmpMatrix = new Matrix4f();
public void doRender(AbstractClientPlayer abstractclientplayer, double d0, double d1, double d2, float f,
float f1) {
if (!abstractclientplayer.isUser() || this.renderManager.livingPlayer == abstractclientplayer) {
double nameY = d1;
HighPolySkin highPolySkin = abstractclientplayer.getEaglerSkinModel().highPoly;
if(highPolySkin == null) {
super.doRender(abstractclientplayer, d0, d1, d2, f, f1);
return;
}else if(highPolySkin == HighPolySkin.LAXATIVE_DUDE) {
nameY += 0.1;
}else if(highPolySkin == HighPolySkin.BABY_WINSTON) {
nameY -= 1.0;
}
GlStateManager.pushMatrix();
GlStateManager.disableCull();
try {
Minecraft mc = Minecraft.getMinecraft();
float f2 = this.interpolateRotation(abstractclientplayer.prevRenderYawOffset, abstractclientplayer.renderYawOffset,
f1);
float f3 = this.interpolateRotation(abstractclientplayer.prevRotationYawHead, abstractclientplayer.rotationYawHead,
f1);
float f4 = f3 - f2;
if (abstractclientplayer.isRiding() && abstractclientplayer.ridingEntity instanceof EntityLivingBase) {
EntityLivingBase entitylivingbase1 = (EntityLivingBase) abstractclientplayer.ridingEntity;
f2 = this.interpolateRotation(entitylivingbase1.prevRenderYawOffset, entitylivingbase1.renderYawOffset,
f1);
f4 = f3 - f2;
float f5 = MathHelper.wrapAngleTo180_float(f4);
if (f5 < -85.0F) {
f5 = -85.0F;
}
if (f5 >= 85.0F) {
f5 = 85.0F;
}
f2 = f3 - f5;
if (f5 * f5 > 2500.0F) {
f2 += f5 * 0.2F;
}
}
this.renderLivingAt(abstractclientplayer, d0, d1, d2);
float f10 = this.handleRotationFloat(abstractclientplayer, f1);
this.rotateCorpse(abstractclientplayer, f10, f2, f1);
GlStateManager.enableRescaleNormal();
this.preRenderCallback(abstractclientplayer, f1);
float f6 = 0.0625F;
GlStateManager.scale(HighPolySkin.highPolyScale, HighPolySkin.highPolyScale, HighPolySkin.highPolyScale);
mc.getTextureManager().bindTexture(highPolySkin.texture);
if(abstractclientplayer.isPlayerSleeping()) {
if(highPolySkin == HighPolySkin.LAXATIVE_DUDE || highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) {
GlStateManager.translate(0.0f, -3.7f, 0.0f);
}else if(highPolySkin == HighPolySkin.BABY_WINSTON) {
GlStateManager.translate(0.0f, -2.4f, 0.0f);
}else {
GlStateManager.translate(0.0f, -3.0f, 0.0f);
}
}
float var15 = abstractclientplayer.prevLimbSwingAmount + (abstractclientplayer.limbSwingAmount - abstractclientplayer.prevLimbSwingAmount) * f1;
float var16 = abstractclientplayer.limbSwing - abstractclientplayer.limbSwingAmount * (1.0F - f1);
if(highPolySkin == HighPolySkin.LONG_ARMS) {
GlStateManager.rotate(MathHelper.sin(var16) * 20f * var15, 0.0f, 1.0f, 0.0f);
GlStateManager.rotate(MathHelper.cos(var16) * 7f * var15, 0.0f, 0.0f, 1.0f);
}else if(highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) {
GlStateManager.rotate(MathHelper.sin(var16) * 7f * var15, 0.0f, 1.0f, 0.0f);
GlStateManager.rotate(MathHelper.cos(var16) * 3f * var15, 0.0f, 0.0f, 1.0f);
GlStateManager.rotate(-f3, 0.0f, 1.0f, 0.0f);
float xd = (float)(abstractclientplayer.posX - abstractclientplayer.prevPosX);
GlStateManager.rotate(xd * 70.0f * var15, 0.0f, 0.0f, 1.0f);
float zd = (float)(abstractclientplayer.posZ - abstractclientplayer.prevPosZ);
GlStateManager.rotate(zd * 70.0f * var15, 1.0f, 0.0f, 0.0f);
GlStateManager.rotate(f3, 0.0f, 1.0f, 0.0f);
}else if(highPolySkin == HighPolySkin.LAXATIVE_DUDE) {
GlStateManager.rotate(-f3, 0.0f, 1.0f, 0.0f);
float xd = (float)(abstractclientplayer.posX - abstractclientplayer.prevPosX);
GlStateManager.rotate(-xd * 40.0f * var15, 0.0f, 0.0f, 1.0f);
float zd = (float)(abstractclientplayer.posZ - abstractclientplayer.prevPosZ);
GlStateManager.rotate(-zd * 40.0f * var15, 1.0f, 0.0f, 0.0f);
GlStateManager.rotate(f3, 0.0f, 1.0f, 0.0f);
}else if(highPolySkin == HighPolySkin.BABY_WINSTON) {
GlStateManager.translate(0.0f, (MathHelper.cos(f10 % 100000.0f) + 1.0f) * var15 * 0.2f, 0.0f);
GlStateManager.rotate(MathHelper.sin(var16) * 5f * var15, 0.0f, 1.0f, 0.0f);
GlStateManager.rotate(MathHelper.cos(var16) * 5f * var15, 0.0f, 0.0f, 1.0f);
}
if (abstractclientplayer.hurtTime > 0 || abstractclientplayer.deathTime > 0) {
GlStateManager.color(1.2f, 0.8F, 0.8F, 1.0F);
}
if(DeferredStateManager.isInDeferredPass()) {
DeferredStateManager.setDefaultMaterialConstants();
DeferredStateManager.setRoughnessConstant(0.5f);
DeferredStateManager.setMetalnessConstant(0.05f);
}
if(highPolySkin.bodyModel != null) {
EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(highPolySkin.bodyModel));
}
float jumpFactor = 0.0f;
if(highPolySkin.headModel != null) {
if(highPolySkin == HighPolySkin.BABY_CHARLES) {
long millis = System.currentTimeMillis();
float partialTicks = (float) ((millis - abstractclientplayer.eaglerHighPolyAnimationTick) * 0.02);
//long l50 = millis / 50l * 50l;
//boolean runTick = par1EntityPlayer.eaglerHighPolyAnimationTick < l50 && millis >= l50;
abstractclientplayer.eaglerHighPolyAnimationTick = millis;
if(partialTicks < 0.0f) {
partialTicks = 0.0f;
}
if(partialTicks > 1.0f) {
partialTicks = 1.0f;
}
float jumpFac = (float)(abstractclientplayer.posY - abstractclientplayer.prevPosY);
if(jumpFac < 0.0f && !abstractclientplayer.isCollidedVertically) {
jumpFac = -jumpFac;
jumpFac *= 0.1f;
}
jumpFac -= 0.05f;
if(jumpFac > 0.1f && !abstractclientplayer.isCollidedVertically) {
jumpFac = 0.1f;
}else if(jumpFac < 0.0f) {
jumpFac = 0.0f;
}else if(jumpFac > 0.1f && abstractclientplayer.isCollidedVertically) {
jumpFac = 0.1f;
}else if(jumpFac > 0.4f) {
jumpFac = 0.4f;
}
jumpFac *= 10.0f;
abstractclientplayer.eaglerHighPolyAnimationFloat3 += (jumpFac / (jumpFac + 1.0f)) * 6.0f * partialTicks;
if(Float.isInfinite(abstractclientplayer.eaglerHighPolyAnimationFloat3)) {
abstractclientplayer.eaglerHighPolyAnimationFloat3 = 1.0f;
}else if(abstractclientplayer.eaglerHighPolyAnimationFloat3 > 1.0f) {
abstractclientplayer.eaglerHighPolyAnimationFloat3 = 1.0f;
}else if(abstractclientplayer.eaglerHighPolyAnimationFloat3 < -1.0f) {
abstractclientplayer.eaglerHighPolyAnimationFloat3 = -1.0f;
}
abstractclientplayer.eaglerHighPolyAnimationFloat2 += abstractclientplayer.eaglerHighPolyAnimationFloat3 * partialTicks;
abstractclientplayer.eaglerHighPolyAnimationFloat5 += partialTicks;
while(abstractclientplayer.eaglerHighPolyAnimationFloat5 > 0.05f) {
abstractclientplayer.eaglerHighPolyAnimationFloat5 -= 0.05f;
abstractclientplayer.eaglerHighPolyAnimationFloat3 *= 0.99f;
abstractclientplayer.eaglerHighPolyAnimationFloat2 *= 0.9f;
}
jumpFactor = abstractclientplayer.eaglerHighPolyAnimationFloat2; //(abstractclientplayer.eaglerHighPolyAnimationFloat1 - abstractclientplayer.eaglerHighPolyAnimationFloat2) * partialTicks + abstractclientplayer.eaglerHighPolyAnimationFloat2;
jumpFactor -= 0.12f;
if(jumpFactor < 0.0f) {
jumpFactor = 0.0f;
}
jumpFactor = jumpFactor / (jumpFactor + 2.0f);
if(jumpFactor > 1.0f) {
jumpFactor = 1.0f;
}
}
if(jumpFactor > 0.0f) {
GlStateManager.pushMatrix();
GlStateManager.translate(0.0f, jumpFactor * 3.0f, 0.0f);
}
EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(highPolySkin.headModel));
if(jumpFactor > 0.0f) {
GlStateManager.popMatrix();
}
}
if(highPolySkin.limbsModel != null && highPolySkin.limbsModel.length > 0) {
for(int i = 0; i < highPolySkin.limbsModel.length; ++i) {
DeferredStateManager.setRoughnessConstant(0.023f);
DeferredStateManager.setMetalnessConstant(0.902f);
float offset = 0.0f;
if(highPolySkin.limbsOffset != null) {
if(highPolySkin.limbsOffset.length == 1) {
offset = highPolySkin.limbsOffset[0];
}else {
offset = highPolySkin.limbsOffset[i];
}
}
GlStateManager.pushMatrix();
if(offset != 0.0f || highPolySkin.limbsInitialRotation != 0.0f) {
if(offset != 0.0f) {
GlStateManager.translate(0.0f, offset, 0.0f);
}
if(highPolySkin.limbsInitialRotation != 0.0f) {
GlStateManager.rotate(highPolySkin.limbsInitialRotation, 1.0f, 0.0f, 0.0f);
}
}
if(highPolySkin == HighPolySkin.LONG_ARMS) {
if(abstractclientplayer.isSwingInProgress) {
float var17 = MathHelper.cos(-abstractclientplayer.getSwingProgress(f1) * (float)Math.PI * 2.0f - 1.2f) - 0.362f;
var17 *= var17;
GlStateManager.rotate(-var17 * 20.0f, 1.0f, 0.0f, 0.0f);
}
}else if(highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) {
if(abstractclientplayer.isSwingInProgress) {
float var17 = MathHelper.cos(-abstractclientplayer.getSwingProgress(f1) * (float)Math.PI * 2.0f - 1.2f) - 0.362f;
var17 *= var17;
GlStateManager.rotate(var17 * 60.0f, 1.0f, 0.0f, 0.0f);
}
GlStateManager.rotate(40.0f * var15, 1.0f, 0.0f, 0.0f);
}else if(highPolySkin == HighPolySkin.LAXATIVE_DUDE) {
float fff = (i == 0) ? 1.0f : -1.0f;
float swing = (MathHelper.cos(f10 % 100000.0f) * fff + 0.2f) * var15;
float swing2 = (MathHelper.cos(f10 % 100000.0f) * fff * 0.5f + 0.0f) * var15;
GlStateManager.rotate(swing * 25.0f, 1.0f, 0.0f, 0.0f);
if(abstractclientplayer.isSwingInProgress) {
float var17 = MathHelper.cos(-abstractclientplayer.getSwingProgress(f1) * (float)Math.PI * 2.0f - 1.2f) - 0.362f;
var17 *= var17;
GlStateManager.rotate(-var17 * 25.0f, 1.0f, 0.0f, 0.0f);
}
// shear matrix
tmpMatrix.setIdentity();
tmpMatrix.m21 = swing2;
tmpMatrix.m23 = swing2 * -0.2f;
GlStateManager.multMatrix(tmpMatrix);
}
if(i != 0) {
mc.getTextureManager().bindTexture(highPolySkin.texture);
if (abstractclientplayer.hurtTime > 0 || abstractclientplayer.deathTime > 0) {
GlStateManager.color(1.2f, 0.8F, 0.8F, 1.0F);
}else {
GlStateManager.color(1.0f, 1.0F, 1.0F, 1.0F);
}
}
EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(highPolySkin.limbsModel[i]));
if(i == 0) {
GlStateManager.pushMatrix();
GlStateManager.translate(-0.287f, 0.05f, 0.0f);
if(highPolySkin == HighPolySkin.LONG_ARMS) {
GlStateManager.translate(1.72f, 2.05f, -0.24f);
ItemStack stk = abstractclientplayer.getHeldItem();
if(stk != null) {
Item itm = stk.getItem();
if(itm != null) {
if(itm == Items.bow) {
GlStateManager.translate(-0.22f, 0.8f, 0.6f);
GlStateManager.rotate(-90.0f, 1.0f, 0.0f, 0.0f);
}else if(itm instanceof ItemBlock && !((ItemBlock)itm).getBlock().isNormalCube()) {
GlStateManager.translate(0.0f, -0.1f, 0.13f);
}else if(!itm.isFull3D()) {
GlStateManager.translate(-0.08f, -0.1f, 0.16f);
}
}
}
}else if(highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) {
GlStateManager.translate(-0.029f, 1.2f, -3f);
GlStateManager.rotate(-5.0f, 0.0f, 1.0f, 0.0f);
float var17 = -1.2f * var15;
if(abstractclientplayer.isSwingInProgress) {
float vvar17 = MathHelper.cos(-abstractclientplayer.getSwingProgress(f1) * (float)Math.PI * 2.0f - 1.2f) - 0.362f;
var17 = vvar17 < var17 ? vvar17 : var17;
}
GlStateManager.translate(-0.02f * var17, 0.42f * var17, var17 * 0.35f);
GlStateManager.rotate(var17 * 30.0f, 1.0f, 0.0f, 0.0f);
GlStateManager.rotate(110.0f, 1.0f, 0.0f, 0.0f);
ItemStack stk = abstractclientplayer.getHeldItem();
if(stk != null) {
Item itm = stk.getItem();
if(itm != null) {
if(itm == Items.bow) {
GlStateManager.translate(-0.18f, 1.0f, 0.4f);
GlStateManager.rotate(-95.0f, 1.0f, 0.0f, 0.0f);
}else if(itm instanceof ItemBlock && !((ItemBlock)itm).getBlock().isNormalCube()) {
GlStateManager.translate(0.0f, -0.1f, 0.13f);
}else if(!itm.isFull3D()) {
GlStateManager.translate(-0.08f, -0.1f, 0.16f);
}
}
}
}else if(highPolySkin == HighPolySkin.LAXATIVE_DUDE) {
GlStateManager.translate(1.291f, 2.44f, -2.18f);
GlStateManager.rotate(95.0f, 1.0f, 0.0f, 0.0f);
ItemStack stk = abstractclientplayer.getHeldItem();
if(stk != null) {
Item itm = stk.getItem();
if(itm != null) {
if(itm == Items.bow) {
GlStateManager.translate(-0.65f, 1.3f, -0.1f);
GlStateManager.rotate(180.0f, 0.0f, 0.0f, 1.0f);
GlStateManager.rotate(20.0f, 1.0f, 0.0f, 0.0f);
}else if(itm instanceof ItemBlock && !((ItemBlock)itm).getBlock().isNormalCube()) {
GlStateManager.translate(0.0f, -0.35f, 0.4f);
}else if(!itm.isFull3D()) {
GlStateManager.translate(-0.1f, -0.1f, 0.16f);
}
}
}
}
DeferredStateManager.setDefaultMaterialConstants();
renderHeldItem(abstractclientplayer, f1);
GlStateManager.popMatrix();
}
GlStateManager.popMatrix();
}
}
if(highPolySkin.eyesModel != null && !DeferredStateManager.isEnableShadowRender()) {
float ff = 0.00416f;
int brightness = abstractclientplayer.getBrightnessForRender(0.0f);
float blockLight = (brightness % 65536) * ff;
float skyLight = (brightness / 65536) * ff;
float sunCurve = (float)((abstractclientplayer.worldObj.getWorldTime() + 4000l) % 24000) / 24000.0f;
sunCurve = MathHelper.clamp_float(9.8f - MathHelper.abs(sunCurve * 5.0f + sunCurve * sunCurve * 45.0f - 14.3f) * 0.7f, 0.0f, 1.0f);
skyLight = skyLight * (sunCurve * 0.85f + 0.15f);
blockLight = blockLight * (sunCurve * 0.3f + 0.7f);
float eyeBrightness = blockLight;
if(skyLight > eyeBrightness) {
eyeBrightness = skyLight;
}
eyeBrightness += blockLight * 0.2f;
eyeBrightness = 1.0f - eyeBrightness;
eyeBrightness = MathHelper.clamp_float(eyeBrightness * 1.9f - 1.0f, 0.0f, 1.0f);
if(eyeBrightness > 0.1f) {
if(DeferredStateManager.isInDeferredPass()) {
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
DeferredStateManager.setDefaultMaterialConstants();
DeferredStateManager.setEmissionConstant(eyeBrightness);
}else {
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL_ONE, GL_ONE);
GlStateManager.color(eyeBrightness * 7.0f, eyeBrightness * 7.0f, eyeBrightness * 7.0f, 1.0f);
if(jumpFactor > 0.0f) {
GlStateManager.pushMatrix();
GlStateManager.translate(0.0f, jumpFactor * 3.0f, 0.0f);
}
}
GlStateManager.disableTexture2D();
GlStateManager.disableLighting();
GlStateManager.enableCull();
EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(highPolySkin.eyesModel));
GlStateManager.enableTexture2D();
GlStateManager.enableLighting();
GlStateManager.disableCull();
if(jumpFactor > 0.0f) {
GlStateManager.popMatrix();
}
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
if(!DeferredStateManager.isInDeferredPass()) {
GlStateManager.disableBlend();
}
}
}
}catch(Throwable t) {
logger.error("Couldn\'t render entity");
logger.error(t);
}
GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit);
GlStateManager.enableTexture2D();
GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit);
GlStateManager.enableCull();
GlStateManager.popMatrix();
if (!this.renderOutlines) {
this.renderName(abstractclientplayer, d0, nameY, d2);
}
}
}
public void renderRightArm(AbstractClientPlayer clientPlayer) {
}
public void renderLeftArm(AbstractClientPlayer clientPlayer) {
}
protected void renderHeldItem(AbstractClientPlayer clientPlayer, float partialTicks) {
ItemStack itemstack = clientPlayer.getHeldItem();
if (itemstack != null) {
GlStateManager.pushMatrix();
GlStateManager.translate(-0.11F, 0.475F, 0.25F);
if (clientPlayer.fishEntity != null) {
itemstack = new ItemStack(Items.fishing_rod, 0);
}
Item item = itemstack.getItem();
Minecraft minecraft = Minecraft.getMinecraft();
if (item instanceof ItemBlock && Block.getBlockFromItem(item).getRenderType() == 2) {
GlStateManager.translate(0.0F, 0.1875F, -0.3125F);
GlStateManager.rotate(20.0F, 1.0F, 0.0F, 0.0F);
GlStateManager.rotate(45.0F, 0.0F, 1.0F, 0.0F);
float f1 = 0.375F;
GlStateManager.scale(-f1, -f1, f1);
}
if (clientPlayer.isSneaking()) {
GlStateManager.translate(0.0F, 0.203125F, 0.0F);
}
minecraft.getItemRenderer().renderItem(clientPlayer, itemstack,
ItemCameraTransforms.TransformType.THIRD_PERSON);
GlStateManager.popMatrix();
}
}
}

View File

@ -0,0 +1,242 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.socket.EaglercraftNetworkManager;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.client.C17PacketCustomPayload;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2022-2024 lax1dude. 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 ServerCapeCache {
private static final Logger logger = LogManager.getLogger("ServerCapeCache");
public class CapeCacheEntry {
protected final boolean isPresetCape;
protected final int presetCapeId;
protected final CacheCustomCape customCape;
protected long lastCacheHit = System.currentTimeMillis();
protected CapeCacheEntry(EaglerSkinTexture textureInstance, ResourceLocation resourceLocation) {
this.isPresetCape = false;
this.presetCapeId = -1;
this.customCape = new CacheCustomCape(textureInstance, resourceLocation);
ServerCapeCache.this.textureManager.loadTexture(resourceLocation, textureInstance);
}
/**
* Use only for the constant for the client player
*/
protected CapeCacheEntry(ResourceLocation resourceLocation) {
this.isPresetCape = false;
this.presetCapeId = -1;
this.customCape = new CacheCustomCape(null, resourceLocation);
}
protected CapeCacheEntry(int presetSkinId) {
this.isPresetCape = true;
this.presetCapeId = presetSkinId;
this.customCape = null;
}
public ResourceLocation getResourceLocation() {
if(isPresetCape) {
return DefaultCapes.getCapeFromId(presetCapeId).location;
}else {
if(customCape != null) {
return customCape.resourceLocation;
}else {
return null;
}
}
}
protected void free() {
if(!isPresetCape && customCape.resourceLocation != null) {
ServerCapeCache.this.textureManager.deleteTexture(customCape.resourceLocation);
}
}
}
protected static class CacheCustomCape {
protected final EaglerSkinTexture textureInstance;
protected final ResourceLocation resourceLocation;
protected CacheCustomCape(EaglerSkinTexture textureInstance, ResourceLocation resourceLocation) {
this.textureInstance = textureInstance;
this.resourceLocation = resourceLocation;
}
}
private final CapeCacheEntry defaultCacheEntry = new CapeCacheEntry(0);
private final Map<EaglercraftUUID, CapeCacheEntry> capesCache = new HashMap();
private final Map<EaglercraftUUID, Long> waitingCapes = new HashMap();
private final Map<EaglercraftUUID, Long> evictedCapes = new HashMap();
private final EaglercraftNetworkManager networkManager;
protected final TextureManager textureManager;
private final EaglercraftUUID clientPlayerId;
private final CapeCacheEntry clientPlayerCacheEntry;
private long lastFlush = System.currentTimeMillis();
private long lastFlushReq = System.currentTimeMillis();
private long lastFlushEvict = System.currentTimeMillis();
private static int texId = 0;
public ServerCapeCache(EaglercraftNetworkManager networkManager, TextureManager textureManager) {
this.networkManager = networkManager;
this.textureManager = textureManager;
this.clientPlayerId = EaglerProfile.getPlayerUUID();
this.clientPlayerCacheEntry = new CapeCacheEntry(EaglerProfile.getActiveCapeResourceLocation());
}
public CapeCacheEntry getClientPlayerCape() {
return clientPlayerCacheEntry;
}
public CapeCacheEntry getCape(EaglercraftUUID player) {
if(player.equals(clientPlayerId)) {
return clientPlayerCacheEntry;
}
CapeCacheEntry etr = capesCache.get(player);
if(etr == null) {
if(!waitingCapes.containsKey(player) && !evictedCapes.containsKey(player)) {
waitingCapes.put(player, System.currentTimeMillis());
PacketBuffer buffer;
try {
buffer = CapePackets.writeGetOtherCape(player);
}catch(IOException ex) {
logger.error("Could not write cape request packet!");
logger.error(ex);
return defaultCacheEntry;
}
networkManager.sendPacket(new C17PacketCustomPayload("EAG|Capes-1.8", buffer));
}
return defaultCacheEntry;
}else {
etr.lastCacheHit = System.currentTimeMillis();
return etr;
}
}
public void cacheCapePreset(EaglercraftUUID player, int presetId) {
if(waitingCapes.remove(player) != null) {
CapeCacheEntry etr = capesCache.remove(player);
if(etr != null) {
etr.free();
}
capesCache.put(player, new CapeCacheEntry(presetId));
}else {
logger.error("Unsolicited cape response recieved for \"{}\"! (preset {})", player, presetId);
}
}
public void cacheCapeCustom(EaglercraftUUID player, byte[] pixels) {
if(waitingCapes.remove(player) != null) {
CapeCacheEntry etr = capesCache.remove(player);
if(etr != null) {
etr.free();
}
byte[] pixels32x32 = new byte[4096];
SkinConverter.convertCape23x17RGBto32x32RGBA(pixels, pixels32x32);
try {
etr = new CapeCacheEntry(new EaglerSkinTexture(pixels32x32, 32, 32),
new ResourceLocation("eagler:capes/multiplayer/tex_" + texId++));
}catch(Throwable t) {
etr = new CapeCacheEntry(0);
logger.error("Could not process custom skin packet for \"{}\"!", player);
logger.error(t);
}
capesCache.put(player, etr);
}else {
logger.error("Unsolicited skin response recieved for \"{}\"!", player);
}
}
public void flush() {
long millis = System.currentTimeMillis();
if(millis - lastFlushReq > 5000l) {
lastFlushReq = millis;
if(!waitingCapes.isEmpty()) {
Iterator<Long> waitingItr = waitingCapes.values().iterator();
while(waitingItr.hasNext()) {
if(millis - waitingItr.next().longValue() > 30000l) {
waitingItr.remove();
}
}
}
}
if(millis - lastFlushEvict > 1000l) {
lastFlushEvict = millis;
if(!evictedCapes.isEmpty()) {
Iterator<Long> evictItr = evictedCapes.values().iterator();
while(evictItr.hasNext()) {
if(millis - evictItr.next().longValue() > 3000l) {
evictItr.remove();
}
}
}
}
if(millis - lastFlush > 60000l) {
lastFlush = millis;
if(!capesCache.isEmpty()) {
Iterator<CapeCacheEntry> entryItr = capesCache.values().iterator();
while(entryItr.hasNext()) {
CapeCacheEntry etr = entryItr.next();
if(millis - etr.lastCacheHit > 900000l) { // 15 minutes
entryItr.remove();
etr.free();
}
}
}
}
}
public void destroy() {
Iterator<CapeCacheEntry> entryItr = capesCache.values().iterator();
while(entryItr.hasNext()) {
entryItr.next().free();
}
capesCache.clear();
waitingCapes.clear();
evictedCapes.clear();
}
public void evictCape(EaglercraftUUID uuid) {
evictedCapes.put(uuid, Long.valueOf(System.currentTimeMillis()));
CapeCacheEntry etr = capesCache.remove(uuid);
if(etr != null) {
etr.free();
}
}
}

View File

@ -321,6 +321,7 @@ public class ServerSkinCache {
}
skinsCache.clear();
waitingSkins.clear();
evictedSkins.clear();
}
public void evictSkin(EaglercraftUUID uuid) {

View File

@ -35,6 +35,56 @@ public class SkinConverter {
copyRawPixels(skinIn.pixels, skinOut.pixels, 48, 52, 44, 64, 52, 20, 56, 32, 64, 64);
}
public static void convertCape32x32RGBAto23x17RGB(ImageData skinIn, byte[] skinOut) {
int i, j;
for(int y = 0; y < 17; ++y) {
for(int x = 0; x < 22; ++x) {
i = (y * 23 + x) * 3;
j = skinIn.pixels[y * skinIn.width + x];
if((j & 0xFF000000) != 0) {
skinOut[i] = (byte)(j >> 16);
skinOut[i + 1] = (byte)(j >> 8);
skinOut[i + 2] = (byte)(j & 0xFF);
}else {
skinOut[i] = skinOut[i + 1] = skinOut[i + 2] = 0;
}
}
}
for(int y = 0; y < 11; ++y) {
i = ((y + 6) * 23 + 22) * 3;
j = skinIn.pixels[(y + 11) * skinIn.width + 22];
if((j & 0xFF000000) != 0) {
skinOut[i] = (byte)(j >> 16);
skinOut[i + 1] = (byte)(j >> 8);
skinOut[i + 2] = (byte)(j & 0xFF);
}else {
skinOut[i] = skinOut[i + 1] = skinOut[i + 2] = 0;
}
}
}
public static void convertCape23x17RGBto32x32RGBA(byte[] skinIn, byte[] skinOut) {
int i, j;
for(int y = 0; y < 17; ++y) {
for(int x = 0; x < 22; ++x) {
i = (y * 32 + x) << 2;
j = (y * 23 + x) * 3;
skinOut[i] = (byte)0xFF;
skinOut[i + 1] = skinIn[j];
skinOut[i + 2] = skinIn[j + 1];
skinOut[i + 3] = skinIn[j + 2];
}
}
for(int y = 0; y < 11; ++y) {
i = ((y + 11) * 32 + 22) << 2;
j = ((y + 6) * 23 + 22) * 3;
skinOut[i] = (byte)0xFF;
skinOut[i + 1] = skinIn[j];
skinOut[i + 2] = skinIn[j + 1];
skinOut[i + 3] = skinIn[j + 2];
}
}
private static void copyRawPixels(int[] imageIn, int[] imageOut, int dx1, int dy1, int dx2, int dy2, int sx1,
int sy1, int sx2, int sy2, int imgSrcWidth, int imgDstWidth) {
if(dx1 > dx2) {

View File

@ -19,15 +19,19 @@ import java.util.Map;
*
*/
public enum SkinModel {
STEVE(0, 64, 64, "default", false), ALEX(1, 64, 64, "slim", false), ZOMBIE(2, 64, 64, "zombie", true);
STEVE(0, 64, 64, "default", false), ALEX(1, 64, 64, "slim", false), ZOMBIE(2, 64, 64, "zombie", true),
LONG_ARMS(3, HighPolySkin.LONG_ARMS), WEIRD_CLIMBER_DUDE(4, HighPolySkin.WEIRD_CLIMBER_DUDE),
LAXATIVE_DUDE(5, HighPolySkin.LAXATIVE_DUDE), BABY_CHARLES(6, HighPolySkin.BABY_CHARLES),
BABY_WINSTON(7, HighPolySkin.BABY_WINSTON);
public final int id;
public final int width;
public final int height;
public final String profileSkinType;
public final boolean sanitize;
public final HighPolySkin highPoly;
public static final SkinModel[] skinModels = new SkinModel[3];
public static final SkinModel[] skinModels = new SkinModel[8];
private static final Map<String, SkinModel> skinModelsByName = new HashMap();
private SkinModel(int id, int w, int h, String profileSkinType, boolean sanitize) {
@ -36,6 +40,16 @@ public enum SkinModel {
this.height = h;
this.profileSkinType = profileSkinType;
this.sanitize = sanitize;
this.highPoly = null;
}
private SkinModel(int id, HighPolySkin highPoly) {
this.id = id;
this.width = 256;
this.height = 128;
this.profileSkinType = "eagler";
this.sanitize = true;
this.highPoly = highPoly;
}
public static SkinModel getModelFromId(String str) {

View File

@ -58,6 +58,9 @@ public class SkinPackets {
modelId = SkinModel.STEVE;
}
}
if(modelId.highPoly != null) {
modelId = SkinModel.STEVE;
}
int bytesToRead = modelId.width * modelId.height * 4;
byte[] readSkin = new byte[bytesToRead];
buffer.readBytes(readSkin);

View File

@ -1,10 +1,14 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import net.lax1dude.eaglercraft.v1_8.opengl.EaglerMeshLoader;
import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.model.ModelPlayer;
import net.minecraft.client.model.ModelZombie;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved.
@ -36,7 +40,11 @@ public class SkinPreviewRenderer {
playerModelZombie.isChild = false;
}
public static void renderBiped(int x, int y, int mx, int my, SkinModel skinModel) {
public static void renderPreview(int x, int y, int mx, int my, SkinModel skinModel) {
renderPreview(x, y, mx, my, false, skinModel, null, null);
}
public static void renderPreview(int x, int y, int mx, int my, boolean capeMode, SkinModel skinModel, ResourceLocation skinTexture, ResourceLocation capeTexture) {
ModelBiped model;
switch(skinModel) {
case STEVE:
@ -49,6 +57,17 @@ public class SkinPreviewRenderer {
case ZOMBIE:
model = playerModelZombie;
break;
case LONG_ARMS:
case WEIRD_CLIMBER_DUDE:
case LAXATIVE_DUDE:
case BABY_CHARLES:
case BABY_WINSTON:
if(skinModel.highPoly != null && Minecraft.getMinecraft().gameSettings.enableFNAWSkins) {
renderHighPoly(x, y, mx, my, skinModel.highPoly);
return;
}
model = playerModelSteve;
break;
}
GlStateManager.enableTexture2D();
@ -65,12 +84,95 @@ public class SkinPreviewRenderer {
RenderHelper.enableGUIStandardItemLighting();
GlStateManager.translate(0.0f, 1.0f, 0.0f);
GlStateManager.rotate(((y - my) * -0.06f), 1.0f, 0.0f, 0.0f);
if(capeMode) {
GlStateManager.rotate(140.0f, 0.0f, 1.0f, 0.0f);
mx = x - (x - mx) - 20;
GlStateManager.rotate(((y - my) * -0.02f), 1.0f, 0.0f, 0.0f);
}else {
GlStateManager.rotate(((y - my) * -0.06f), 1.0f, 0.0f, 0.0f);
}
GlStateManager.rotate(((x - mx) * 0.06f), 0.0f, 1.0f, 0.0f);
GlStateManager.translate(0.0f, -1.0f, 0.0f);
if(skinTexture != null) {
Minecraft.getMinecraft().getTextureManager().bindTexture(skinTexture);
}
model.render(null, 0.0f, 0.0f, (float)(System.currentTimeMillis() % 2000000) / 50f, ((x - mx) * 0.06f), ((y - my) * -0.1f), 0.0625f);
if(capeTexture != null && model instanceof ModelPlayer) {
Minecraft.getMinecraft().getTextureManager().bindTexture(capeTexture);
GlStateManager.pushMatrix();
GlStateManager.translate(0.0F, 0.0F, 0.125F);
GlStateManager.rotate(6.0F, 1.0F, 0.0F, 0.0F);
GlStateManager.rotate(180.0F, 0.0F, 1.0F, 0.0F);
((ModelPlayer)model).renderCape(0.0625f);
GlStateManager.popMatrix();
}
GlStateManager.popMatrix();
GlStateManager.disableLighting();
}
private static void renderHighPoly(int x, int y, int mx, int my, HighPolySkin msh) {
GlStateManager.enableTexture2D();
GlStateManager.disableBlend();
GlStateManager.disableCull();
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
GlStateManager.pushMatrix();
GlStateManager.translate(x, y - 80.0f, 100.0f);
GlStateManager.scale(50.0f, 50.0f, 50.0f);
GlStateManager.rotate(180.0f, 1.0f, 0.0f, 0.0f);
GlStateManager.scale(1.0f, -1.0f, 1.0f);
RenderHelper.enableGUIStandardItemLighting();
GlStateManager.translate(0.0f, 1.0f, 0.0f);
GlStateManager.rotate(((y - my) * -0.06f), 1.0f, 0.0f, 0.0f);
GlStateManager.rotate(((x - mx) * 0.06f), 0.0f, 1.0f, 0.0f);
GlStateManager.rotate(180.0f, 0.0f, 0.0f, 1.0f);
GlStateManager.translate(0.0f, -0.6f, 0.0f);
GlStateManager.scale(HighPolySkin.highPolyScale, HighPolySkin.highPolyScale, HighPolySkin.highPolyScale);
Minecraft.getMinecraft().getTextureManager().bindTexture(msh.texture);
if(msh.bodyModel != null) {
EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(msh.bodyModel));
}
if(msh.headModel != null) {
EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(msh.headModel));
}
if(msh.limbsModel != null && msh.limbsModel.length > 0) {
for(int i = 0; i < msh.limbsModel.length; ++i) {
float offset = 0.0f;
if(msh.limbsOffset != null) {
if(msh.limbsOffset.length == 1) {
offset = msh.limbsOffset[0];
}else {
offset = msh.limbsOffset[i];
}
}
if(offset != 0.0f || msh.limbsInitialRotation != 0.0f) {
GlStateManager.pushMatrix();
if(offset != 0.0f) {
GlStateManager.translate(0.0f, offset, 0.0f);
}
if(msh.limbsInitialRotation != 0.0f) {
GlStateManager.rotate(msh.limbsInitialRotation, 1.0f, 0.0f, 0.0f);
}
}
EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(msh.limbsModel[i]));
if(offset != 0.0f || msh.limbsInitialRotation != 0.0f) {
GlStateManager.popMatrix();
}
}
}
GlStateManager.popMatrix();
GlStateManager.disableLighting();
}

View File

@ -294,6 +294,19 @@ public class ConnectionHandshake {
d.writeShort(packetSkin.length);
d.write(packetSkin);
PlatformNetworking.writePlayPacket(bao.toByteArray());
bao.reset();
d.writeByte(HandshakePacketTypes.PROTOCOL_CLIENT_PROFILE_DATA);
profileDataType = "cape_v1";
d.writeByte(profileDataType.length());
d.writeBytes(profileDataType);
byte[] packetCape = EaglerProfile.getCapePacket();
if(packetCape.length > 0xFFFF) {
throw new IOException("Cape packet is too long: " + packetCape.length);
}
d.writeShort(packetCape.length);
d.write(packetCape);
PlatformNetworking.writePlayPacket(bao.toByteArray());
byte[] packetSignatureData = UpdateService.getClientSignatureData();
if(packetSignatureData != null) {

View File

@ -140,4 +140,7 @@ public class GuiScreenAddRelay extends GuiScreen {
super.drawScreen(par1, par2, par3);
}
public boolean blockPTTKey() {
return this.serverName.isFocused() || this.serverAddress.isFocused();
}
}

View File

@ -117,7 +117,7 @@ public class GuiScreenLANConnecting extends GuiScreen {
this.mc.clearTitles();
networkManager.setConnectionState(EnumConnectionState.LOGIN);
networkManager.setNetHandler(new NetHandlerSingleplayerLogin(networkManager, mc, parent));
networkManager.sendPacket(new C00PacketLoginStart(this.mc.getSession().getProfile(), EaglerProfile.getSkinPacket()));
networkManager.sendPacket(new C00PacketLoginStart(this.mc.getSession().getProfile(), EaglerProfile.getSkinPacket(), EaglerProfile.getCapePacket()));
}
}
}

View File

@ -88,7 +88,7 @@ public class GuiScreenSingleplayerConnecting extends GuiScreen {
this.mc.clearTitles();
this.networkManager.setConnectionState(EnumConnectionState.LOGIN);
this.networkManager.setNetHandler(new NetHandlerSingleplayerLogin(this.networkManager, this.mc, this.menu));
this.networkManager.sendPacket(new C00PacketLoginStart(this.mc.getSession().getProfile(), EaglerProfile.getSkinPacket()));
this.networkManager.sendPacket(new C00PacketLoginStart(this.mc.getSession().getProfile(), EaglerProfile.getSkinPacket(), EaglerProfile.getCapePacket()));
}
try {
this.networkManager.processReceivedPackets();

View File

@ -195,4 +195,8 @@ public class GuiShareToLan extends GuiScreen {
super.updateScreen();
this.codeTextField.updateCursorCounter();
}
public boolean blockPTTKey() {
return this.codeTextField.isFocused();
}
}

View File

@ -361,6 +361,9 @@ public class EaglerIntegratedServerWorker {
case IPCPacket17ConfigureLAN.ID: {
IPCPacket17ConfigureLAN pkt = (IPCPacket17ConfigureLAN)ipc;
if(!pkt.iceServers.isEmpty() && ServerPlatformSingleplayer.getClientConfigAdapter().isAllowVoiceClient()) {
currentProcess.enableVoice(pkt.iceServers.toArray(new String[pkt.iceServers.size()]));
}
currentProcess.getConfigurationManager().configureLAN(pkt.gamemode, pkt.cheats); // don't use iceServers
break;

View File

@ -16,7 +16,9 @@ import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.WorldServer;
import net.minecraft.world.WorldSettings;
import net.minecraft.world.WorldSettings.GameType;
import net.lax1dude.eaglercraft.v1_8.sp.server.skins.IntegratedCapeService;
import net.lax1dude.eaglercraft.v1_8.sp.server.skins.IntegratedSkinService;
import net.lax1dude.eaglercraft.v1_8.sp.server.voice.IntegratedVoiceService;
/**
* Copyright (c) 2023-2024 lax1dude, ayunami2000. All Rights Reserved.
@ -45,6 +47,8 @@ public class EaglerMinecraftServer extends MinecraftServer {
protected boolean paused;
protected EaglerSaveHandler saveHandler;
protected IntegratedSkinService skinService;
protected IntegratedCapeService capeService;
protected IntegratedVoiceService voiceService;
private long lastTPSUpdate = 0l;
@ -62,6 +66,8 @@ public class EaglerMinecraftServer extends MinecraftServer {
Bootstrap.register();
this.saveHandler = new EaglerSaveHandler(savesDir, world);
this.skinService = new IntegratedSkinService(new VFile2(saveHandler.getWorldDirectory(), "eagler/skulls"));
this.capeService = new IntegratedCapeService();
this.voiceService = null;
this.setServerOwner(owner);
logger.info("server owner: " + owner);
this.setDemo(demo);
@ -76,6 +82,27 @@ public class EaglerMinecraftServer extends MinecraftServer {
return skinService;
}
public IntegratedCapeService getCapeService() {
return capeService;
}
public IntegratedVoiceService getVoiceService() {
return voiceService;
}
public void enableVoice(String[] iceServers) {
if(iceServers != null) {
if(voiceService != null) {
voiceService.changeICEServers(iceServers);
}else {
voiceService = new IntegratedVoiceService(iceServers);
for(EntityPlayerMP player : getConfigurationManager().func_181057_v()) {
voiceService.handlePlayerLoggedIn(player);
}
}
}
}
public void setBaseServerProperties(EnumDifficulty difficulty, GameType gamemode) {
this.difficulty = difficulty;
this.gamemode = gamemode;

View File

@ -43,6 +43,8 @@ public class EaglerPlayerList extends ServerConfigurationManager {
public void playerLoggedOut(EntityPlayerMP playerIn) {
super.playerLoggedOut(playerIn);
((EaglerMinecraftServer)getServerInstance()).skinService.unregisterPlayer(playerIn.getUniqueID());
EaglerMinecraftServer svr = (EaglerMinecraftServer)getServerInstance();
svr.skinService.unregisterPlayer(playerIn.getUniqueID());
svr.capeService.unregisterPlayer(playerIn.getUniqueID());
}
}

View File

@ -0,0 +1,110 @@
package net.lax1dude.eaglercraft.v1_8.sp.server.skins;
import java.io.IOException;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.minecraft.entity.player.EntityPlayerMP;
/**
* Copyright (c) 2024 lax1dude. 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 IntegratedCapePackets {
public static final int PACKET_MY_CAPE_PRESET = 0x01;
public static final int PACKET_MY_CAPE_CUSTOM = 0x02;
public static final int PACKET_GET_OTHER_CAPE = 0x03;
public static final int PACKET_OTHER_CAPE_PRESET = 0x04;
public static final int PACKET_OTHER_CAPE_CUSTOM = 0x05;
public static void processPacket(byte[] data, EntityPlayerMP sender, IntegratedCapeService capeService) throws IOException {
if(data.length == 0) {
throw new IOException("Zero-length packet recieved");
}
int packetId = (int)data[0] & 0xFF;
try {
switch(packetId) {
case PACKET_GET_OTHER_CAPE:
processGetOtherCape(data, sender, capeService);
break;
default:
throw new IOException("Unknown packet type " + packetId);
}
}catch(IOException ex) {
throw ex;
}catch(Throwable t) {
throw new IOException("Unhandled exception handling packet type " + packetId, t);
}
}
private static void processGetOtherCape(byte[] data, EntityPlayerMP sender, IntegratedCapeService capeService) throws IOException {
if(data.length != 17) {
throw new IOException("Invalid length " + data.length + " for skin request packet");
}
EaglercraftUUID searchUUID = IntegratedSkinPackets.bytesToUUID(data, 1);
capeService.processGetOtherCape(searchUUID, sender);
}
public static void registerEaglerPlayer(EaglercraftUUID clientUUID, byte[] bs, IntegratedCapeService capeService) throws IOException {
if(bs.length == 0) {
throw new IOException("Zero-length packet recieved");
}
byte[] generatedPacket;
int packetType = (int)bs[0] & 0xFF;
switch(packetType) {
case PACKET_MY_CAPE_PRESET:
if(bs.length != 5) {
throw new IOException("Invalid length " + bs.length + " for preset cape packet");
}
generatedPacket = IntegratedCapePackets.makePresetResponse(clientUUID, (bs[1] << 24) | (bs[2] << 16) | (bs[3] << 8) | (bs[4] & 0xFF));
break;
case PACKET_MY_CAPE_CUSTOM:
if(bs.length != 1174) {
throw new IOException("Invalid length " + bs.length + " for custom cape packet");
}
generatedPacket = IntegratedCapePackets.makeCustomResponse(clientUUID, bs, 1, 1173);
break;
default:
throw new IOException("Unknown skin packet type: " + packetType);
}
capeService.registerEaglercraftPlayer(clientUUID, generatedPacket);
}
public static void registerEaglerPlayerFallback(EaglercraftUUID clientUUID, IntegratedCapeService capeService) {
capeService.registerEaglercraftPlayer(clientUUID, IntegratedCapePackets.makePresetResponse(clientUUID, 0));
}
public static byte[] makePresetResponse(EaglercraftUUID uuid, int presetId) {
byte[] ret = new byte[1 + 16 + 4];
ret[0] = (byte)PACKET_OTHER_CAPE_PRESET;
IntegratedSkinPackets.UUIDToBytes(uuid, ret, 1);
ret[17] = (byte)(presetId >> 24);
ret[18] = (byte)(presetId >> 16);
ret[19] = (byte)(presetId >> 8);
ret[20] = (byte)(presetId & 0xFF);
return ret;
}
public static byte[] makeCustomResponse(EaglercraftUUID uuid, byte[] pixels) {
return makeCustomResponse(uuid, pixels, 0, pixels.length);
}
public static byte[] makeCustomResponse(EaglercraftUUID uuid, byte[] pixels, int offset, int length) {
byte[] ret = new byte[1 + 16 + length];
ret[0] = (byte)PACKET_OTHER_CAPE_CUSTOM;
IntegratedSkinPackets.UUIDToBytes(uuid, ret, 1);
System.arraycopy(pixels, offset, ret, 17, length);
return ret;
}
}

View File

@ -0,0 +1,77 @@
package net.lax1dude.eaglercraft.v1_8.sp.server.skins;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.netty.Unpooled;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.server.S3FPacketCustomPayload;
/**
* Copyright (c) 2024 lax1dude. 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 IntegratedCapeService {
public static final Logger logger = LogManager.getLogger("IntegratedCapeService");
public static final int masterRateLimitPerPlayer = 250;
public static final String CHANNEL = "EAG|Capes-1.8";
private final Map<EaglercraftUUID, byte[]> capesCache = new HashMap();
public void processPacket(byte[] packetData, EntityPlayerMP sender) {
try {
IntegratedCapePackets.processPacket(packetData, sender, this);
} catch (IOException e) {
logger.error("Invalid skin request packet recieved from player {}!", sender.getName());
logger.error(e);
sender.playerNetServerHandler.kickPlayerFromServer("Invalid skin request packet recieved!");
}
}
public void processLoginPacket(byte[] packetData, EntityPlayerMP sender) {
try {
IntegratedCapePackets.registerEaglerPlayer(sender.getUniqueID(), packetData, this);
} catch (IOException e) {
logger.error("Invalid skin data packet recieved from player {}!", sender.getName());
logger.error(e);
sender.playerNetServerHandler.kickPlayerFromServer("Invalid skin data packet recieved!");
}
}
public void registerEaglercraftPlayer(EaglercraftUUID playerUUID, byte[] capePacket) {
capesCache.put(playerUUID, capePacket);
}
public void processGetOtherCape(EaglercraftUUID searchUUID, EntityPlayerMP sender) {
byte[] maybeCape = capesCache.get(searchUUID);
if(maybeCape == null) {
maybeCape = IntegratedCapePackets.makePresetResponse(searchUUID, 0);
}
sender.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL, new PacketBuffer(Unpooled.buffer(maybeCape, maybeCape.length).writerIndex(maybeCape.length))));
}
public void unregisterPlayer(EaglercraftUUID playerUUID) {
synchronized(capesCache) {
capesCache.remove(playerUUID);
}
}
}

View File

@ -0,0 +1,255 @@
package net.lax1dude.eaglercraft.v1_8.sp.server.voice;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.netty.Unpooled;
import net.lax1dude.eaglercraft.v1_8.voice.ExpiringSet;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.server.S3FPacketCustomPayload;
/**
* Copyright (c) 2024 lax1dude. 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 IntegratedVoiceService {
public static final Logger logger = LogManager.getLogger("IntegratedVoiceService");
public static final String CHANNEL = "EAG|Voice-1.8";
private byte[] iceServersPacket;
private final Map<EaglercraftUUID, EntityPlayerMP> voicePlayers = new HashMap<>();
private final Map<EaglercraftUUID, ExpiringSet<EaglercraftUUID>> voiceRequests = new HashMap<>();
private final Set<VoicePair> voicePairs = new HashSet<>();
public IntegratedVoiceService(String[] iceServers) {
iceServersPacket = IntegratedVoiceSignalPackets.makeVoiceSignalPacketAllowed(true, iceServers);
}
public void changeICEServers(String[] iceServers) {
iceServersPacket = IntegratedVoiceSignalPackets.makeVoiceSignalPacketAllowed(true, iceServers);
}
private static class VoicePair {
private final EaglercraftUUID uuid1;
private final EaglercraftUUID uuid2;
@Override
public int hashCode() {
return uuid1.hashCode() ^ uuid2.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
VoicePair other = (VoicePair) obj;
return (uuid1.equals(other.uuid1) && uuid2.equals(other.uuid2))
|| (uuid1.equals(other.uuid2) && uuid2.equals(other.uuid1));
}
private VoicePair(EaglercraftUUID uuid1, EaglercraftUUID uuid2) {
this.uuid1 = uuid1;
this.uuid2 = uuid2;
}
private boolean anyEquals(EaglercraftUUID uuid) {
return uuid1.equals(uuid) || uuid2.equals(uuid);
}
}
public void handlePlayerLoggedIn(EntityPlayerMP player) {
player.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL, new PacketBuffer(
Unpooled.buffer(iceServersPacket, iceServersPacket.length).writerIndex(iceServersPacket.length))));
}
public void handlePlayerLoggedOut(EntityPlayerMP player) {
removeUser(player.getUniqueID());
}
public void processPacket(PacketBuffer packetData, EntityPlayerMP sender) {
try {
IntegratedVoiceSignalPackets.processPacket(packetData, sender, this);
} catch (IOException e) {
logger.error("Invalid voice signal packet recieved from player {}!", sender.getName());
logger.error(e);
sender.playerNetServerHandler.kickPlayerFromServer("Invalid voice signal packet recieved!");
}
}
void handleVoiceSignalPacketTypeRequest(EaglercraftUUID player, EntityPlayerMP sender) {
EaglercraftUUID senderUUID = sender.getUniqueID();
if (senderUUID.equals(player))
return; // prevent duplicates
if (!voicePlayers.containsKey(senderUUID))
return;
EntityPlayerMP targetPlayerCon = voicePlayers.get(player);
if (targetPlayerCon == null)
return;
VoicePair newPair = new VoicePair(player, senderUUID);
if (voicePairs.contains(newPair))
return; // already paired
ExpiringSet<EaglercraftUUID> senderRequestSet = voiceRequests.get(senderUUID);
if (senderRequestSet == null) {
voiceRequests.put(senderUUID, senderRequestSet = new ExpiringSet<>(2000));
}
if (!senderRequestSet.add(player)) {
return;
}
// check if other has requested earlier
ExpiringSet<EaglercraftUUID> theSet;
if ((theSet = voiceRequests.get(player)) != null && theSet.contains(senderUUID)) {
theSet.remove(senderUUID);
if (theSet.isEmpty())
voiceRequests.remove(player);
senderRequestSet.remove(player);
if (senderRequestSet.isEmpty())
voiceRequests.remove(senderUUID);
// send each other add data
voicePairs.add(newPair);
targetPlayerCon.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL,
IntegratedVoiceSignalPackets.makeVoiceSignalPacketConnect(senderUUID, false)));
sender.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL,
IntegratedVoiceSignalPackets.makeVoiceSignalPacketConnect(player, true)));
}
}
void handleVoiceSignalPacketTypeConnect(EntityPlayerMP sender) {
if (voicePlayers.containsKey(sender.getUniqueID())) {
return;
}
boolean hasNoOtherPlayers = voicePlayers.isEmpty();
voicePlayers.put(sender.getUniqueID(), sender);
if (hasNoOtherPlayers) {
return;
}
byte[] packetToBroadcast = IntegratedVoiceSignalPackets.makeVoiceSignalPacketGlobal(voicePlayers.values());
for (EntityPlayerMP userCon : voicePlayers.values()) {
userCon.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL, new PacketBuffer(Unpooled
.buffer(packetToBroadcast, packetToBroadcast.length).writerIndex(packetToBroadcast.length))));
}
}
void handleVoiceSignalPacketTypeICE(EaglercraftUUID player, String str, EntityPlayerMP sender) {
VoicePair pair = new VoicePair(player, sender.getUniqueID());
EntityPlayerMP pass = voicePairs.contains(pair) ? voicePlayers.get(player) : null;
if (pass != null) {
pass.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL,
IntegratedVoiceSignalPackets.makeVoiceSignalPacketICE(sender.getUniqueID(), str)));
}
}
void handleVoiceSignalPacketTypeDesc(EaglercraftUUID player, String str, EntityPlayerMP sender) {
VoicePair pair = new VoicePair(player, sender.getUniqueID());
EntityPlayerMP pass = voicePairs.contains(pair) ? voicePlayers.get(player) : null;
if (pass != null) {
pass.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL,
IntegratedVoiceSignalPackets.makeVoiceSignalPacketDesc(sender.getUniqueID(), str)));
}
}
void handleVoiceSignalPacketTypeDisconnect(EaglercraftUUID player, EntityPlayerMP sender) {
if (player != null) {
if (!voicePlayers.containsKey(player)) {
return;
}
byte[] userDisconnectPacket = null;
Iterator<VoicePair> pairsItr = voicePairs.iterator();
while (pairsItr.hasNext()) {
VoicePair voicePair = pairsItr.next();
EaglercraftUUID target = null;
if (voicePair.uuid1.equals(player)) {
target = voicePair.uuid2;
} else if (voicePair.uuid2.equals(player)) {
target = voicePair.uuid1;
}
if (target != null) {
pairsItr.remove();
EntityPlayerMP conn = voicePlayers.get(target);
if (conn != null) {
if (userDisconnectPacket == null) {
userDisconnectPacket = IntegratedVoiceSignalPackets.makeVoiceSignalPacketDisconnect(player);
}
conn.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL,
new PacketBuffer(Unpooled.buffer(userDisconnectPacket, userDisconnectPacket.length)
.writerIndex(userDisconnectPacket.length))));
}
sender.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL,
IntegratedVoiceSignalPackets.makeVoiceSignalPacketDisconnectPB(target)));
}
}
} else {
removeUser(sender.getUniqueID());
}
}
public void removeUser(EaglercraftUUID user) {
if (voicePlayers.remove(user) == null) {
return;
}
voiceRequests.remove(user);
if (voicePlayers.size() > 0) {
byte[] voicePlayersPkt = IntegratedVoiceSignalPackets.makeVoiceSignalPacketGlobal(voicePlayers.values());
for (EntityPlayerMP userCon : voicePlayers.values()) {
if (!user.equals(userCon.getUniqueID())) {
userCon.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL,
new PacketBuffer(Unpooled.buffer(voicePlayersPkt, voicePlayersPkt.length)
.writerIndex(voicePlayersPkt.length))));
}
}
}
byte[] userDisconnectPacket = null;
Iterator<VoicePair> pairsItr = voicePairs.iterator();
while (pairsItr.hasNext()) {
VoicePair voicePair = pairsItr.next();
EaglercraftUUID target = null;
if (voicePair.uuid1.equals(user)) {
target = voicePair.uuid2;
} else if (voicePair.uuid2.equals(user)) {
target = voicePair.uuid1;
}
if (target != null) {
pairsItr.remove();
if (voicePlayers.size() > 0) {
EntityPlayerMP conn = voicePlayers.get(target);
if (conn != null) {
if (userDisconnectPacket == null) {
userDisconnectPacket = IntegratedVoiceSignalPackets.makeVoiceSignalPacketDisconnect(user);
}
conn.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL,
new PacketBuffer(Unpooled.buffer(userDisconnectPacket, userDisconnectPacket.length)
.writerIndex(userDisconnectPacket.length))));
}
}
}
}
}
}

View File

@ -0,0 +1,198 @@
package net.lax1dude.eaglercraft.v1_8.sp.server.voice;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.netty.ByteBuf;
import net.lax1dude.eaglercraft.v1_8.netty.Unpooled;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.PacketBuffer;
/**
* Copyright (c) 2024 lax1dude. 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 IntegratedVoiceSignalPackets {
static final int VOICE_SIGNAL_ALLOWED = 0;
static final int VOICE_SIGNAL_REQUEST = 0;
static final int VOICE_SIGNAL_CONNECT = 1;
static final int VOICE_SIGNAL_DISCONNECT = 2;
static final int VOICE_SIGNAL_ICE = 3;
static final int VOICE_SIGNAL_DESC = 4;
static final int VOICE_SIGNAL_GLOBAL = 5;
public static void processPacket(PacketBuffer buffer, EntityPlayerMP sender, IntegratedVoiceService voiceService) throws IOException {
int packetId = -1;
if(buffer.readableBytes() == 0) {
throw new IOException("Zero-length packet recieved");
}
try {
packetId = buffer.readUnsignedByte();
switch(packetId) {
case VOICE_SIGNAL_REQUEST: {
voiceService.handleVoiceSignalPacketTypeRequest(buffer.readUuid(), sender);
break;
}
case VOICE_SIGNAL_CONNECT: {
voiceService.handleVoiceSignalPacketTypeConnect(sender);
break;
}
case VOICE_SIGNAL_ICE: {
voiceService.handleVoiceSignalPacketTypeICE(buffer.readUuid(), buffer.readStringFromBuffer(32767), sender);
break;
}
case VOICE_SIGNAL_DESC: {
voiceService.handleVoiceSignalPacketTypeDesc(buffer.readUuid(), buffer.readStringFromBuffer(32767), sender);
break;
}
case VOICE_SIGNAL_DISCONNECT: {
voiceService.handleVoiceSignalPacketTypeDisconnect(buffer.readableBytes() > 0 ? buffer.readUuid() : null, sender);
break;
}
default: {
throw new IOException("Unknown packet type " + packetId);
}
}
if(buffer.readableBytes() > 0) {
throw new IOException("Voice packet is too long!");
}
}catch(IOException ex) {
throw ex;
}catch(Throwable t) {
throw new IOException("Unhandled exception handling voice packet type " + packetId, t);
}
}
static byte[] makeVoiceSignalPacketAllowed(boolean allowed, String[] iceServers) {
if (iceServers == null) {
byte[] ret = new byte[2];
ByteBuf wrappedBuffer = Unpooled.buffer(ret, ret.length);
wrappedBuffer.writeByte(VOICE_SIGNAL_ALLOWED);
wrappedBuffer.writeBoolean(allowed);
return ret;
}
byte[][] iceServersBytes = new byte[iceServers.length][];
int totalLen = 2 + PacketBuffer.getVarIntSize(iceServers.length);
for(int i = 0; i < iceServers.length; ++i) {
byte[] b = iceServersBytes[i] = iceServers[i].getBytes(StandardCharsets.UTF_8);
totalLen += PacketBuffer.getVarIntSize(b.length) + b.length;
}
byte[] ret = new byte[totalLen];
PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length));
wrappedBuffer.writeByte(VOICE_SIGNAL_ALLOWED);
wrappedBuffer.writeBoolean(allowed);
wrappedBuffer.writeVarIntToBuffer(iceServersBytes.length);
for(int i = 0; i < iceServersBytes.length; ++i) {
byte[] b = iceServersBytes[i];
wrappedBuffer.writeVarIntToBuffer(b.length);
wrappedBuffer.writeBytes(b);
}
return ret;
}
static byte[] makeVoiceSignalPacketGlobal(Collection<EntityPlayerMP> users) {
int cnt = users.size();
byte[][] displayNames = new byte[cnt][];
int i = 0;
for(EntityPlayerMP user : users) {
String name = user.getName();
if(name.length() > 16) name = name.substring(0, 16);
displayNames[i++] = name.getBytes(StandardCharsets.UTF_8);
}
int totalLength = 1 + PacketBuffer.getVarIntSize(cnt) + (cnt << 4);
for(i = 0; i < cnt; ++i) {
totalLength += PacketBuffer.getVarIntSize(displayNames[i].length) + displayNames[i].length;
}
byte[] ret = new byte[totalLength];
PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length));
wrappedBuffer.writeByte(VOICE_SIGNAL_GLOBAL);
wrappedBuffer.writeVarIntToBuffer(cnt);
for(EntityPlayerMP user : users) {
wrappedBuffer.writeUuid(user.getUniqueID());
}
for(i = 0; i < cnt; ++i) {
wrappedBuffer.writeVarIntToBuffer(displayNames[i].length);
wrappedBuffer.writeBytes(displayNames[i]);
}
return ret;
}
static PacketBuffer makeVoiceSignalPacketConnect(EaglercraftUUID player, boolean offer) {
byte[] ret = new byte[18];
PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length));
wrappedBuffer.writeByte(VOICE_SIGNAL_CONNECT);
wrappedBuffer.writeUuid(player);
wrappedBuffer.writeBoolean(offer);
return wrappedBuffer;
}
static byte[] makeVoiceSignalPacketConnectAnnounce(EaglercraftUUID player) {
byte[] ret = new byte[17];
PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length));
wrappedBuffer.writeByte(VOICE_SIGNAL_CONNECT);
wrappedBuffer.writeUuid(player);
return ret;
}
static byte[] makeVoiceSignalPacketDisconnect(EaglercraftUUID player) {
if(player == null) {
return new byte[] { (byte)VOICE_SIGNAL_DISCONNECT };
}
byte[] ret = new byte[17];
PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length));
wrappedBuffer.writeByte(VOICE_SIGNAL_DISCONNECT);
wrappedBuffer.writeUuid(player);
return ret;
}
static PacketBuffer makeVoiceSignalPacketDisconnectPB(EaglercraftUUID player) {
if(player == null) {
byte[] ret = new byte[1];
PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length));
wrappedBuffer.writeByte(VOICE_SIGNAL_DISCONNECT);
return wrappedBuffer;
}
byte[] ret = new byte[17];
PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length));
wrappedBuffer.writeByte(VOICE_SIGNAL_DISCONNECT);
wrappedBuffer.writeUuid(player);
return wrappedBuffer;
}
static PacketBuffer makeVoiceSignalPacketICE(EaglercraftUUID player, String str) {
byte[] strBytes = str.getBytes(StandardCharsets.UTF_8);
byte[] ret = new byte[17 + PacketBuffer.getVarIntSize(strBytes.length) + strBytes.length];
PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length));
wrappedBuffer.writeByte(VOICE_SIGNAL_ICE);
wrappedBuffer.writeUuid(player);
wrappedBuffer.writeVarIntToBuffer(strBytes.length);
wrappedBuffer.writeBytes(strBytes);
return wrappedBuffer;
}
static PacketBuffer makeVoiceSignalPacketDesc(EaglercraftUUID player, String str) {
byte[] strBytes = str.getBytes(StandardCharsets.UTF_8);
byte[] ret = new byte[17 + PacketBuffer.getVarIntSize(strBytes.length) + strBytes.length];
PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length));
wrappedBuffer.writeByte(VOICE_SIGNAL_DESC);
wrappedBuffer.writeUuid(player);
wrappedBuffer.writeVarIntToBuffer(strBytes.length);
wrappedBuffer.writeBytes(strBytes);
return wrappedBuffer;
}
}

View File

@ -41,6 +41,8 @@ public class GuiUpdateCheckerOverlay extends Gui {
private int width;
private int height;
private int totalHeightOffset = 0;
private boolean isIngame;
private GuiScreen backScreen;
@ -61,10 +63,10 @@ public class GuiUpdateCheckerOverlay extends Gui {
this.mc = mc;
this.width = w;
this.height = h;
checkForUpdatesButton = new GuiButton(0, w - 150, 0, 150, 20, I18n.format("update.button") + " " + I18n.format(mc.gameSettings.enableUpdateSvc ? "gui.yes" : "gui.no"));
startDownloadButton = new GuiButton(1, w - 115, 0, 115, 20, I18n.format("update.startDownload"));
viewAllUpdatesButton = new GuiButton(2, w - 115, 0, 115, 20, I18n.format("update.viewAll", 0));
dismissUpdatesButton = new GuiButton(3, w - 115, 0, 115, 20, I18n.format("update.dismiss"));
checkForUpdatesButton = new GuiButton(0, 0, 0, 150, 20, I18n.format("update.button") + " " + I18n.format(mc.gameSettings.enableUpdateSvc ? "gui.yes" : "gui.no"));
startDownloadButton = new GuiButton(1, 1, 0, 115, 20, I18n.format("update.startDownload"));
viewAllUpdatesButton = new GuiButton(2, 1, 0, 115, 20, I18n.format("update.viewAll", 0));
dismissUpdatesButton = new GuiButton(3, 1, 0, 115, 20, I18n.format("update.dismiss"));
}
public void drawScreen(int mx, int my, float partialTicks) {
@ -81,6 +83,7 @@ public class GuiUpdateCheckerOverlay extends Gui {
startDownloadButton.visible = false;
viewAllUpdatesButton.visible = false;
dismissUpdatesButton.visible = false;
totalHeightOffset = 0;
int i = UpdateService.getAvailableUpdates().size();
boolean shownSP = i > 0 || !mc.isSingleplayer() || LANServerController.isHostingLAN();
@ -95,7 +98,7 @@ public class GuiUpdateCheckerOverlay extends Gui {
dismissUpdatesButton.visible = true;
viewAllUpdatesButton.displayString = I18n.format("update.viewAll", i);
str = I18n.format("update.found");
mc.fontRendererObj.drawStringWithShadow(str, width - mc.fontRendererObj.getStringWidth(str) - 3, 22, 0xFFFFAA);
mc.fontRendererObj.drawStringWithShadow(str, 3, 22, 0xFFFFAA);
int embedY = 35;
int embedWidth = 115;
@ -109,7 +112,7 @@ public class GuiUpdateCheckerOverlay extends Gui {
}
GlStateManager.pushMatrix();
GlStateManager.translate(width - embedWidth - 1, embedY, 0.0f);
GlStateManager.translate(1.0f, embedY, 0.0f);
GlStateManager.scale(0.75f, 0.75f, 0.75f);
int embedHeight2 = (int)(embedHeight / 0.75f);
@ -143,16 +146,20 @@ public class GuiUpdateCheckerOverlay extends Gui {
startDownloadButton.yPosition = embedHeight + embedY + 5;
viewAllUpdatesButton.yPosition = startDownloadButton.yPosition + 22;
dismissUpdatesButton.yPosition = viewAllUpdatesButton.yPosition + 22;
totalHeightOffset = dismissUpdatesButton.yPosition + 20;
GlStateManager.popMatrix();
}else if(isIngame) {
if(shownSP) {
str = I18n.format("update.noneNew");
mc.fontRendererObj.drawString(str, width - mc.fontRendererObj.getStringWidth(str) - 3, 22, 0xDDDDDD);
mc.fontRendererObj.drawString(str, 3, 22, 0xDDDDDD);
if(i > 0) {
viewAllUpdatesButton.yPosition = 40;
viewAllUpdatesButton.visible = true;
viewAllUpdatesButton.displayString = I18n.format("update.viewAll", i);
totalHeightOffset = 60;
}else {
totalHeightOffset = 32;
}
}
}
@ -173,23 +180,23 @@ public class GuiUpdateCheckerOverlay extends Gui {
viewAllUpdatesButton.visible = false;
dismissUpdatesButton.visible = false;
GlStateManager.pushMatrix();
GlStateManager.translate(width, isIngame ? 0.0f : 10.0f, 0.0f);
GlStateManager.translate(1.0f, isIngame ? 0.0f : 18.0f, 0.0f);
String str = I18n.format("update.downloading");
mc.fontRendererObj.drawStringWithShadow(str, -mc.fontRendererObj.getStringWidth(str) - 2, 2, 0xFFFFAA);
mc.fontRendererObj.drawStringWithShadow(str, 2, 2, 0xFFFFAA);
GlStateManager.translate(0.0f, 14.0f, 0.0f);
GlStateManager.scale(0.75f, 0.75f, 0.75f);
if(!StringUtils.isAllBlank(progressState.statusString1)) {
str = progressState.statusString1;
mc.fontRendererObj.drawStringWithShadow(str, -mc.fontRendererObj.getStringWidth(str) - 3, 0, 0xFFFFFF);
mc.fontRendererObj.drawStringWithShadow(str, 3, 0, 0xFFFFFF);
}
int cc = isIngame ? 0xBBBBBB : 0xFFFFFF;
if(!StringUtils.isAllBlank(progressState.statusString2)) {
str = progressState.statusString2;
mc.fontRendererObj.drawStringWithShadow(str, -mc.fontRendererObj.getStringWidth(str) - 3, 11, cc);
mc.fontRendererObj.drawStringWithShadow(str, 3, 11, cc);
}
int progX1 = -135;
int progX1 = 3;
int progY1 = 22;
int progX2 = -3;
int progX2 = 135;
int progY2 = 32;
float prog = progressState.progressBar;
if(prog >= 0.0f) {
@ -202,6 +209,7 @@ public class GuiUpdateCheckerOverlay extends Gui {
drawGradientRect(progX1, progY1 + 1, progX1 + 1, progY2 - 1, 0xFF000000, 0xFF000000);
drawGradientRect(progX2 - 1, progY1 + 1, progX2, progY2 - 1, 0xFF000000, 0xFF000000);
}
totalHeightOffset = 32;
if(!StringUtils.isAllBlank(progressState.statusString3)) {
GlStateManager.translate(0.0f, progY2 + 2, 0.0f);
GlStateManager.scale(0.66f, 0.66f, 0.66f);
@ -209,10 +217,12 @@ public class GuiUpdateCheckerOverlay extends Gui {
List<String> wrappedURL = mc.fontRendererObj.listFormattedStringToWidth(str, (int)((progX2 - progX1) * 1.5f));
for(int i = 0, l = wrappedURL.size(); i < l; ++i) {
str = wrappedURL.get(i);
mc.fontRendererObj.drawStringWithShadow(str, -mc.fontRendererObj.getStringWidth(str) - 5, i * 11, cc);
mc.fontRendererObj.drawStringWithShadow(str, 5, i * 11, cc);
}
totalHeightOffset += (int)(wrappedURL.size() * 5.5f);
}
GlStateManager.popMatrix();
}
public void mouseClicked(int mx, int my, int btn) {
@ -244,4 +254,8 @@ public class GuiUpdateCheckerOverlay extends Gui {
}
}
}
public int getSharedWorldInfoYOffset() {
return totalHeightOffset;
}
}

View File

@ -0,0 +1,20 @@
package net.lax1dude.eaglercraft.v1_8.voice;
/**
* Copyright (c) 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 enum EnumVoiceChannelPeerState {
FAILED, SUCCESS, LOADING;
}

View File

@ -0,0 +1,20 @@
package net.lax1dude.eaglercraft.v1_8.voice;
/**
* Copyright (c) 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 enum EnumVoiceChannelReadyState {
NONE, ABORTED, DEVICE_INITIALIZED;
}

View File

@ -0,0 +1,20 @@
package net.lax1dude.eaglercraft.v1_8.voice;
/**
* Copyright (c) 2022-2024 lax1dude. 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 enum EnumVoiceChannelStatus {
DISCONNECTED, CONNECTING, CONNECTED, UNAVAILABLE;
}

View File

@ -0,0 +1,20 @@
package net.lax1dude.eaglercraft.v1_8.voice;
/**
* Copyright (c) 2022-2024 lax1dude. 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 enum EnumVoiceChannelType {
NONE, GLOBAL, PROXIMITY;
}

View File

@ -0,0 +1,84 @@
package net.lax1dude.eaglercraft.v1_8.voice;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
/**
* Copyright (c) 2022 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 ExpiringSet<T> extends HashSet<T> {
private final long expiration;
private final ExpiringEvent<T> event;
private final Map<T, Long> timestamps = new HashMap<>();
public ExpiringSet(long expiration) {
this.expiration = expiration;
this.event = null;
}
public ExpiringSet(long expiration, ExpiringEvent<T> event) {
this.expiration = expiration;
this.event = event;
}
public interface ExpiringEvent<T> {
void onExpiration(T item);
}
public void checkForExpirations() {
Iterator<T> iterator = this.timestamps.keySet().iterator();
long now = System.currentTimeMillis();
while (iterator.hasNext()) {
T element = iterator.next();
if (super.contains(element)) {
if (this.timestamps.get(element) + this.expiration < now) {
if (this.event != null) this.event.onExpiration(element);
iterator.remove();
super.remove(element);
}
} else {
iterator.remove();
super.remove(element);
}
}
}
public boolean add(T o) {
checkForExpirations();
boolean success = super.add(o);
if (success) timestamps.put(o, System.currentTimeMillis());
return success;
}
public boolean remove(Object o) {
checkForExpirations();
boolean success = super.remove(o);
if (success) timestamps.remove(o);
return success;
}
public void clear() {
this.timestamps.clear();
super.clear();
}
public boolean contains(Object o) {
checkForExpirations();
return super.contains(o);
}
}

View File

@ -0,0 +1,772 @@
package net.lax1dude.eaglercraft.v1_8.voice;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import java.util.List;
import java.util.Set;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.Keyboard;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.lax1dude.eaglercraft.v1_8.sp.gui.GuiSlider2;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2022-2024 lax1dude, 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 GuiVoiceMenu extends Gui {
public class AbortedException extends RuntimeException {
}
private static final ResourceLocation voiceGuiIcons = new ResourceLocation("eagler:gui/eagler_gui.png");
protected final GuiScreen parent;
protected Minecraft mc;
protected FontRenderer fontRendererObj;
protected int width;
protected int height;
protected int voiceButtonOFFposX;
protected int voiceButtonOFFposY;
protected int voiceButtonOFFposW;
protected int voiceButtonOFFposH;
protected int voiceButtonRADIUSposX;
protected int voiceButtonRADIUSposY;
protected int voiceButtonRADIUSposW;
protected int voiceButtonRADIUSposH;
protected int voiceButtonGLOBALposX;
protected int voiceButtonGLOBALposY;
protected int voiceButtonGLOBALposW;
protected int voiceButtonGLOBALposH;
protected int voiceScreenButtonOFFposX;
protected int voiceScreenButtonOFFposY;
protected int voiceScreenButtonOFFposW;
protected int voiceScreenButtonOFFposH;
protected int voiceScreenButtonRADIUSposX;
protected int voiceScreenButtonRADIUSposY;
protected int voiceScreenButtonRADIUSposW;
protected int voiceScreenButtonRADIUSposH;
protected int voiceScreenButtonGLOBALposX;
protected int voiceScreenButtonGLOBALposY;
protected int voiceScreenButtonGLOBALposW;
protected int voiceScreenButtonGLOBALposH;
protected int voiceScreenButtonChangeRadiusposX;
protected int voiceScreenButtonChangeRadiusposY;
protected int voiceScreenButtonChangeRadiusposW;
protected int voiceScreenButtonChangeRadiusposH;
protected int voiceScreenVolumeIndicatorX;
protected int voiceScreenVolumeIndicatorY;
protected int voiceScreenVolumeIndicatorW;
protected int voiceScreenVolumeIndicatorH;
protected boolean showSliderBlocks = false;
protected boolean showSliderVolume = false;
protected boolean showPTTKeyConfig = false;
protected int showNewPTTKey = 0;
protected GuiSlider2 sliderBlocks = null;
protected GuiSlider2 sliderListenVolume = null;
protected GuiSlider2 sliderSpeakVolume = null;
protected GuiButton applyRadiusButton = null;
protected GuiButton applyVolumeButton = null;
protected GuiButton noticeContinueButton = null;
protected GuiButton noticeCancelButton = null;
protected static boolean showingCompatWarning = false;
protected static boolean showCompatWarning = true;
protected static boolean showingTrackingWarning = false;
protected static boolean showTrackingWarning = true;
protected static EnumVoiceChannelType continueChannel = null;
public GuiVoiceMenu(GuiScreen parent) {
this.parent = parent;
}
public void setResolution(Minecraft mc, int w, int h) {
this.mc = mc;
this.fontRendererObj = mc.fontRendererObj;
this.width = w;
this.height = h;
initGui();
}
public void initGui() {
this.sliderBlocks = new GuiSlider2(-1, (width - 150) / 2, height / 3 + 20, 150, 20, (VoiceClientController.getVoiceProximity() - 5) / 17.0f, 1.0f) {
public boolean mousePressed(Minecraft par1Minecraft, int par2, int par3) {
if(super.mousePressed(par1Minecraft, par2, par3)) {
this.displayString = "" + (int)((sliderValue * 17.0f) + 5.0f) + " Blocks";
return true;
}else {
return false;
}
}
public void mouseDragged(Minecraft par1Minecraft, int par2, int par3) {
super.mouseDragged(par1Minecraft, par2, par3);
this.displayString = "" + (int)((sliderValue * 17.0f) + 5.0f) + " Blocks";
}
};
sliderBlocks.displayString = "" + VoiceClientController.getVoiceProximity() + " Blocks";
this.sliderListenVolume = new GuiSlider2(-1, (width - 150) / 2, height / 3 + 10, 150, 20, VoiceClientController.getVoiceListenVolume(), 1.0f);
this.sliderSpeakVolume = new GuiSlider2(-1, (width - 150) / 2, height / 3 + 56, 150, 20, VoiceClientController.getVoiceSpeakVolume(), 1.0f);
applyRadiusButton = new GuiButton(2, (width - 150) / 2, height / 3 + 49, 150, 20, I18n.format("voice.apply"));
applyVolumeButton = new GuiButton(3, (width - 150) / 2, height / 3 + 90, 150, 20, I18n.format("voice.apply"));
noticeContinueButton = new GuiButton(5, (width - 150) / 2, height / 3 + 60, 150, 20, I18n.format("voice.unsupportedWarning10"));
noticeCancelButton = new GuiButton(6, (width - 150) / 2, height / 3 + 90, 150, 20, I18n.format("voice.unsupportedWarning11"));
applyRadiusButton.visible = applyVolumeButton.visible = noticeContinueButton.visible = noticeCancelButton.visible = false;
}
private void drawButtons(int mx, int my, float partialTicks) {
applyRadiusButton.drawButton(mc, mx, my);
applyVolumeButton.drawButton(mc, mx, my);
noticeContinueButton.drawButton(mc, mx, my);
noticeCancelButton.drawButton(mc, mx, my);
}
public void drawScreen(int mx, int my, float partialTicks) {
String txt = I18n.format("voice.title");
drawString(fontRendererObj, txt, width - 5 - fontRendererObj.getStringWidth(txt), 5, 0xFFCC22);
applyRadiusButton.visible = showSliderBlocks;
applyVolumeButton.visible = showSliderVolume;
if(showSliderBlocks || showSliderVolume || showPTTKeyConfig) {
drawRect(0, 0, this.width, this.height, 0xB0101010);
if(showSliderBlocks) {
drawRect(width / 2 - 86, height / 4 - 1, this.width / 2 + 86, height / 3 + 64 + height / 16, 0xFFDDDDDD);
drawRect(width / 2 - 85, height / 4 + 0, this.width / 2 + 85, height / 3 + 63 + height / 16, 0xFF333333);
drawCenteredString(this.fontRendererObj, I18n.format("voice.radiusTitle"), this.width / 2, height / 4 + 9, 16777215);
drawString(this.fontRendererObj, I18n.format("voice.radiusLabel"), (this.width - 150) / 2 + 3, height / 3 + 6, 0xCCCCCC);
sliderBlocks.drawButton(mc, mx, my);
}else if(showSliderVolume) {
drawRect(width / 2 - 86, height / 4 - 11, this.width / 2 + 86, height / 3 + 104 + height / 16, 0xFFDDDDDD);
drawRect(width / 2 - 85, height / 4 - 10, this.width / 2 + 85, height / 3 + 103 + height / 16, 0xFF333333);
drawCenteredString(this.fontRendererObj, I18n.format("voice.volumeTitle"), this.width / 2, height / 4 - 1, 16777215);
drawString(this.fontRendererObj, I18n.format("voice.volumeListen"), (this.width - 150) / 2 + 3, height / 3 - 4, 0xCCCCCC);
sliderListenVolume.drawButton(mc, mx, my);
drawString(this.fontRendererObj, I18n.format("voice.volumeSpeak"), (this.width - 150) / 2 + 3, height / 3 + 42, 0xCCCCCC);
sliderSpeakVolume.drawButton(mc, mx, my);
}else if(showPTTKeyConfig) {
drawRect(width / 2 - 86, height / 3 - 10, this.width / 2 + 86, height / 3 + 35, 0xFFDDDDDD);
drawRect(width / 2 - 85, height / 3 - 9, this.width / 2 + 85, height / 3 + 34, 0xFF333333);
if(showNewPTTKey > 0) {
GlStateManager.pushMatrix();
GlStateManager.translate(this.width / 2, height / 3 + 5, 0.0f);
GlStateManager.scale(2.0f, 2.0f, 2.0f);
drawCenteredString(this.fontRendererObj, Keyboard.getKeyName(mc.gameSettings.voicePTTKey), 0, 0, 0xFFCC11);
GlStateManager.popMatrix();
}else {
drawCenteredString(this.fontRendererObj, I18n.format("voice.pttChangeDesc"), this.width / 2, height / 3 + 8, 16777215);
}
}
drawButtons(mx, my, partialTicks);
throw new AbortedException();
}
GlStateManager.pushMatrix();
GlStateManager.translate(width - 6, 15, 0.0f);
GlStateManager.scale(0.75f, 0.75f, 0.75f);
if(!VoiceClientController.isClientSupported()) {
txt = I18n.format("voice.titleVoiceUnavailable");
drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 6, 0xFF7777);
txt = I18n.format("voice.titleVoiceBrowserError");
drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 19, 0xAA4444);
GlStateManager.popMatrix();
return;
}
if(!VoiceClientController.isServerSupported()) {
txt = I18n.format("voice.titleNoVoice");
drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 5, 0xFF7777);
GlStateManager.popMatrix();
return;
}
int xo = 0;
// this feature is optional
//if(VoiceClientController.voiceRelayed()) {
// txt = I18n.format("voice.warning1");
// drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 8, 0xBB9999);
// txt = I18n.format("voice.warning2");
// drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 18, 0xBB9999);
// txt = I18n.format("voice.warning3");
// drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 28, 0xBB9999);
// xo = 43;
// GlStateManager.translate(0.0f, xo, 0.0f);
//}
EnumVoiceChannelStatus status = VoiceClientController.getVoiceStatus();
EnumVoiceChannelType channel = VoiceClientController.getVoiceChannel();
boolean flag = false;
if(channel == EnumVoiceChannelType.NONE) {
flag = true;
}else {
if(status == EnumVoiceChannelStatus.CONNECTED) {
if(channel == EnumVoiceChannelType.PROXIMITY) {
txt = I18n.format("voice.connectedRadius").replace("$radius$", "" + VoiceClientController.getVoiceProximity()).replace("$f$", "");
int w = fontRendererObj.getStringWidth(txt);
int xx = width - 5 - (w * 3 / 4);
int yy = 15 + (xo * 3 / 4);
voiceScreenButtonChangeRadiusposX = xx;
voiceScreenButtonChangeRadiusposY = yy;
voiceScreenButtonChangeRadiusposW = width - 3 - xx;
voiceScreenButtonChangeRadiusposH = 12;
if(mx >= xx && my >= yy && mx < xx + voiceScreenButtonChangeRadiusposW && my < yy + 12) {
txt = I18n.format("voice.connectedRadius").replace("$radius$", "" + VoiceClientController.getVoiceProximity())
.replace("$f$", "" + EnumChatFormatting.UNDERLINE) + EnumChatFormatting.RESET;
}
}else {
txt = I18n.format("voice.connectedGlobal");
}
voiceScreenVolumeIndicatorX = width - 15 - (104 * 3 / 4);
voiceScreenVolumeIndicatorY = 15 + (xo * 3 / 4) + 30;
voiceScreenVolumeIndicatorW = width - voiceScreenVolumeIndicatorX - 4;
voiceScreenVolumeIndicatorH = 23;
drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 5, 0x66DD66);
drawRect(-90, 42, 2, 52, 0xFFAAAAAA);
drawRect(-89, 43, 1, 51, 0xFF222222);
float vol = VoiceClientController.getVoiceListenVolume();
drawRect(-89, 43, -89 + (int)(vol * 90), 51, 0xFF993322);
for(float f = 0.07f; f < vol; f += 0.08f) {
int ww = (int)(f * 90);
drawRect(-89 + ww, 43, -89 + ww + 1, 51, 0xFF999999);
}
drawRect(-90, 57, 2, 67, 0xFFAAAAAA);
drawRect(-89, 58, 1, 66, 0xFF222222);
vol = VoiceClientController.getVoiceSpeakVolume();
drawRect(-89, 58, -89 + (int)(vol * 90), 66, 0xFF993322);
for(float f = 0.07f; f < vol; f += 0.08f) {
int ww = (int)(f * 90);
drawRect(-89 + ww, 58, -89 + ww + 1, 66, 0xFF999999);
}
mc.getTextureManager().bindTexture(voiceGuiIcons);
GlStateManager.color(0.7f, 0.7f, 0.7f, 1.0f);
GlStateManager.pushMatrix();
GlStateManager.translate(-104.0f, 41.5f, 0.0f);
GlStateManager.scale(0.7f, 0.7f, 0.7f);
drawTexturedModalRect(0, 0, 64, 144, 16, 16);
GlStateManager.popMatrix();
GlStateManager.pushMatrix();
GlStateManager.translate(-104.0f, 56.5f, 0.0f);
GlStateManager.scale(0.7f, 0.7f, 0.7f);
if((mc.currentScreen == null || !mc.currentScreen.blockPTTKey()) && Keyboard.isKeyDown(mc.gameSettings.voicePTTKey)) {
GlStateManager.color(0.9f, 0.4f, 0.4f, 1.0f);
drawTexturedModalRect(0, 0, 64, 64, 16, 16);
}else {
drawTexturedModalRect(0, 0, 64, 32, 16, 16);
}
GlStateManager.popMatrix();
txt = I18n.format("voice.ptt", Keyboard.getKeyName(mc.gameSettings.voicePTTKey));
drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt) - 10, 76, 0x66DD66);
mc.getTextureManager().bindTexture(voiceGuiIcons);
GlStateManager.color(0.4f, 0.9f, 0.4f, 1.0f);
GlStateManager.pushMatrix();
GlStateManager.translate(-7.0f, 74.5f, 0.0f);
GlStateManager.scale(0.35f, 0.35f, 0.35f);
drawTexturedModalRect(0, 0, 32, 224, 32, 32);
GlStateManager.popMatrix();
txt = I18n.format("voice.playersListening");
GlStateManager.pushMatrix();
GlStateManager.translate(0.0f, 98.0f, 0.0f);
GlStateManager.scale(1.2f, 1.2f, 1.2f);
drawString(fontRendererObj, txt, -fontRendererObj.getStringWidth(txt), 0, 0xFF7777);
GlStateManager.popMatrix();
List<EaglercraftUUID> playersToRender = VoiceClientController.getVoiceRecent();
if(playersToRender.size() > 0) {
EaglercraftUUID uuid;
Set<EaglercraftUUID> playersSpeaking = VoiceClientController.getVoiceSpeaking();
Set<EaglercraftUUID> playersMuted = VoiceClientController.getVoiceMuted();
for(int i = 0, l = playersToRender.size(); i < l; ++i) {
uuid = playersToRender.get(i);
txt = VoiceClientController.getVoiceUsername(uuid);
boolean muted = playersMuted.contains(uuid);
boolean speaking = !muted && playersSpeaking.contains(uuid);
int mhy = voiceScreenVolumeIndicatorY + voiceScreenVolumeIndicatorH + 33 + i * 9;
boolean hovered = mx >= voiceScreenVolumeIndicatorX - 3 && my >= mhy && mx < voiceScreenVolumeIndicatorX + voiceScreenVolumeIndicatorW + 2 && my < mhy + 9;
float cm = hovered ? 1.5f : 1.0f;
mc.getTextureManager().bindTexture(voiceGuiIcons);
GlStateManager.pushMatrix();
GlStateManager.translate(-100.0f, 115.0f + i * 12.0f, 0.0f);
GlStateManager.scale(0.78f, 0.78f, 0.78f);
if(muted) {
GlStateManager.color(1.0f * cm, 0.2f * cm, 0.2f * cm, 1.0f);
drawTexturedModalRect(0, 0, 64, 208, 16, 16);
}else if(speaking) {
GlStateManager.color(1.0f * cm, 1.0f * cm, 1.0f * cm, 1.0f);
drawTexturedModalRect(0, 0, 64, 176, 16, 16);
}else {
GlStateManager.color(0.65f * cm, 0.65f * cm, 0.65f * cm, 1.0f);
drawTexturedModalRect(0, 0, 64, 144, 16, 16);
}
GlStateManager.popMatrix();
if(muted) {
drawString(fontRendererObj, txt, -84, 117 + i * 12, attenuate(0xCC4444, cm));
}else if(speaking) {
drawString(fontRendererObj, txt, -84, 117 + i * 12, attenuate(0xCCCCCC, cm));
}else {
drawString(fontRendererObj, txt, -84, 117 + i * 12, attenuate(0x999999, cm));
}
}
}else {
txt = "(none)";
drawString(fontRendererObj, txt, -fontRendererObj.getStringWidth(txt), 112, 0xAAAAAA);
}
}else if(status == EnumVoiceChannelStatus.CONNECTING) {
float fadeTimer = MathHelper.sin((float)((System.currentTimeMillis() % 700l) * 0.0014d) * 3.14159f) * 0.35f + 0.3f;
txt = I18n.format("voice.connecting");
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 5, (0xFFDD77 | ((int)(Math.pow(fadeTimer, 1.0d / 2.2d) * 255.0f) << 24)));
GlStateManager.disableBlend();
}else if(status == EnumVoiceChannelStatus.UNAVAILABLE) {
txt = I18n.format("voice.unavailable");
drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 5, 0xFF3333);
}else {
flag = true;
}
}
if(flag) {
txt = I18n.format("voice.notConnected");
drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 5, 0xBB9999);
}
String OFFstring = I18n.format("voice.off");
String RADIUSstring = I18n.format("voice.radius");
String GLOBALstring = I18n.format("voice.global");
int OFFwidth = fontRendererObj.getStringWidth(OFFstring);
int RADIUSwidth = fontRendererObj.getStringWidth(RADIUSstring);
int GLOBALwidth = fontRendererObj.getStringWidth(GLOBALstring);
voiceButtonOFFposX = 0 - OFFwidth - 8 - RADIUSwidth - 8 - GLOBALwidth;
voiceButtonOFFposY = 20;
voiceButtonOFFposW = OFFwidth + 5;
voiceButtonOFFposH = 15;
voiceScreenButtonOFFposX = voiceButtonOFFposX * 3 / 4 + width - 6;
voiceScreenButtonOFFposY = 15 + (voiceButtonOFFposY + xo) * 3 / 4;
voiceScreenButtonOFFposW = voiceButtonOFFposW * 3 / 4;
voiceScreenButtonOFFposH = voiceButtonOFFposH * 3 / 4;
voiceButtonRADIUSposX = 0 - RADIUSwidth - 8 - GLOBALwidth;
voiceButtonRADIUSposY = 20;
voiceButtonRADIUSposW = RADIUSwidth + 5;
voiceButtonRADIUSposH = 15;
voiceScreenButtonRADIUSposX = voiceButtonRADIUSposX * 3 / 4 + width - 6;
voiceScreenButtonRADIUSposY = 15 + (voiceButtonRADIUSposY + xo) * 3 / 4;
voiceScreenButtonRADIUSposW = voiceButtonRADIUSposW * 3 / 4;
voiceScreenButtonRADIUSposH = voiceButtonRADIUSposH * 3 / 4;
voiceButtonGLOBALposX = 0 - GLOBALwidth;
voiceButtonGLOBALposY = 20;
voiceButtonGLOBALposW = GLOBALwidth + 5;
voiceButtonGLOBALposH = 15;
voiceScreenButtonGLOBALposX = voiceButtonGLOBALposX * 3 / 4 + width - 6;
voiceScreenButtonGLOBALposY = 15 + (voiceButtonGLOBALposY + xo) * 3 / 4;
voiceScreenButtonGLOBALposW = voiceButtonGLOBALposW * 3 / 4;
voiceScreenButtonGLOBALposH = voiceButtonGLOBALposH * 3 / 4;
if(channel == EnumVoiceChannelType.NONE) {
drawOutline(voiceButtonOFFposX, voiceButtonOFFposY, voiceButtonOFFposW, voiceButtonOFFposH, 0xFFCCCCCC);
drawRect(voiceButtonOFFposX + 1, voiceButtonOFFposY + 1, voiceButtonOFFposX + voiceButtonOFFposW - 2,
voiceButtonOFFposY + voiceButtonOFFposH - 1, 0xFF222222);
}else if(mx >= voiceScreenButtonOFFposX && my >= voiceScreenButtonOFFposY && mx < voiceScreenButtonOFFposX +
voiceScreenButtonOFFposW && my < voiceScreenButtonOFFposY + voiceScreenButtonOFFposH) {
drawOutline(voiceButtonOFFposX, voiceButtonOFFposY, voiceButtonOFFposW, voiceButtonOFFposH, 0xFF777777);
}
if(channel == EnumVoiceChannelType.PROXIMITY) {
drawOutline(voiceButtonRADIUSposX, voiceButtonRADIUSposY, voiceButtonRADIUSposW, voiceButtonRADIUSposH, 0xFFCCCCCC);
drawRect(voiceButtonRADIUSposX + 1, voiceButtonRADIUSposY + 1, voiceButtonRADIUSposX + voiceButtonRADIUSposW - 2,
voiceButtonRADIUSposY + voiceButtonRADIUSposH - 1, 0xFF222222);
}else if(mx >= voiceScreenButtonRADIUSposX && my >= voiceScreenButtonRADIUSposY && mx < voiceScreenButtonRADIUSposX +
voiceScreenButtonRADIUSposW && my < voiceScreenButtonRADIUSposY + voiceScreenButtonRADIUSposH) {
drawOutline(voiceButtonRADIUSposX, voiceButtonRADIUSposY, voiceButtonRADIUSposW, voiceButtonRADIUSposH, 0xFF777777);
}
if(channel == EnumVoiceChannelType.GLOBAL) {
drawOutline(voiceButtonGLOBALposX, voiceButtonGLOBALposY, voiceButtonGLOBALposW, voiceButtonGLOBALposH, 0xFFCCCCCC);
drawRect(voiceButtonGLOBALposX + 1, voiceButtonGLOBALposY + 1, voiceButtonGLOBALposX + voiceButtonGLOBALposW - 2,
voiceButtonGLOBALposY + voiceButtonGLOBALposH - 1, 0xFF222222);
}else if(mx >= voiceScreenButtonGLOBALposX && my >= voiceScreenButtonGLOBALposY && mx < voiceScreenButtonGLOBALposX +
voiceScreenButtonGLOBALposW && my < voiceScreenButtonGLOBALposY + voiceScreenButtonGLOBALposH) {
drawOutline(voiceButtonGLOBALposX, voiceButtonGLOBALposY, voiceButtonGLOBALposW, voiceButtonGLOBALposH, 0xFF777777);
}
int enabledColor = (status == EnumVoiceChannelStatus.CONNECTED || channel == EnumVoiceChannelType.NONE) ? 0x66DD66 : 0xDDCC66;
int disabledColor = 0xDD4444;
if(channel != EnumVoiceChannelType.NONE && status == EnumVoiceChannelStatus.UNAVAILABLE) {
enabledColor = disabledColor;
}
drawString(fontRendererObj, OFFstring, 3 - OFFwidth - 8 - RADIUSwidth - 8 - GLOBALwidth, 24, channel == EnumVoiceChannelType.NONE ? enabledColor : disabledColor);
drawString(fontRendererObj, RADIUSstring, 3 - RADIUSwidth - 8 - GLOBALwidth, 24, channel == EnumVoiceChannelType.PROXIMITY ? enabledColor : disabledColor);
drawString(fontRendererObj, GLOBALstring, 3 - GLOBALwidth, 24, channel == EnumVoiceChannelType.GLOBAL ? enabledColor : disabledColor);
GlStateManager.popMatrix();
if(showingCompatWarning) {
drawNotice(I18n.format("voice.unsupportedWarning1"), false, I18n.format("voice.unsupportedWarning2"), I18n.format("voice.unsupportedWarning3"),
"", I18n.format("voice.unsupportedWarning4"), I18n.format("voice.unsupportedWarning5"), I18n.format("voice.unsupportedWarning6"),
I18n.format("voice.unsupportedWarning7"), I18n.format("voice.unsupportedWarning8"), I18n.format("voice.unsupportedWarning9"));
noticeContinueButton.visible = true;
noticeCancelButton.visible = false;
}else if(showingTrackingWarning) {
drawNotice(I18n.format("voice.ipGrabWarning1"), true, I18n.format("voice.ipGrabWarning2"), I18n.format("voice.ipGrabWarning3"),
I18n.format("voice.ipGrabWarning4"), "", I18n.format("voice.ipGrabWarning5"), I18n.format("voice.ipGrabWarning6"),
I18n.format("voice.ipGrabWarning7"), I18n.format("voice.ipGrabWarning8"), I18n.format("voice.ipGrabWarning9"),
I18n.format("voice.ipGrabWarning10"), I18n.format("voice.ipGrabWarning11"), I18n.format("voice.ipGrabWarning12"));
noticeContinueButton.visible = true;
noticeCancelButton.visible = true;
}else {
noticeContinueButton.visible = false;
noticeCancelButton.visible = false;
}
drawButtons(mx, my, partialTicks);
if(showingCompatWarning || showingTrackingWarning) {
throw new AbortedException();
}
}
private void drawNotice(String title, boolean showCancel, String... lines) {
int widthAccum = 0;
for(int i = 0; i < lines.length; ++i) {
int w = fontRendererObj.getStringWidth(lines[i]);
if(widthAccum < w) {
widthAccum = w;
}
}
int margin = 15;
int x = (width - widthAccum) / 2;
int y = (height - lines.length * 10 - 60 - margin) / 2;
drawRect(x - margin - 1, y - margin - 1, x + widthAccum + margin + 1,
y + lines.length * 10 + 49 + margin, 0xFFCCCCCC);
drawRect(x - margin, y - margin, x + widthAccum + margin,
y + lines.length * 10 + 48 + margin, 0xFF111111);
drawCenteredString(fontRendererObj, EnumChatFormatting.BOLD + title, width / 2, y, 0xFF7766);
for(int i = 0; i < lines.length; ++i) {
drawString(fontRendererObj, lines[i], x, y + i * 10 + 18, 0xDDAAAA);
}
if(!showCancel) {
noticeContinueButton.width = 150;
noticeContinueButton.xPosition = (width - 150) / 2;
noticeContinueButton.yPosition = y + lines.length * 10 + 29;
}else {
noticeContinueButton.width = widthAccum / 2 - 10;
noticeContinueButton.xPosition = (width - widthAccum) / 2 + widthAccum / 2 + 3;
noticeContinueButton.yPosition = y + lines.length * 10 + 28;
noticeCancelButton.width = widthAccum / 2 - 10;
noticeCancelButton.xPosition = (width - widthAccum) / 2 + 4;
noticeCancelButton.yPosition = y + lines.length * 10 + 28;
}
}
public static int attenuate(int cin, float f) {
return attenuate(cin, f, f, f, 1.0f);
}
public static int attenuate(int cin, float r, float g, float b, float a) {
float var10 = (float) (cin >> 24 & 255) / 255.0F;
float var6 = (float) (cin >> 16 & 255) / 255.0F;
float var7 = (float) (cin >> 8 & 255) / 255.0F;
float var8 = (float) (cin & 255) / 255.0F;
var10 *= a;
var6 *= r;
var7 *= g;
var8 *= b;
if(var10 > 1.0f) {
var10 = 1.0f;
}
if(var6 > 1.0f) {
var6 = 1.0f;
}
if(var7 > 1.0f) {
var7 = 1.0f;
}
if(var8 > 1.0f) {
var8 = 1.0f;
}
return (((int)(var10 * 255.0f) << 24) | ((int)(var6 * 255.0f) << 16) | ((int)(var7 * 255.0f) << 8) | (int)(var8 * 255.0f));
}
private void drawOutline(int x, int y, int w, int h, int color) {
drawRect(x, y, x + w, y + 1, color);
drawRect(x + w - 1, y + 1, x + w, y + h - 1, color);
drawRect(x, y + h - 1, x + w, y + h, color);
drawRect(x, y + 1, x + 1, y + h - 1, color);
}
public void mouseReleased(int par1, int par2, int par3) {
applyRadiusButton.mouseReleased(par1, par2);
applyVolumeButton.mouseReleased(par1, par2);
noticeContinueButton.mouseReleased(par1, par2);
noticeCancelButton.mouseReleased(par1, par2);
if(showSliderBlocks || showSliderVolume) {
if(showSliderBlocks) {
if(par3 == 0) {
sliderBlocks.mouseReleased(par1, par2);
}
}else if(showSliderVolume) {
if(par3 == 0) {
sliderListenVolume.mouseReleased(par1, par2);
sliderSpeakVolume.mouseReleased(par1, par2);
}
}
throw new AbortedException();
}
}
public void keyTyped(char par1, int par2) {
if(showSliderBlocks || showSliderVolume || showPTTKeyConfig) {
if(showPTTKeyConfig) {
if(par2 == 1) {
showPTTKeyConfig = false;
}else {
mc.gameSettings.voicePTTKey = par2;
showNewPTTKey = 10;
}
}
throw new AbortedException();
}
}
public void mouseClicked(int mx, int my, int button) {
if(showSliderBlocks || showSliderVolume || showPTTKeyConfig || showingCompatWarning || showingTrackingWarning) {
if(showSliderBlocks) {
sliderBlocks.mousePressed(mc, mx, my);
}else if(showSliderVolume) {
sliderListenVolume.mousePressed(mc, mx, my);
sliderSpeakVolume.mousePressed(mc, mx, my);
}
if(button == 0) {
if(applyRadiusButton.mousePressed(mc, mx, my)) actionPerformed(applyRadiusButton);
if(applyVolumeButton.mousePressed(mc, mx, my)) actionPerformed(applyVolumeButton);
if(noticeContinueButton.mousePressed(mc, mx, my)) actionPerformed(noticeContinueButton);
if(noticeCancelButton.mousePressed(mc, mx, my)) actionPerformed(noticeCancelButton);
}
throw new AbortedException();
}
EnumVoiceChannelStatus status = VoiceClientController.getVoiceStatus();
EnumVoiceChannelType channel = VoiceClientController.getVoiceChannel();
if(button == 0) {
if(VoiceClientController.isSupported()) {
if(mx >= voiceScreenButtonOFFposX && my >= voiceScreenButtonOFFposY && mx < voiceScreenButtonOFFposX +
voiceScreenButtonOFFposW && my < voiceScreenButtonOFFposY + voiceScreenButtonOFFposH) {
VoiceClientController.setVoiceChannel(EnumVoiceChannelType.NONE);
this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
}else if(mx >= voiceScreenButtonRADIUSposX && my >= voiceScreenButtonRADIUSposY && mx < voiceScreenButtonRADIUSposX +
voiceScreenButtonRADIUSposW && my < voiceScreenButtonRADIUSposY + voiceScreenButtonRADIUSposH) {
if(showCompatWarning) {
continueChannel = EnumVoiceChannelType.PROXIMITY;
showingCompatWarning = true;
}else if(showTrackingWarning) {
continueChannel = EnumVoiceChannelType.PROXIMITY;
showingTrackingWarning = true;
}else {
VoiceClientController.setVoiceChannel(EnumVoiceChannelType.PROXIMITY);
}
this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
}else if(mx >= voiceScreenButtonGLOBALposX && my >= voiceScreenButtonGLOBALposY && mx < voiceScreenButtonGLOBALposX +
voiceScreenButtonGLOBALposW && my < voiceScreenButtonGLOBALposY + voiceScreenButtonGLOBALposH) {
if(showCompatWarning) {
continueChannel = EnumVoiceChannelType.GLOBAL;
showingCompatWarning = true;
}else if(showTrackingWarning) {
continueChannel = EnumVoiceChannelType.GLOBAL;
showingTrackingWarning = true;
}else {
VoiceClientController.setVoiceChannel(EnumVoiceChannelType.GLOBAL);
}
this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
}else if(channel == EnumVoiceChannelType.PROXIMITY && status == EnumVoiceChannelStatus.CONNECTED && mx >= voiceScreenButtonChangeRadiusposX &&
my >= voiceScreenButtonChangeRadiusposY && mx < voiceScreenButtonChangeRadiusposX + voiceScreenButtonChangeRadiusposW &&
my < voiceScreenButtonChangeRadiusposY + voiceScreenButtonChangeRadiusposH) {
showSliderBlocks = true;
sliderBlocks.sliderValue = (VoiceClientController.getVoiceProximity() - 5) / 17.0f;
this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
}else if(status == EnumVoiceChannelStatus.CONNECTED && channel != EnumVoiceChannelType.NONE && mx >= voiceScreenVolumeIndicatorX &&
my >= voiceScreenVolumeIndicatorY && mx < voiceScreenVolumeIndicatorX + voiceScreenVolumeIndicatorW &&
my < voiceScreenVolumeIndicatorY + voiceScreenVolumeIndicatorH) {
showSliderVolume = true;
sliderListenVolume.sliderValue = VoiceClientController.getVoiceListenVolume();
sliderSpeakVolume.sliderValue = VoiceClientController.getVoiceSpeakVolume();
this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
}else if(status == EnumVoiceChannelStatus.CONNECTED && channel != EnumVoiceChannelType.NONE && mx >= voiceScreenVolumeIndicatorX - 1 &&
my >= voiceScreenVolumeIndicatorY + voiceScreenVolumeIndicatorH + 2 && mx < voiceScreenVolumeIndicatorX + voiceScreenVolumeIndicatorW + 2 &&
my < voiceScreenVolumeIndicatorY + voiceScreenVolumeIndicatorH + 12) {
showPTTKeyConfig = true;
this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
}else if(status == EnumVoiceChannelStatus.CONNECTED) {
List<EaglercraftUUID> playersToRender = VoiceClientController.getVoiceRecent();
if(playersToRender.size() > 0) {
Set<EaglercraftUUID> playersMuted = VoiceClientController.getVoiceMuted();
for(int i = 0, l = playersToRender.size(); i < l; ++i) {
EaglercraftUUID uuid = playersToRender.get(i);
String txt = VoiceClientController.getVoiceUsername(uuid);
boolean muted = playersMuted.contains(uuid);
int mhy = voiceScreenVolumeIndicatorY + voiceScreenVolumeIndicatorH + 33 + i * 9;
if(mx >= voiceScreenVolumeIndicatorX - 3 && my >= mhy && mx < voiceScreenVolumeIndicatorX + voiceScreenVolumeIndicatorW + 2 && my < mhy + 9) {
VoiceClientController.setVoiceMuted(uuid, !muted);
this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
break;
}
}
}
}
}
}
}
private void actionPerformed(GuiButton btn) {
if(btn.id == 2) {
showSliderBlocks = false;
VoiceClientController.setVoiceProximity(mc.gameSettings.voiceListenRadius = (int)((sliderBlocks.sliderValue * 17.0f) + 5.0f));
mc.gameSettings.saveOptions();
}else if(btn.id == 3) {
showSliderVolume = false;
VoiceClientController.setVoiceListenVolume(mc.gameSettings.voiceListenVolume = sliderListenVolume.sliderValue);
VoiceClientController.setVoiceSpeakVolume(mc.gameSettings.voiceSpeakVolume = sliderSpeakVolume.sliderValue);
mc.gameSettings.saveOptions();
}else if(btn.id == 4) {
showPTTKeyConfig = false;
mc.gameSettings.saveOptions();
}else if(btn.id == 5) {
if(showingCompatWarning) {
showingCompatWarning = false;
showCompatWarning = false;
if(showTrackingWarning) {
showingTrackingWarning = true;
}else {
VoiceClientController.setVoiceChannel(continueChannel);
}
}else if(showingTrackingWarning) {
showingTrackingWarning = false;
showTrackingWarning = false;
VoiceClientController.setVoiceChannel(continueChannel);
}
}else if(btn.id == 6) {
if(showingTrackingWarning) {
showingTrackingWarning = false;
VoiceClientController.setVoiceChannel(EnumVoiceChannelType.NONE);
}
}
}
public void updateScreen() {
if(showNewPTTKey > 0) {
--showNewPTTKey;
if(showNewPTTKey == 0) {
showPTTKeyConfig = false;
mc.gameSettings.saveOptions();
}
}
}
public boolean isBlockingInput() {
return showSliderBlocks || showSliderVolume || showPTTKeyConfig || showingCompatWarning || showingTrackingWarning;
}
}

View File

@ -0,0 +1,258 @@
package net.lax1dude.eaglercraft.v1_8.voice;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.GL_GREATER;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.Keyboard;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiChat;
import net.minecraft.client.gui.GuiIngameMenu;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2022-2024 lax1dude, 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 GuiVoiceOverlay extends Gui {
public final Minecraft mc;
public int width;
public int height;
private long pttTimer = 0l;
public GuiVoiceOverlay(Minecraft mc) {
this.mc = mc;
}
public void setResolution(int w, int h) {
this.width = w;
this.height = h;
}
private static final ResourceLocation voiceGuiIcons = new ResourceLocation("eagler:gui/eagler_gui.png");
public void drawOverlay() {
if(mc.theWorld != null && VoiceClientController.getVoiceStatus() == EnumVoiceChannelStatus.CONNECTED && VoiceClientController.getVoiceChannel() != EnumVoiceChannelType.NONE &&
!(mc.currentScreen != null && (mc.currentScreen instanceof GuiIngameMenu))) {
if(mc.currentScreen != null && mc.currentScreen.doesGuiPauseGame()) {
return;
}
GlStateManager.disableLighting();
GlStateManager.disableBlend();
GlStateManager.enableAlpha();
GlStateManager.alphaFunc(GL_GREATER, 0.1F);
GlStateManager.pushMatrix();
if(mc.currentScreen == null || (mc.currentScreen instanceof GuiChat)) {
GlStateManager.translate(width / 2 + 77, height - 56, 0.0f);
if(mc.thePlayer == null || mc.thePlayer.capabilities.isCreativeMode) {
GlStateManager.translate(0.0f, 16.0f, 0.0f);
}
}else {
GlStateManager.translate(width / 2 + 10, 4, 0.0f);
}
GlStateManager.scale(0.75f, 0.75f, 0.75f);
String txxt = "press '" + Keyboard.getKeyName(mc.gameSettings.voicePTTKey) + "'";
drawString(mc.fontRendererObj, txxt, -3 - mc.fontRendererObj.getStringWidth(txxt), 9, 0xDDDDDD);
GlStateManager.scale(0.66f, 0.66f, 0.66f);
mc.getTextureManager().bindTexture(voiceGuiIcons);
if((mc.currentScreen == null || !mc.currentScreen.blockPTTKey()) && Keyboard.isKeyDown(mc.gameSettings.voicePTTKey)) {
long millis = System.currentTimeMillis();
if(pttTimer == 0l) {
pttTimer = millis;
}
GlStateManager.color(0.2f, 0.2f, 0.2f, 1.0f);
drawTexturedModalRect(0, 0, 0, 64, 32, 32);
GlStateManager.translate(-1.5f, -1.5f, 0.0f);
if(millis - pttTimer < 1050l) {
if((millis - pttTimer) % 300l < 150l) {
GlStateManager.color(0.9f, 0.2f, 0.2f, 1.0f);
}else {
GlStateManager.color(0.9f, 0.7f, 0.7f, 1.0f);
}
}else {
GlStateManager.color(0.9f, 0.3f, 0.3f, 1.0f);
}
drawTexturedModalRect(0, 0, 0, 64, 32, 32);
}else {
pttTimer = 0l;
GlStateManager.color(0.2f, 0.2f, 0.2f, 1.0f);
drawTexturedModalRect(0, 0, 0, 32, 32, 32);
GlStateManager.translate(-1.5f, -1.5f, 0.0f);
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
drawTexturedModalRect(0, 0, 0, 32, 32, 32);
GlStateManager.translate(-0.5f, -0.5f, 0.0f);
drawTexturedModalRect(0, 0, 0, 32, 32, 32);
}
GlStateManager.popMatrix();
if(VoiceClientController.getVoiceChannel() == EnumVoiceChannelType.PROXIMITY) {
Set<EaglercraftUUID> listeners = VoiceClientController.getVoiceListening();
if(listeners.size() > 0) {
Set<EaglercraftUUID> speakers = VoiceClientController.getVoiceSpeaking();
Set<EaglercraftUUID> muted = VoiceClientController.getVoiceMuted();
List<EaglercraftUUID> listenerList = new ArrayList();
listenerList.addAll(listeners);
listenerList.removeAll(muted);
while(listenerList.size() > 5) {
boolean flag = false;
for(int i = 0, l = listenerList.size(); i < l; ++i) {
if(!speakers.contains(listenerList.get(i))) {
listenerList.remove(i);
flag = true;
break;
}
}
if(!flag) {
break;
}
}
int more = listenerList.size() - 5;
int ww = width;
int hh = height;
if(mc.currentScreen != null && (mc.currentScreen instanceof GuiChat)) {
hh -= 15;
}
List<String> listenerListStr = new ArrayList(Math.min(5, listenerList.size()));
int left = 50;
for(int i = 0, l = listenerList.size(); i < l && i < 5; ++i) {
String txt = VoiceClientController.getVoiceUsername(listenerList.get(i));
listenerListStr.add(txt);
int j = mc.fontRendererObj.getStringWidth(txt) + 4;
if(j > left) {
left = j;
}
}
if(more > 0) {
GlStateManager.pushMatrix();
GlStateManager.translate(ww - left + 3, hh - 10, left);
GlStateManager.scale(0.75f, 0.75f, 0.75f);
drawString(mc.fontRendererObj, "(" + more + " more)", 0, 0, 0xBBBBBB);
GlStateManager.popMatrix();
hh -= 9;
}
for(int i = 0, l = listenerList.size(); i < l && i < 5; ++i) {
boolean speaking = speakers.contains(listenerList.get(i));
float speakf = speaking ? 1.0f : 0.75f;
drawString(mc.fontRendererObj, listenerListStr.get(i), ww - left, hh - 13 - i * 11, speaking ? 0xEEEEEE : 0xBBBBBB);
mc.getTextureManager().bindTexture(voiceGuiIcons);
GlStateManager.pushMatrix();
GlStateManager.translate(ww - left - 14, hh - 14 - i * 11, 0.0f);
GlStateManager.scale(0.75f, 0.75f, 0.75f);
GlStateManager.color(speakf * 0.2f, speakf * 0.2f, speakf * 0.2f, 1.0f);
drawTexturedModalRect(0, 0, 64, speaking ? 176 : 208, 16, 16);
GlStateManager.translate(0.25f, 0.25f, 0.0f);
drawTexturedModalRect(0, 0, 64, speaking ? 176 : 208, 16, 16);
GlStateManager.translate(-1.25f, -1.25f, 0.0f);
GlStateManager.color(speakf, speakf, speakf, 1.0f);
drawTexturedModalRect(0, 0, 64, speaking ? 176 : 208, 16, 16);
GlStateManager.popMatrix();
}
}
}else if(VoiceClientController.getVoiceChannel() == EnumVoiceChannelType.GLOBAL) {
Set<EaglercraftUUID> speakers = VoiceClientController.getVoiceSpeaking();
Set<EaglercraftUUID> muted = VoiceClientController.getVoiceMuted();
List<EaglercraftUUID> listenerList = new ArrayList();
listenerList.addAll(speakers);
listenerList.removeAll(muted);
int more = listenerList.size() - 5;
int ww = width;
int hh = height;
if(mc.currentScreen != null && (mc.currentScreen instanceof GuiChat)) {
hh -= 15;
}
List<String> listenerListStr = new ArrayList(Math.min(5, listenerList.size()));
int left = 50;
for(int i = 0, l = listenerList.size(); i < l && i < 5; ++i) {
String txt = VoiceClientController.getVoiceUsername(listenerList.get(i));
listenerListStr.add(txt);
int j = mc.fontRendererObj.getStringWidth(txt) + 4;
if(j > left) {
left = j;
}
}
if(more > 0) {
GlStateManager.pushMatrix();
GlStateManager.translate(ww - left + 3, hh - 10, left);
GlStateManager.scale(0.75f, 0.75f, 0.75f);
drawString(mc.fontRendererObj, "(" + more + " more)", 0, 0, 0xBBBBBB);
GlStateManager.popMatrix();
hh -= 9;
}
for(int i = 0, l = listenerList.size(); i < l && i < 5; ++i) {
drawString(mc.fontRendererObj, listenerListStr.get(i), ww - left, hh - 13 - i * 11, 0xEEEEEE);
mc.getTextureManager().bindTexture(voiceGuiIcons);
GlStateManager.pushMatrix();
GlStateManager.translate(ww - left - 14, hh - 14 - i * 11, 0.0f);
GlStateManager.scale(0.75f, 0.75f, 0.75f);
GlStateManager.color(0.2f, 0.2f, 0.2f, 1.0f);
drawTexturedModalRect(0, 0, 64, 176, 16, 16);
GlStateManager.translate(0.25f, 0.25f, 0.0f);
drawTexturedModalRect(0, 0, 64, 176, 16, 16);
GlStateManager.translate(-1.25f, -1.25f, 0.0f);
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
drawTexturedModalRect(0, 0, 64, 176, 16, 16);
GlStateManager.popMatrix();
}
}
}
}
}

View File

@ -0,0 +1,367 @@
package net.lax1dude.eaglercraft.v1_8.voice;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.Keyboard;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformVoiceClient;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.profile.EaglerProfile;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;
/**
* Copyright (c) 2022-2024 lax1dude, 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 VoiceClientController {
public static final String SIGNAL_CHANNEL = "EAG|Voice-1.8";
static final Logger logger = LogManager.getLogger("VoiceClientController");
private static boolean clientSupport = false;
private static boolean serverSupport = false;
private static Consumer<PacketBuffer> packetSendCallback = null;
private static EnumVoiceChannelType voiceChannel = EnumVoiceChannelType.NONE;
private static final HashSet<EaglercraftUUID> nearbyPlayers = new HashSet<>();
private static final ExpiringSet<EaglercraftUUID> recentlyNearbyPlayers = new ExpiringSet<>(5000, uuid -> {
if (!nearbyPlayers.contains(uuid)) {
PlatformVoiceClient.signalDisconnect(uuid, false);
}
});
private static final Map<EaglercraftUUID, String> uuidToNameLookup = new HashMap<>(256);
public static boolean isSupported() {
return isClientSupported() && isServerSupported();
}
private static boolean checked = false;
public static boolean isClientSupported() {
if (!checked) {
checked = true;
clientSupport = EagRuntime.getConfiguration().isAllowVoiceClient() && PlatformVoiceClient.isSupported();
}
return clientSupport;
}
public static boolean isServerSupported() {
return serverSupport;
}
public static void initializeVoiceClient(Consumer<PacketBuffer> signalSendCallbackIn) {
packetSendCallback = signalSendCallbackIn;
uuidToNameLookup.clear();
if (getVoiceChannel() != EnumVoiceChannelType.NONE) sendInitialVoice();
}
public static void handleVoiceSignalPacket(PacketBuffer packetData) {
VoiceSignalPackets.handleVoiceSignal(packetData);
}
static void handleVoiceSignalPacketTypeGlobal(EaglercraftUUID[] voicePlayers, String[] voiceNames) {
uuidToNameLookup.clear();
for (int i = 0; i < voicePlayers.length; i++) {
if(voiceNames != null) {
uuidToNameLookup.put(voicePlayers[i], voiceNames[i]);
}
sendPacketRequestIfNeeded(voicePlayers[i]);
}
}
public static void handleServerDisconnect() {
if(!isClientSupported()) return;
serverSupport = false;
uuidToNameLookup.clear();
for (EaglercraftUUID uuid : nearbyPlayers) {
PlatformVoiceClient.signalDisconnect(uuid, false);
}
for (EaglercraftUUID uuid : recentlyNearbyPlayers) {
PlatformVoiceClient.signalDisconnect(uuid, false);
}
nearbyPlayers.clear();
recentlyNearbyPlayers.clear();
Set<EaglercraftUUID> antiConcurrentModificationUUIDs = new HashSet<>(listeningSet);
for (EaglercraftUUID uuid : antiConcurrentModificationUUIDs) {
PlatformVoiceClient.signalDisconnect(uuid, false);
}
activateVoice(false);
}
static void handleVoiceSignalPacketTypeAllowed(boolean voiceAvailableStat, String[] servs) {
serverSupport = voiceAvailableStat;
PlatformVoiceClient.setICEServers(servs);
if(isSupported()) {
EnumVoiceChannelType ch = getVoiceChannel();
setVoiceChannel(EnumVoiceChannelType.NONE);
setVoiceChannel(ch);
}
}
static void handleVoiceSignalPacketTypeConnect(EaglercraftUUID user, boolean offer) {
PlatformVoiceClient.signalConnect(user, offer);
}
static void handleVoiceSignalPacketTypeConnectAnnounce(EaglercraftUUID user) {
sendPacketRequest(user);
}
static void handleVoiceSignalPacketTypeDisconnect(EaglercraftUUID user) {
PlatformVoiceClient.signalDisconnect(user, true);
}
static void handleVoiceSignalPacketTypeICECandidate(EaglercraftUUID user, String ice) {
PlatformVoiceClient.signalICECandidate(user, ice);
}
static void handleVoiceSignalPacketTypeDescription(EaglercraftUUID user, String desc) {
PlatformVoiceClient.signalDescription(user, desc);
}
public static void tickVoiceClient(Minecraft mc) {
if(!isClientSupported()) return;
recentlyNearbyPlayers.checkForExpirations();
speakingSet.clear();
PlatformVoiceClient.tickVoiceClient();
if (getVoiceChannel() != EnumVoiceChannelType.NONE && (getVoiceStatus() == EnumVoiceChannelStatus.CONNECTING || getVoiceStatus() == EnumVoiceChannelStatus.CONNECTED)) {
activateVoice((mc.currentScreen == null || !mc.currentScreen.blockPTTKey()) && Keyboard.isKeyDown(mc.gameSettings.voicePTTKey));
if (mc.theWorld != null && mc.thePlayer != null) {
HashSet<EaglercraftUUID> seenPlayers = new HashSet<>();
for (EntityPlayer player : mc.theWorld.playerEntities) {
if (player == mc.thePlayer) continue;
if (getVoiceChannel() == EnumVoiceChannelType.PROXIMITY) updateVoicePosition(player.getUniqueID(), player.posX, player.posY + player.getEyeHeight(), player.posZ);
int prox = 22;
// cube
if (Math.abs(mc.thePlayer.posX - player.posX) <= prox && Math.abs(mc.thePlayer.posY - player.posY) <= prox && Math.abs(mc.thePlayer.posZ - player.posZ) <= prox) {
if (!uuidToNameLookup.containsKey(player.getUniqueID())) {
uuidToNameLookup.put(player.getUniqueID(), player.getName());
}
if (addNearbyPlayer(player.getUniqueID())) {
seenPlayers.add(player.getUniqueID());
}
}
}
cleanupNearbyPlayers(seenPlayers);
}
}
}
public static final boolean addNearbyPlayer(EaglercraftUUID uuid) {
recentlyNearbyPlayers.remove(uuid);
if (nearbyPlayers.add(uuid)) {
sendPacketRequestIfNeeded(uuid);
return true;
}
return false;
}
public static final void removeNearbyPlayer(EaglercraftUUID uuid) {
if (nearbyPlayers.remove(uuid)) {
if (getVoiceStatus() == EnumVoiceChannelStatus.DISCONNECTED || getVoiceStatus() == EnumVoiceChannelStatus.UNAVAILABLE) return;
if (voiceChannel == EnumVoiceChannelType.PROXIMITY) recentlyNearbyPlayers.add(uuid);
}
}
public static final void cleanupNearbyPlayers(HashSet<EaglercraftUUID> existingPlayers) {
nearbyPlayers.stream().filter(ud -> !existingPlayers.contains(ud)).collect(Collectors.toSet()).forEach(VoiceClientController::removeNearbyPlayer);
}
public static final void updateVoicePosition(EaglercraftUUID uuid, double x, double y, double z) {
PlatformVoiceClient.updateVoicePosition(uuid, x, y, z);
}
public static void setVoiceChannel(EnumVoiceChannelType channel) {
if (voiceChannel == channel) return;
if (channel != EnumVoiceChannelType.NONE) PlatformVoiceClient.initializeDevices();
PlatformVoiceClient.resetPeerStates();
if (channel == EnumVoiceChannelType.NONE) {
for (EaglercraftUUID uuid : nearbyPlayers) {
PlatformVoiceClient.signalDisconnect(uuid, false);
}
for (EaglercraftUUID uuid : recentlyNearbyPlayers) {
PlatformVoiceClient.signalDisconnect(uuid, false);
}
nearbyPlayers.clear();
recentlyNearbyPlayers.clear();
Set<EaglercraftUUID> antiConcurrentModificationUUIDs = new HashSet<>(listeningSet);
for (EaglercraftUUID uuid : antiConcurrentModificationUUIDs) {
PlatformVoiceClient.signalDisconnect(uuid, false);
}
sendPacketDisconnect(null);
activateVoice(false);
} else if (voiceChannel == EnumVoiceChannelType.PROXIMITY) {
for (EaglercraftUUID uuid : nearbyPlayers) {
PlatformVoiceClient.signalDisconnect(uuid, false);
}
for (EaglercraftUUID uuid : recentlyNearbyPlayers) {
PlatformVoiceClient.signalDisconnect(uuid, false);
}
nearbyPlayers.clear();
recentlyNearbyPlayers.clear();
sendPacketDisconnect(null);
} else if(voiceChannel == EnumVoiceChannelType.GLOBAL) {
Set<EaglercraftUUID> antiConcurrentModificationUUIDs = new HashSet<>(listeningSet);
antiConcurrentModificationUUIDs.removeAll(nearbyPlayers);
antiConcurrentModificationUUIDs.removeAll(recentlyNearbyPlayers);
for (EaglercraftUUID uuid : antiConcurrentModificationUUIDs) {
PlatformVoiceClient.signalDisconnect(uuid, false);
}
sendPacketDisconnect(null);
}
voiceChannel = channel;
if (channel != EnumVoiceChannelType.NONE) {
sendInitialVoice();
}
}
public static void sendInitialVoice() {
sendPacketConnect();
for (EaglercraftUUID uuid : nearbyPlayers) {
sendPacketRequest(uuid);
}
}
public static EnumVoiceChannelType getVoiceChannel() {
return voiceChannel;
}
private static boolean voicePeerErrored() {
return PlatformVoiceClient.getPeerState() == EnumVoiceChannelPeerState.FAILED || PlatformVoiceClient.getPeerStateConnect() == EnumVoiceChannelPeerState.FAILED || PlatformVoiceClient.getPeerStateInitial() == EnumVoiceChannelPeerState.FAILED || PlatformVoiceClient.getPeerStateDesc() == EnumVoiceChannelPeerState.FAILED || PlatformVoiceClient.getPeerStateIce() == EnumVoiceChannelPeerState.FAILED;
}
public static EnumVoiceChannelStatus getVoiceStatus() {
return (!isClientSupported() || !isServerSupported()) ? EnumVoiceChannelStatus.UNAVAILABLE :
(PlatformVoiceClient.getReadyState() != EnumVoiceChannelReadyState.DEVICE_INITIALIZED ?
EnumVoiceChannelStatus.CONNECTING : (voicePeerErrored() ? EnumVoiceChannelStatus.UNAVAILABLE : EnumVoiceChannelStatus.CONNECTED));
}
private static boolean talkStatus = false;
public static void activateVoice(boolean talk) {
if (talkStatus != talk) {
PlatformVoiceClient.activateVoice(talk);
talkStatus = talk;
}
}
private static int proximity = 16;
public static void setVoiceProximity(int prox) {
PlatformVoiceClient.setVoiceProximity(prox);
proximity = prox;
}
public static int getVoiceProximity() {
return proximity;
}
private static float volumeListen = 0.5f;
public static void setVoiceListenVolume(float f) {
PlatformVoiceClient.setVoiceListenVolume(f);
volumeListen = f;
}
public static float getVoiceListenVolume() {
return volumeListen;
}
private static float volumeSpeak = 0.5f;
public static void setVoiceSpeakVolume(float f) {
if (volumeSpeak != f) {
PlatformVoiceClient.setMicVolume(f);
}
volumeSpeak = f;
}
public static float getVoiceSpeakVolume() {
return volumeSpeak;
}
private static final Set<EaglercraftUUID> listeningSet = new HashSet<>();
private static final Set<EaglercraftUUID> speakingSet = new HashSet<>();
private static final Set<EaglercraftUUID> mutedSet = new HashSet<>();
public static Set<EaglercraftUUID> getVoiceListening() {
return listeningSet;
}
public static Set<EaglercraftUUID> getVoiceSpeaking() {
return speakingSet;
}
public static void setVoiceMuted(EaglercraftUUID uuid, boolean mute) {
PlatformVoiceClient.mutePeer(uuid, mute);
if (mute) {
mutedSet.add(uuid);
} else {
mutedSet.remove(uuid);
}
}
public static Set<EaglercraftUUID> getVoiceMuted() {
return mutedSet;
}
public static List<EaglercraftUUID> getVoiceRecent() {
return new ArrayList<>(listeningSet);
}
public static String getVoiceUsername(EaglercraftUUID uuid) {
if(uuid == null) {
return "null";
}
String ret = uuidToNameLookup.get(uuid);
return ret == null ? uuid.toString() : ret;
}
public static void sendPacketICE(EaglercraftUUID peerId, String candidate) {
packetSendCallback.accept(VoiceSignalPackets.makeVoiceSignalPacketICE(peerId, candidate));
}
public static void sendPacketDesc(EaglercraftUUID peerId, String desc) {
packetSendCallback.accept(VoiceSignalPackets.makeVoiceSignalPacketDesc(peerId, desc));
}
public static void sendPacketDisconnect(EaglercraftUUID peerId) {
packetSendCallback.accept(VoiceSignalPackets.makeVoiceSignalPacketDisconnect(peerId));
}
public static void sendPacketConnect() {
packetSendCallback.accept(VoiceSignalPackets.makeVoiceSignalPacketConnect());
}
public static void sendPacketRequest(EaglercraftUUID peerId) {
packetSendCallback.accept(VoiceSignalPackets.makeVoiceSignalPacketRequest(peerId));
}
private static void sendPacketRequestIfNeeded(EaglercraftUUID uuid) {
if (getVoiceStatus() == EnumVoiceChannelStatus.DISCONNECTED || getVoiceStatus() == EnumVoiceChannelStatus.UNAVAILABLE) return;
if(uuid.equals(EaglerProfile.getPlayerUUID())) return;
if (!getVoiceListening().contains(uuid)) sendPacketRequest(uuid);
}
}

View File

@ -0,0 +1,142 @@
package net.lax1dude.eaglercraft.v1_8.voice;
import java.nio.charset.StandardCharsets;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.netty.Unpooled;
import net.minecraft.network.PacketBuffer;
/**
* Copyright (c) 2024 lax1dude, 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 VoiceSignalPackets {
static final int VOICE_SIGNAL_ALLOWED = 0;
static final int VOICE_SIGNAL_REQUEST = 0;
static final int VOICE_SIGNAL_CONNECT = 1;
static final int VOICE_SIGNAL_DISCONNECT = 2;
static final int VOICE_SIGNAL_ICE = 3;
static final int VOICE_SIGNAL_DESC = 4;
static final int VOICE_SIGNAL_GLOBAL = 5;
static void handleVoiceSignal(PacketBuffer streamIn) {
try {
int sig = streamIn.readUnsignedByte();
switch(sig) {
case VOICE_SIGNAL_ALLOWED: {
boolean voiceAvailableStat = streamIn.readUnsignedByte() == 1;
String[] servs = null;
if(voiceAvailableStat) {
servs = new String[streamIn.readVarIntFromBuffer()];
for(int i = 0; i < servs.length; i++) {
servs[i] = streamIn.readStringFromBuffer(1024);
}
}
VoiceClientController.handleVoiceSignalPacketTypeAllowed(voiceAvailableStat, servs);
break;
}
case VOICE_SIGNAL_GLOBAL: {
if (VoiceClientController.getVoiceChannel() != EnumVoiceChannelType.GLOBAL) return;
EaglercraftUUID[] voiceIds = new EaglercraftUUID[streamIn.readVarIntFromBuffer()];
for(int i = 0; i < voiceIds.length; i++) {
voiceIds[i] = streamIn.readUuid();
}
String[] voiceNames = null;
if (streamIn.isReadable()) {
voiceNames = new String[voiceIds.length];
for(int i = 0; i < voiceNames.length; i++) {
voiceNames[i] = streamIn.readStringFromBuffer(16);
}
}
VoiceClientController.handleVoiceSignalPacketTypeGlobal(voiceIds, voiceNames);
break;
}
case VOICE_SIGNAL_CONNECT: {
EaglercraftUUID uuid = streamIn.readUuid();
if (streamIn.isReadable()) {
VoiceClientController.handleVoiceSignalPacketTypeConnect(uuid, streamIn.readBoolean());
} else if (VoiceClientController.getVoiceChannel() != EnumVoiceChannelType.PROXIMITY || VoiceClientController.getVoiceListening().contains(uuid)) {
VoiceClientController.handleVoiceSignalPacketTypeConnectAnnounce(uuid);
}
break;
}
case VOICE_SIGNAL_DISCONNECT: {
VoiceClientController.handleVoiceSignalPacketTypeDisconnect(streamIn.readableBytes() > 0 ? streamIn.readUuid() : null);
break;
}
case VOICE_SIGNAL_ICE: {
VoiceClientController.handleVoiceSignalPacketTypeICECandidate(streamIn.readUuid(), streamIn.readStringFromBuffer(32767));
break;
}
case VOICE_SIGNAL_DESC: {
VoiceClientController.handleVoiceSignalPacketTypeDescription(streamIn.readUuid(), streamIn.readStringFromBuffer(32767));
break;
}
default: {
VoiceClientController.logger.error("Unknown voice signal packet '{}'!", sig);
break;
}
}
}catch(Throwable ex) {
VoiceClientController.logger.error("Failed to handle signal packet!");
VoiceClientController.logger.error(ex);
}
}
static PacketBuffer makeVoiceSignalPacketRequest(EaglercraftUUID user) {
PacketBuffer ret = new PacketBuffer(Unpooled.buffer(17, 17));
ret.writeByte(VOICE_SIGNAL_REQUEST);
ret.writeUuid(user);
return ret;
}
static PacketBuffer makeVoiceSignalPacketICE(EaglercraftUUID user, String icePacket) {
byte[] str = icePacket.getBytes(StandardCharsets.UTF_8);
int estLen = 17 + PacketBuffer.getVarIntSize(str.length) + str.length;
PacketBuffer ret = new PacketBuffer(Unpooled.buffer(estLen, estLen));
ret.writeByte(VOICE_SIGNAL_ICE);
ret.writeUuid(user);
ret.writeByteArray(str);
return ret;
}
static PacketBuffer makeVoiceSignalPacketDesc(EaglercraftUUID user, String descPacket) {
byte[] str = descPacket.getBytes(StandardCharsets.UTF_8);
int estLen = 17 + PacketBuffer.getVarIntSize(str.length) + str.length;
PacketBuffer ret = new PacketBuffer(Unpooled.buffer(estLen, estLen));
ret.writeByte(VOICE_SIGNAL_DESC);
ret.writeUuid(user);
ret.writeByteArray(str);
return ret;
}
static PacketBuffer makeVoiceSignalPacketDisconnect(EaglercraftUUID user) {
if (user == null) {
PacketBuffer ret = new PacketBuffer(Unpooled.buffer(1, 1));
ret.writeByte(VOICE_SIGNAL_DISCONNECT);
return ret;
}
PacketBuffer ret = new PacketBuffer(Unpooled.buffer(17, 17));
ret.writeByte(VOICE_SIGNAL_DISCONNECT);
ret.writeUuid(user);
return ret;
}
public static PacketBuffer makeVoiceSignalPacketConnect() {
PacketBuffer ret = new PacketBuffer(Unpooled.buffer(1, 1));
ret.writeByte(VOICE_SIGNAL_CONNECT);
return ret;
}
}

View File

@ -0,0 +1,118 @@
package net.lax1dude.eaglercraft.v1_8.voice;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import java.util.HashSet;
import java.util.Set;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityOtherPlayerMP;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2022-2024 lax1dude. 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 VoiceTagRenderer {
private static final ResourceLocation voiceGuiIcons = new ResourceLocation("eagler:gui/eagler_gui.png");
private static final Set<EaglercraftUUID> voiceTagsDrawnThisFrame = new HashSet();
public static void renderVoiceNameTag(Minecraft mc, EntityOtherPlayerMP player, int offset) {
EaglercraftUUID uuid = player.getUniqueID();
boolean mute = VoiceClientController.getVoiceMuted().contains(uuid);
if((mute || VoiceClientController.getVoiceSpeaking().contains(uuid)) && voiceTagsDrawnThisFrame.add(uuid)) {
GlStateManager.disableLighting();
GlStateManager.disableTexture2D();
GlStateManager.enableAlpha();
GlStateManager.depthMask(false);
GlStateManager.disableDepth();
GlStateManager.enableBlend();
GlStateManager.pushMatrix();
GlStateManager.translate(-8.0f, -18.0f + offset, 0.0f);
GlStateManager.scale(16.0f, 16.0f, 16.0f);
Tessellator tessellator = Tessellator.getInstance();
WorldRenderer worldrenderer = tessellator.getWorldRenderer();
worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR);
float a = 0.25F;
worldrenderer.pos(-0.02, -0.02, 0.0).color(0.0F, 0.0F, 0.0F, a).endVertex();
worldrenderer.pos(-0.02, 1.02, 0.0).color(0.0F, 0.0F, 0.0F, a).endVertex();
worldrenderer.pos(1.02, 1.02, 0.0).color(0.0F, 0.0F, 0.0F, a).endVertex();
worldrenderer.pos(1.02, -0.02, 0.0).color(0.0F, 0.0F, 0.0F, a).endVertex();
tessellator.draw();
GlStateManager.enableTexture2D();
GlStateManager.enableAlpha();
GlStateManager.alphaFunc(GL_GREATER, 0.02f);
mc.getTextureManager().bindTexture(voiceGuiIcons);
int u = 0;
int v = mute ? 192 : 160;
float var7 = 0.00390625F;
float var8 = 0.00390625F;
if(mute) {
GlStateManager.color(0.9F, 0.3F, 0.3F, 0.125F);
}else {
GlStateManager.color(1.0F, 1.0F, 1.0F, 0.125F);
}
worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX);
worldrenderer.pos(0, 1.0, 0).tex((double) ((float) (u + 0.2f) * var7), (double) ((float) (v + 32 - 0.2f) * var8)).endVertex();
worldrenderer.pos(1.0, 1.0, 0).tex((double) ((float) (u + 32 - 0.2f) * var7), (double) ((float) (v + 32 - 0.2f) * var8)).endVertex();
worldrenderer.pos(1.0, 0, 0).tex((double) ((float) (u + 32 - 0.2f) * var7), (double) ((float) (v + 0.2f) * var8)).endVertex();
worldrenderer.pos(0, 0, 0).tex((double) ((float) (u + 0.2f) * var7), (double) ((float) (v + 0.2f) * var8)).endVertex();
tessellator.draw();
GlStateManager.alphaFunc(GL_GREATER, 0.1f);
GlStateManager.enableDepth();
GlStateManager.depthMask(true);
if(mute) {
GlStateManager.color(0.9F, 0.3F, 0.3F, 1.0F);
}else {
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
}
worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX);
worldrenderer.pos(0, 1.0, 0).tex((double) ((float) (u + 0.2f) * var7), (double) ((float) (v + 32 - 0.2f) * var8)).endVertex();
worldrenderer.pos(1.0, 1.0, 0).tex((double) ((float) (u + 32 - 0.2f) * var7), (double) ((float) (v + 32 - 0.2f) * var8)).endVertex();
worldrenderer.pos(1.0, 0, 0).tex((double) ((float) (u + 32 - 0.2f) * var7), (double) ((float) (v + 0.2f) * var8)).endVertex();
worldrenderer.pos(0, 0, 0).tex((double) ((float) (u + 0.2f) * var7), (double) ((float) (v + 0.2f) * var8)).endVertex();
tessellator.draw();
GlStateManager.enableLighting();
GlStateManager.disableBlend();
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
GlStateManager.popMatrix();
}
}
public static void clearTagsDrawnSet() {
voiceTagsDrawnThisFrame.clear();
}
}

View File

@ -99,7 +99,7 @@ public class BlockRedstoneWire extends Block {
BlockPos posTmp = new BlockPos(0, 0, 0);
Block block = worldIn.getBlockState(blockpos).getBlock();
if (!canConnectTo(worldIn.getBlockState(blockpos), direction) && (block.isBlockNormalCube()
|| !canConnectUpwardsTo(worldIn.getBlockState(blockpos.offsetEvenFaster(EnumFacing.UP, posTmp))))) {
|| !canConnectUpwardsTo(worldIn.getBlockState(blockpos.offsetEvenFaster(EnumFacing.DOWN, posTmp))))) {
Block block1 = worldIn.getBlockState(pos.up()).getBlock();
return !block1.isBlockNormalCube() && block.isBlockNormalCube()
&& canConnectUpwardsTo(worldIn.getBlockState(blockpos.offsetEvenFaster(EnumFacing.UP, posTmp)))
@ -177,11 +177,13 @@ public class BlockRedstoneWire extends Block {
if (worldIn.getBlockState(blockpos).getBlock().isNormalCube()
&& !worldIn.getBlockState(pos1.up()).getBlock().isNormalCube()) {
if (flag && pos1.getY() >= pos2.getY()) {
l = this.getMaxCurrentStrength(worldIn, blockpos.up(), l);
++blockpos.y;
l = this.getMaxCurrentStrength(worldIn, blockpos, l);
}
} else if (!worldIn.getBlockState(blockpos).getBlock().isNormalCube() && flag
&& pos1.getY() <= pos2.getY()) {
l = this.getMaxCurrentStrength(worldIn, blockpos.down(), l);
--blockpos.y;
l = this.getMaxCurrentStrength(worldIn, blockpos, l);
}
}
@ -205,6 +207,7 @@ public class BlockRedstoneWire extends Block {
this.blocksNeedingUpdate.add(pos1);
facings = EnumFacing._VALUES;
for (int m = 0; m < facings.length; ++m) {
this.blocksNeedingUpdate.add(pos1.offset(facings[m]));
}

View File

@ -21,6 +21,8 @@ import com.google.common.collect.Lists;
import net.hoosiertransfer.CullingMod;
import net.hoosiertransfer.Alfheim.ILightUpdatesProcessor;
import net.hoosiertransfer.Config;
import net.lax1dude.eaglercraft.v1_8.Display;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.EaglerXBungeeVersion;
@ -38,6 +40,7 @@ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerFolderResourcePack;
import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerFontRenderer;
import net.lax1dude.eaglercraft.v1_8.opengl.EaglerMeshLoader;
import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.lax1dude.eaglercraft.v1_8.opengl.ImageData;
@ -65,6 +68,8 @@ import net.lax1dude.eaglercraft.v1_8.sp.gui.GuiScreenIntegratedServerBusy;
import net.lax1dude.eaglercraft.v1_8.sp.gui.GuiScreenSingleplayerConnecting;
import net.lax1dude.eaglercraft.v1_8.sp.lan.LANServerController;
import net.lax1dude.eaglercraft.v1_8.update.RelayUpdateChecker;
import net.lax1dude.eaglercraft.v1_8.voice.GuiVoiceOverlay;
import net.lax1dude.eaglercraft.v1_8.voice.VoiceClientController;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.client.audio.MusicTicker;
@ -306,6 +311,12 @@ public class Minecraft implements IThreadListener {
public SkullCommand eagskullCommand;
public GuiVoiceOverlay voiceOverlay;
public float startZoomValue = 18.0f;
public float adjustedZoomValue = 18.0f;
public boolean isZoomKey = false;
public Minecraft(GameConfiguration gameConfig) {
theMinecraft = this;
StringTranslate.initClient();
@ -423,6 +434,7 @@ public class Minecraft implements IThreadListener {
this.mcResourceManager.registerReloadListener(new MetalsLUT());
this.mcResourceManager.registerReloadListener(new EmissiveItems());
this.mcResourceManager.registerReloadListener(new BlockVertexIDs());
this.mcResourceManager.registerReloadListener(new EaglerMeshLoader());
AchievementList.openInventory.setStatStringFormatter(new IStatStringFormat() {
public String formatString(String parString1) {
try {
@ -473,6 +485,9 @@ public class Minecraft implements IThreadListener {
this.checkGLError("Post startup");
this.ingameGUI = new GuiIngame(this);
this.eagskullCommand = new SkullCommand(this);
this.voiceOverlay = new GuiVoiceOverlay(this);
ScaledResolution voiceRes = new ScaledResolution(this);
this.voiceOverlay.setResolution(voiceRes.getScaledWidth(), voiceRes.getScaledHeight());
ServerList.initServerList(this);
EaglerProfile.read();
@ -871,6 +886,7 @@ public class Minecraft implements IThreadListener {
public void updateDisplay() {
this.mcProfiler.startSection("display_update");
Display.setVSync(this.gameSettings.enableVsync);
Display.update();
this.mcProfiler.endSection();
this.checkWindowResize();
@ -1217,12 +1233,14 @@ public class Minecraft implements IThreadListener {
private void resize(int width, int height) {
this.displayWidth = Math.max(1, width);
this.displayHeight = Math.max(1, height);
ScaledResolution scaledresolution = new ScaledResolution(this);
if (this.currentScreen != null) {
ScaledResolution scaledresolution = new ScaledResolution(this);
this.currentScreen.onResize(this, scaledresolution.getScaledWidth(), scaledresolution.getScaledHeight());
}
this.loadingScreen = new LoadingScreenRenderer(this);
this.voiceOverlay.setResolution(scaledresolution.getScaledWidth(), scaledresolution.getScaledHeight());
}
public MusicTicker func_181535_r() {
@ -1262,6 +1280,9 @@ public class Minecraft implements IThreadListener {
this.ingameGUI.updateTick();
}
this.mcProfiler.endStartSection("eaglerVoice");
VoiceClientController.tickVoiceClient(this);
this.mcProfiler.endSection();
this.entityRenderer.getMouseOver(1.0F);
this.mcProfiler.startSection("gameMode");
@ -1349,7 +1370,9 @@ public class Minecraft implements IThreadListener {
if (i1 <= 200L) {
int j = Mouse.getEventDWheel();
if (j != 0) {
if (this.thePlayer.isSpectator()) {
if (this.isZoomKey) {
this.adjustedZoomValue = MathHelper.clamp_float(adjustedZoomValue - j * 4.0f, 5.0f, 32.0f);
} else if (this.thePlayer.isSpectator()) {
j = j < 0 ? -1 : 1;
if (this.ingameGUI.getSpectatorGui().func_175262_a()) {
this.ingameGUI.getSpectatorGui().func_175259_b(-j);
@ -1538,6 +1561,12 @@ public class Minecraft implements IThreadListener {
}
}
boolean zoomKey = this.gameSettings.keyBindZoomCamera.isKeyDown();
if (zoomKey != isZoomKey) {
adjustedZoomValue = startZoomValue;
isZoomKey = zoomKey;
}
boolean flag = this.gameSettings.chatVisibility != EntityPlayer.EnumChatVisibility.HIDDEN;
while (this.gameSettings.keyBindInventory.isPressed()) {
@ -1638,12 +1667,12 @@ public class Minecraft implements IThreadListener {
this.entityRenderer.func_181022_b();
}
if (!this.isGamePaused) {
if (!this.isGamePaused && Config.audioEnabled()) {
this.mcMusicTicker.update();
this.mcSoundHandler.update();
}
if (this.theWorld != null) {
if (this.theWorld != null) {
if (!this.isGamePaused) {
this.theWorld.setAllowedSpawnTypes(this.theWorld.getDifficulty() != EnumDifficulty.PEACEFUL, true);
@ -1663,7 +1692,7 @@ public class Minecraft implements IThreadListener {
}
this.mcProfiler.endStartSection("animateTick");
if (!this.isGamePaused && this.theWorld != null) {
if (!this.isGamePaused && this.theWorld != null && Config.animateTick()) {
this.theWorld.doVoidFogParticles(MathHelper.floor_double(this.thePlayer.posX),
MathHelper.floor_double(this.thePlayer.posY), MathHelper.floor_double(this.thePlayer.posZ));
}
@ -1730,6 +1759,7 @@ public class Minecraft implements IThreadListener {
*/
public void launchIntegratedServer(String folderName, String worldName, WorldSettings worldSettingsIn) {
this.loadWorld((WorldClient) null);
Minecraft.getMinecraft().getRenderManager().setEnableFNAWSkins(this.gameSettings.enableFNAWSkins);
session.reset();
SingleplayerServerController.launchEaglercraftServer(folderName, gameSettings.difficulty.getDifficultyId(),
Math.max(gameSettings.renderDistanceChunks, 2), worldSettingsIn);
@ -2273,4 +2303,12 @@ public class Minecraft implements IThreadListener {
public void clearTitles() {
ingameGUI.displayTitle(null, null, -1, -1, -1);
}
public boolean getEnableFNAWSkins() {
boolean ret = this.gameSettings.enableFNAWSkins;
if (this.thePlayer != null) {
ret &= this.thePlayer.sendQueue.currentFNAWSkinAllowedState;
}
return ret;
}
}

View File

@ -1,6 +1,7 @@
package net.minecraft.client.entity;
import net.lax1dude.eaglercraft.v1_8.mojang.authlib.GameProfile;
import net.lax1dude.eaglercraft.v1_8.profile.SkinModel;
import net.minecraft.client.Minecraft;
import net.minecraft.client.network.NetworkPlayerInfo;
import net.minecraft.client.resources.DefaultPlayerSkin;
@ -35,6 +36,14 @@ import net.minecraft.world.WorldSettings;
public abstract class AbstractClientPlayer extends EntityPlayer {
private NetworkPlayerInfo playerInfo;
public long eaglerHighPolyAnimationTick = System.currentTimeMillis();
public float eaglerHighPolyAnimationFloat1 = 0.0f;
public float eaglerHighPolyAnimationFloat2 = 0.0f;
public float eaglerHighPolyAnimationFloat3 = 0.0f;
public float eaglerHighPolyAnimationFloat4 = 0.0f;
public float eaglerHighPolyAnimationFloat5 = 0.0f;
public float eaglerHighPolyAnimationFloat6 = 0.0f;
public AbstractClientPlayer(World worldIn, GameProfile playerProfile) {
super(worldIn, playerProfile);
}
@ -92,6 +101,11 @@ public abstract class AbstractClientPlayer extends EntityPlayer {
: networkplayerinfo.getSkinType();
}
public SkinModel getEaglerSkinModel() {
NetworkPlayerInfo networkplayerinfo = this.getPlayerInfo();
return networkplayerinfo == null ? SkinModel.STEVE : networkplayerinfo.getEaglerSkinModel();
}
public float getFovModifier() {
float f = 1.0F;
if (this.capabilities.isFlying) {

View File

@ -32,8 +32,8 @@ import net.minecraft.util.ResourceLocation;
*/
public class GuiButton extends Gui {
protected static final ResourceLocation buttonTextures = new ResourceLocation("textures/gui/widgets.png");
protected int width;
protected int height;
public int width;
public int height;
public int xPosition;
public int yPosition;
public String displayString;

Some files were not shown because too many files have changed in this diff Show More