Update #28 - Added capes, voice chat, FNAW skins, and fixes

This commit is contained in:
lax1dude 2024-04-20 16:20:06 -07:00
parent 42c57894f9
commit ba88b52022
171 changed files with 7476 additions and 868 deletions

View File

@ -11,13 +11,15 @@
- 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

View File

@ -58,7 +58,11 @@ If you would like to host your own relay, the JAR file and instructions can be d
## PBR Shaders
EaglercraftX 1.8 includes a deferred physically-based renderer modeled after the GTA V rendering engine with many new improvements and a novel raytracing technique for fast realistic reflections. It can be enabled in the "Shaders" menu in the game's options screen. Shader packs in EaglercraftX are just a component of resource packs, so any custom shaders you install will be in the form of a resource pack. EaglercraftX also comes with a very well optimized built-in PBR shader pack and also a concise built-in PBR material texture pack to give all blocks and items in the game realistic lighting and materials that looks better than most vanilla Minecraft shader packs. The default shader and texture packs were created from scratch by lax1dude, shaders packs made for vanilla Minecraft will not work in EaglercraftX and no shaders in EaglercraftX were taken from vanilla Minecraft shader packs.
EaglercraftX 1.8 includes a deferred physically-based renderer modeled after the GTA V rendering engine with many new improvements and a novel raytracing technique for fast realistic reflections. It can be enabled in the "Shaders" menu in the game's options screen. Shader packs in EaglercraftX are just a component of resource packs, so any custom shaders you install will be in the form of a resource pack. EaglercraftX also comes with a very well optimized built-in PBR shader pack and also a built-in PBR material texture pack to give all blocks and items in the game realistic lighting and materials that looks better than most vanilla Minecraft shader packs. The default shader and texture packs were created from scratch by lax1dude, shaders packs made for vanilla Minecraft will not work in EaglercraftX and no shaders in EaglercraftX were taken from vanilla Minecraft shader packs.
## Voice Chat
EaglercraftX 1.8 includes an integrated voice-chat service that can be used in shared worlds and also on multiplayer servers when it is enabled by the server owner. This feature also uses WebRTC like shared worlds, so be careful that you don't leak your IP address accidentally by using it on a public server. If you own a website and don't want people to use voice chat on it, edit the `eaglercraftXOpts` variable in your index.html and add `allowVoiceClient: false`.
## Making a Server
@ -96,6 +100,14 @@ By setting `online_mode` to `false` in the BungeeCord `config.yml` the authentic
When configuring the EaglercraftXBungee `listeners.yml` file, every listener includes an `http_server` section that can be used to configure the listener to also behave like a regular HTTP server when the websocket address is entered into a browser. If this is disabled people will get the normal "404 Websocket Upgrade Failure" instead when they accidentally type your server address into their browser. `root` defines the path to the folder containing index.html and the other files you want to host, relative to the `plugins/EaglercraftXBungee` folder. This can be useful for hosting the client if the offline download doesn't work for some reason but might slow your BungeeCord server down if lots of people are loading it all the time.
### Enabling Voice Chat
Voice chat is disabled by default in EaglercraftXBungee because it is not recommended for use on public servers. To enable it, add or change `allow_voice: true` to your EaglercraftXBungee `listeners.yml` file. The main difference between Eaglercraft 1.5.2 and EaglercraftX 1.8's voice chat feature is that the "Global" channel now only includes other players on the same server as you instead of every single player connected to the same bungeecord proxy. If you would like to disable voice chat on certain servers, add the names of the servers to the `disable_voice_chat_on_servers` list in the EaglercraftXBungee `settings.yml` file. You may have to add this property to the YML file manually if you've upgraded your server from an older version of EaglercraftXBungee.
### Disabling FNAW Skins
Players are known to complain about the high-poly Five Nights At Winstons character skins making PVP harder because of the belief that they change a player's hitbox. If you would like to disable those skins in your PVP worlds you can either set `disable_fnaw_skins_everywhere: true` in your EaglercraftXBungee `settings.yml` file to disable them for all players on your whole BungeeCord proxy, or you can disable them on specific servers by adding the names of the servers to the `disable_fnaw_skins_on_servers` list also in `settings.yml` like with disabling voice chat.
## Launch Options
The EaglercraftX 1.8 client is configured primarily through a variable called `window.eaglercraftXOpts` that must be set before the client starts up.
@ -140,6 +152,7 @@ The default eaglercraftXOpts values is this:
- `logInvalidCerts:` print update certificates with invalid signatures to console
- `enableSignatureBadge:` show a badge on the title screen indicating if digital signature is valid
- `checkRelaysForUpdates:` proprietary feature used in offline downloads
- `allowVoiceClient:` can be used to disable the voice chat feature
## Developing a Client

View File

@ -1 +1 @@
u27
u28

View File

@ -44,7 +44,7 @@
~ 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))))) {
> CHANGE 2 : 3 @ 2 : 3
@ -74,8 +74,19 @@
~ BlockPos blockpos = pos1.offsetEvenFaster(enumfacing, tmp);
~ boolean flag = blockpos.x != pos2.x || blockpos.z != pos2.z;
> CHANGE 35 : 37 @ 35 : 37
> CHANGE 7 : 9 @ 7 : 8
~ ++blockpos.y;
~ l = this.getMaxCurrentStrength(worldIn, blockpos, l);
> CHANGE 3 : 5 @ 3 : 4
~ --blockpos.y;
~ l = this.getMaxCurrentStrength(worldIn, blockpos, l);
> CHANGE 23 : 26 @ 23 : 25
~ facings = EnumFacing._VALUES;
~ for (int m = 0; m < facings.length; ++m) {
~ this.blocksNeedingUpdate.add(pos1.offset(facings[m]));

View File

@ -20,7 +20,7 @@
> DELETE 1 @ 1 : 4
> CHANGE 1 : 52 @ 1 : 4
> CHANGE 1 : 55 @ 1 : 4
~
~ import net.lax1dude.eaglercraft.v1_8.internal.PlatformInput;
@ -46,6 +46,7 @@
~ 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;
@ -73,6 +74,8 @@
~ 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;
> DELETE 2 @ 2 : 4
@ -165,10 +168,16 @@
+ public int bungeeOutdatedMsgTimer = 0;
+ private boolean isLANOpen = false;
> INSERT 1 : 3 @ 1
> INSERT 1 : 9 @ 1
+ public SkullCommand eagskullCommand;
+
+ public GuiVoiceOverlay voiceOverlay;
+
+ public float startZoomValue = 18.0f;
+ public float adjustedZoomValue = 18.0f;
+ public boolean isZoomKey = false;
+
> CHANGE 2 : 3 @ 2 : 5
@ -248,7 +257,7 @@
~ this.standardGalacticFontRenderer = new EaglerFontRenderer(this.gameSettings,
> INSERT 5 : 11 @ 5
> INSERT 5 : 12 @ 5
+ this.mcResourceManager.registerReloadListener(new ShaderPackInfoReloadListener());
+ this.mcResourceManager.registerReloadListener(PBRTextureMapUtils.blockMaterialConstants);
@ -256,6 +265,7 @@
+ this.mcResourceManager.registerReloadListener(new MetalsLUT());
+ this.mcResourceManager.registerReloadListener(new EmissiveItems());
+ this.mcResourceManager.registerReloadListener(new BlockVertexIDs());
+ this.mcResourceManager.registerReloadListener(new EaglerMeshLoader());
> CHANGE 3 : 4 @ 3 : 4
@ -273,9 +283,12 @@
+ SkinPreviewRenderer.initialize();
> INSERT 2 : 11 @ 2
> INSERT 2 : 14 @ 2
+ 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();
@ -490,7 +503,11 @@
+ Mouse.tickCursorShape();
> DELETE 39 @ 39 : 57
> INSERT 5 : 6 @ 5
+ Display.setVSync(this.gameSettings.enableVsync);
> DELETE 34 @ 34 : 52
> CHANGE 39 : 40 @ 39 : 40
@ -518,11 +535,19 @@
~ Display.toggleFullscreen();
> DELETE 11 @ 11 : 12
> INSERT 5 : 6 @ 5
> DELETE 2 @ 2 : 10
+ ScaledResolution scaledresolution = new ScaledResolution(this);
> INSERT 9 : 28 @ 9
> DELETE 1 @ 1 : 2
> DELETE 4 @ 4 : 6
> CHANGE 1 : 2 @ 1 : 7
~ this.voiceOverlay.setResolution(scaledresolution.getScaledWidth(), scaledresolution.getScaledHeight());
> INSERT 11 : 30 @ 11
+ RateLimitTracker.tick();
+
@ -544,7 +569,13 @@
+ RelayUpdateChecker.runTick();
+
> INSERT 15 : 16 @ 15
> INSERT 5 : 8 @ 5
+ this.mcProfiler.endStartSection("eaglerVoice");
+ VoiceClientController.tickVoiceClient(this);
+
> INSERT 10 : 11 @ 10
+ GlStateManager.viewport(0, 0, displayWidth, displayHeight); // to be safe
@ -573,7 +604,13 @@
~ return Minecraft.this.currentScreen.getClass().getName();
> CHANGE 40 : 42 @ 40 : 41
> CHANGE 25 : 28 @ 25 : 26
~ if (this.isZoomKey) {
~ this.adjustedZoomValue = MathHelper.clamp_float(adjustedZoomValue - j * 4.0f, 5.0f, 32.0f);
~ } else if (this.thePlayer.isSpectator()) {
> CHANGE 14 : 16 @ 14 : 15
~ if ((!this.inGameHasFocus || !Mouse.isActuallyGrabbed()) && Mouse.getEventButtonState()) {
~ this.inGameHasFocus = false;
@ -613,7 +650,16 @@
+ GlStateManager.recompileShaders();
> INSERT 163 : 164 @ 163
> INSERT 71 : 77 @ 71
+ boolean zoomKey = this.gameSettings.keyBindZoomCamera.isKeyDown();
+ if (zoomKey != isZoomKey) {
+ adjustedZoomValue = startZoomValue;
+ isZoomKey = zoomKey;
+ }
+
> INSERT 92 : 93 @ 92
+ this.eagskullCommand.tick();
@ -664,8 +710,9 @@
+ }
+
> CHANGE 6 : 16 @ 6 : 54
> CHANGE 6 : 17 @ 6 : 54
~ Minecraft.getMinecraft().getRenderManager().setEnableFNAWSkins(this.gameSettings.enableFNAWSkins);
~ session.reset();
~ SingleplayerServerController.launchEaglercraftServer(folderName, gameSettings.difficulty.getDifficultyId(),
~ Math.max(gameSettings.renderDistanceChunks, 2), worldSettingsIn);
@ -799,7 +846,7 @@
> DELETE 26 @ 26 : 34
> INSERT 7 : 27 @ 7
> INSERT 7 : 35 @ 7
+
+ public static int getGLMaximumTextureSize() {
@ -821,5 +868,13 @@
+ 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;
+ }
> EOF

View File

@ -5,14 +5,34 @@
# Version: 1.0
# Author: lax1dude
> CHANGE 2 : 3 @ 2 : 4
> CHANGE 2 : 4 @ 2 : 4
~ import net.lax1dude.eaglercraft.v1_8.mojang.authlib.GameProfile;
~ import net.lax1dude.eaglercraft.v1_8.profile.SkinModel;
> DELETE 2 @ 2 : 6
> DELETE 6 @ 6 : 7
> DELETE 44 @ 44 : 62
> INSERT 6 : 14 @ 6
+ 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;
+
> DELETE 38 @ 38 : 56
> INSERT 6 : 11 @ 6
+ public SkinModel getEaglerSkinModel() {
+ NetworkPlayerInfo networkplayerinfo = this.getPlayerInfo();
+ return networkplayerinfo == null ? SkinModel.STEVE : networkplayerinfo.getEaglerSkinModel();
+ }
+
> EOF

View File

@ -13,7 +13,12 @@
> DELETE 3 @ 3 : 6
> INSERT 13 : 14 @ 13
> CHANGE 4 : 6 @ 4 : 6
~ public int width;
~ public int height;
> INSERT 7 : 8 @ 7
+ public float fontScale = 1.0f;

View File

@ -117,4 +117,11 @@
~ for (int i = 0; i < parArrayOfString.length; ++i) {
~ String s = parArrayOfString[i];
> INSERT 24 : 28 @ 24
+
+ public boolean blockPTTKey() {
+ return true;
+ }
> EOF

View File

@ -26,4 +26,11 @@
~ protected void mouseClicked(int parInt1, int parInt2, int parInt3) {
> INSERT 46 : 50 @ 46
+
+ public boolean blockPTTKey() {
+ return commandTextField.isFocused();
+ }
> EOF

View File

@ -7,17 +7,37 @@
> DELETE 2 @ 2 : 5
> CHANGE 15 : 18 @ 15 : 16
> INSERT 7 : 9 @ 7
+ private GuiButton enableFNAWSkinsButton;
+
> CHANGE 8 : 11 @ 8 : 9
~ EnumPlayerModelParts[] parts = EnumPlayerModelParts._VALUES;
~ for (int k = 0; k < parts.length; ++k) {
~ EnumPlayerModelParts enumplayermodelparts = parts[k];
> CHANGE 14 : 15 @ 14 : 15
> CHANGE 10 : 14 @ 10 : 11
~ this.buttonList.add(enableFNAWSkinsButton = new GuiButton(201, this.width / 2 - 100,
~ this.height / 6 + 10 + 24 * (i >> 1), I18n.format("options.skinCustomisation.enableFNAWSkins") + ": "
~ + I18n.format(mc.gameSettings.enableFNAWSkins ? "options.on" : "options.off")));
~ this.buttonList.add(new GuiButton(200, this.width / 2 - 100, this.height / 6 + 40 + 24 * (i >> 1),
> CHANGE 3 : 4 @ 3 : 4
~ protected void actionPerformed(GuiButton parGuiButton) {
> CHANGE 27 : 32 @ 27 : 28
> INSERT 4 : 9 @ 4
+ } else if (parGuiButton.id == 201) {
+ mc.gameSettings.enableFNAWSkins = !mc.gameSettings.enableFNAWSkins;
+ mc.getRenderManager().setEnableFNAWSkins(mc.getEnableFNAWSkins());
+ enableFNAWSkinsButton.displayString = I18n.format("options.skinCustomisation.enableFNAWSkins") + ": "
+ + I18n.format(mc.gameSettings.enableFNAWSkins ? "options.on" : "options.off");
> CHANGE 23 : 28 @ 23 : 24
~ /*
~ * TODO: I changed this to getUnformattedText() from getFormattedText() because

View File

@ -54,7 +54,14 @@
~ this.overlayDebug.renderDebugInfo(scaledresolution);
> INSERT 87 : 90 @ 87
> INSERT 83 : 87 @ 83
+ if (this.mc.currentScreen == null) {
+ this.mc.voiceOverlay.drawOverlay();
+ }
+
> INSERT 4 : 7 @ 4
+ if (this.mc.gameSettings.hudWorld && (mc.currentScreen == null || !(mc.currentScreen instanceof GuiChat))) {
+ j -= 10;

View File

@ -5,8 +5,9 @@
# Version: 1.0
# Author: lax1dude
> CHANGE 2 : 11 @ 2 : 9
> CHANGE 2 : 14 @ 2 : 9
~ import net.lax1dude.eaglercraft.v1_8.EagRuntime;
~ import net.lax1dude.eaglercraft.v1_8.Mouse;
~ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
~ import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController;
@ -15,6 +16,8 @@
~ import net.lax1dude.eaglercraft.v1_8.sp.gui.GuiShareToLan;
~ import net.lax1dude.eaglercraft.v1_8.sp.lan.LANServerController;
~ import net.lax1dude.eaglercraft.v1_8.update.GuiUpdateCheckerOverlay;
~ import net.lax1dude.eaglercraft.v1_8.voice.GuiVoiceMenu;
~ import net.minecraft.client.Minecraft;
~ import net.minecraft.client.audio.PositionedSoundRecord;
> CHANGE 4 : 7 @ 4 : 5
@ -25,16 +28,20 @@
> DELETE 2 @ 2 : 4
> INSERT 1 : 11 @ 1
> INSERT 1 : 15 @ 1
+ private GuiButton lanButton;
+
+ boolean hasSentAutoSave = !SingleplayerServerController.isWorldRunning();
+
+ private GuiUpdateCheckerOverlay updateCheckerOverlay;
+ private GuiVoiceMenu voiceMenu;
+
+ public GuiIngameMenu() {
+ updateCheckerOverlay = new GuiUpdateCheckerOverlay(true, this);
+ if (EagRuntime.getConfiguration().isAllowVoiceClient()) {
+ voiceMenu = new GuiVoiceMenu(this);
+ }
+ }
+
@ -90,8 +97,12 @@
~ }
~ break;
> CHANGE 6 : 9 @ 6 : 7
> CHANGE 6 : 13 @ 6 : 7
~ if (EagRuntime.getConfiguration().isAllowVoiceClient()
~ && (!mc.isSingleplayer() || LANServerController.isHostingLAN())) {
~ voiceMenu.updateScreen();
~ }
~ if (Mouse.isActuallyGrabbed()) {
~ Mouse.setGrabbed(false);
~ }
@ -100,45 +111,76 @@
~ this.drawCenteredString(this.fontRendererObj, I18n.format("menu.game", new Object[0]), this.width / 2, 20,
> INSERT 1 : 35 @ 1
> CHANGE 1 : 55 @ 1 : 2
~
~ this.updateCheckerOverlay.drawScreen(i, j, f);
~
~ if (LANServerController.isLANOpen()) {
~ int offset = this.updateCheckerOverlay.getSharedWorldInfoYOffset();
~ String str = I18n.format("lanServer.pauseMenu0");
~ drawString(fontRendererObj, str, 6, 10 + offset, 0xFFFF55);
~
~ if (mc.gameSettings.hideJoinCode) {
~ GlStateManager.pushMatrix();
~ GlStateManager.translate(7.0f, 25.0f + offset, 0.0f);
~ GlStateManager.scale(0.75f, 0.75f, 0.75f);
~ str = I18n.format("lanServer.showCode");
~ int w = fontRendererObj.getStringWidth(str);
~ boolean hover = i > 4 && i < 8 + w * 3 / 4 && j > 24 + offset && j < 25 + offset + 8;
~ drawString(fontRendererObj, EnumChatFormatting.UNDERLINE + str, 0, 0, hover ? 0xEEEEAA : 0xCCCC55);
~ GlStateManager.popMatrix();
~ } else {
~ int w = fontRendererObj.getStringWidth(str);
~ GlStateManager.pushMatrix();
~ GlStateManager.translate(6 + w + 3, 11 + offset, 0.0f);
~ GlStateManager.scale(0.75f, 0.75f, 0.75f);
~ str = I18n.format("lanServer.hideCode");
~ int w2 = fontRendererObj.getStringWidth(str);
~ boolean hover = i > 6 + w + 2 && i < 6 + w + 3 + w2 * 3 / 4 && j > 11 + offset - 1
~ && j < 11 + offset + 6;
~ drawString(fontRendererObj, EnumChatFormatting.UNDERLINE + str, 0, 0, hover ? 0xEEEEAA : 0xCCCC55);
~ GlStateManager.popMatrix();
~
~ drawString(
~ fontRendererObj, EnumChatFormatting.GRAY + I18n.format("lanServer.pauseMenu1") + " "
~ + EnumChatFormatting.RESET + LANServerController.getCurrentURI(),
~ 6, 25 + offset, 0xFFFFFF);
~ drawString(
~ fontRendererObj, EnumChatFormatting.GRAY + I18n.format("lanServer.pauseMenu2") + " "
~ + EnumChatFormatting.RESET + LANServerController.getCurrentCode(),
~ 6, 35 + offset, 0xFFFFFF);
~ }
~ }
~
~ try {
~ if (EagRuntime.getConfiguration().isAllowVoiceClient()
~ && (!mc.isSingleplayer() || LANServerController.isHostingLAN())) {
~ if (voiceMenu.isBlockingInput()) {
~ super.drawScreen(0, 0, f);
~ } else {
~ super.drawScreen(i, j, f);
~ }
~ voiceMenu.drawScreen(i, j, f);
~ } else {
~ super.drawScreen(i, j, f);
~ }
~ } catch (GuiVoiceMenu.AbortedException ex) {
~ }
> INSERT 1 : 80 @ 1
+
+ this.updateCheckerOverlay.drawScreen(i, j, f);
+
+ if (LANServerController.isLANOpen()) {
+ String str = I18n.format("lanServer.pauseMenu0");
+ drawString(fontRendererObj, str, 6, 32, 0xFFFF55);
+
+ if (mc.gameSettings.hideJoinCode) {
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(7.0f, 47.0f, 0.0f);
+ GlStateManager.scale(0.75f, 0.75f, 0.75f);
+ str = I18n.format("lanServer.showCode");
+ int w = fontRendererObj.getStringWidth(str);
+ boolean hover = i > 6 && i < 8 + w * 3 / 4 && j > 46 && j < 47 + 8;
+ drawString(fontRendererObj, EnumChatFormatting.UNDERLINE + str, 0, 0, hover ? 0xEEEEAA : 0xCCCC55);
+ GlStateManager.popMatrix();
+ } else {
+ int w = fontRendererObj.getStringWidth(str);
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(6 + w + 3, 33, 0.0f);
+ GlStateManager.scale(0.75f, 0.75f, 0.75f);
+ str = I18n.format("lanServer.hideCode");
+ int w2 = fontRendererObj.getStringWidth(str);
+ boolean hover = i > 6 + w + 2 && i < 6 + w + 3 + w2 * 3 / 4 && j > 33 - 1 && j < 33 + 6;
+ drawString(fontRendererObj, EnumChatFormatting.UNDERLINE + str, 0, 0, hover ? 0xEEEEAA : 0xCCCC55);
+ GlStateManager.popMatrix();
+
+ drawString(fontRendererObj, EnumChatFormatting.GRAY + I18n.format("lanServer.pauseMenu1") + " "
+ + EnumChatFormatting.RESET + LANServerController.getCurrentURI(), 6, 47, 0xFFFFFF);
+ drawString(fontRendererObj, EnumChatFormatting.GRAY + I18n.format("lanServer.pauseMenu2") + " "
+ + EnumChatFormatting.RESET + LANServerController.getCurrentCode(), 6, 57, 0xFFFFFF);
+ protected void keyTyped(char par1, int par2) {
+ try {
+ if (EagRuntime.getConfiguration().isAllowVoiceClient()
+ && (!mc.isSingleplayer() || LANServerController.isHostingLAN())) {
+ voiceMenu.keyTyped(par1, par2);
+ }
+ super.keyTyped(par1, par2);
+ } catch (GuiVoiceMenu.AbortedException ex) {
+ }
+
> INSERT 2 : 42 @ 2
+ }
+
+ public void confirmClicked(boolean par1, int par2) {
+ mc.displayGuiScreen(this);
@ -152,11 +194,20 @@
+ }
+
+ protected void mouseClicked(int par1, int par2, int par3) {
+ try {
+ if (EagRuntime.getConfiguration().isAllowVoiceClient()
+ && (!mc.isSingleplayer() || LANServerController.isHostingLAN())) {
+ voiceMenu.mouseClicked(par1, par2, par3);
+ }
+ } catch (GuiVoiceMenu.AbortedException ex) {
+ return;
+ }
+ if (par3 == 0) {
+ int offset = this.updateCheckerOverlay.getSharedWorldInfoYOffset();
+ if (mc.gameSettings.hideJoinCode) {
+ String str = I18n.format("lanServer.showCode");
+ int w = fontRendererObj.getStringWidth(str);
+ if (par1 > 6 && par1 < 8 + w * 3 / 4 && par2 > 46 && par2 < 47 + 8) {
+ if (par1 > 4 && par1 < 8 + w * 3 / 4 && par2 > 24 + offset && par2 < 25 + offset + 8) {
+ mc.gameSettings.hideJoinCode = false;
+ this.mc.getSoundHandler()
+ .playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
@ -167,7 +218,8 @@
+ int w = fontRendererObj.getStringWidth(str);
+ str = I18n.format("lanServer.hideCode");
+ int w2 = fontRendererObj.getStringWidth(str);
+ if (par1 > 6 + w + 2 && par1 < 6 + w + 3 + w2 * 3 / 4 && par2 > 33 - 1 && par2 < 33 + 6) {
+ if (par1 > 6 + w + 2 && par1 < 6 + w + 3 + w2 * 3 / 4 && par2 > 11 + offset - 1
+ && par2 < 11 + offset + 6) {
+ mc.gameSettings.hideJoinCode = true;
+ this.mc.getSoundHandler()
+ .playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
@ -179,5 +231,23 @@
+ this.updateCheckerOverlay.mouseClicked(par1, par2, par3);
+ super.mouseClicked(par1, par2, par3);
+ }
+
+ public void setWorldAndResolution(Minecraft par1Minecraft, int par2, int par3) {
+ super.setWorldAndResolution(par1Minecraft, par2, par3);
+ if (EagRuntime.getConfiguration().isAllowVoiceClient()) {
+ voiceMenu.setResolution(par1Minecraft, par2, par3);
+ }
+ }
+
+ protected void mouseReleased(int par1, int par2, int par3) {
+ try {
+ if (EagRuntime.getConfiguration().isAllowVoiceClient()
+ && (!mc.isSingleplayer() || LANServerController.isHostingLAN())) {
+ voiceMenu.mouseReleased(par1, par2, par3);
+ }
+ super.mouseReleased(par1, par2, par3);
+ } catch (GuiVoiceMenu.AbortedException ex) {
+ }
+ }
> EOF

View File

@ -59,7 +59,11 @@
~ I18n.format("options.debugConsoleButton", new Object[0])));
~ btn.enabled = EagRuntime.getPlatformType() != EnumPlatformType.DESKTOP;
> INSERT 17 : 18 @ 17
> CHANGE 10 : 11 @ 10 : 11
~ return chatcomponenttext.getUnformattedText();
> INSERT 6 : 7 @ 6
+ SingleplayerServerController.setDifficulty(-1);

View File

@ -28,4 +28,11 @@
~ protected void mouseClicked(int parInt1, int parInt2, int parInt3) {
> INSERT 46 : 50 @ 46
+
+ public boolean blockPTTKey() {
+ return nameField.isFocused();
+ }
> EOF

View File

@ -178,11 +178,15 @@
~ private void openWebLink(String parURI) {
~ EagRuntime.openLink(parURI);
> INSERT 34 : 38 @ 34
> INSERT 34 : 42 @ 34
+
+ public boolean shouldHangupIntegratedServer() {
+ return true;
+ }
+
+ public boolean blockPTTKey() {
+ return false;
+ }
> EOF

View File

@ -42,4 +42,11 @@
~ protected void mouseClicked(int parInt1, int parInt2, int parInt3) {
> INSERT 102 : 106 @ 102
+
+ public boolean blockPTTKey() {
+ return this.bookIsUnsigned;
+ }
> EOF

View File

@ -9,11 +9,20 @@
~
> CHANGE 12 : 17 @ 12 : 15
> INSERT 8 : 11 @ 8
~ GameSettings.Options.PARTICLES, GameSettings.Options.FXAA, GameSettings.Options.MIPMAP_LEVELS,
~ GameSettings.Options.BLOCK_ALTERNATIVES, GameSettings.Options.ENTITY_SHADOWS, GameSettings.Options.FOG,
~ GameSettings.Options.FULLSCREEN, GameSettings.Options.HUD_FPS, GameSettings.Options.HUD_COORDS,
+ /**
+ * + An array of all of GameSettings.Options's video options.
+ */
> CHANGE 2 : 10 @ 2 : 7
~ GameSettings.Options.FRAMERATE_LIMIT, GameSettings.Options.EAGLER_VSYNC, GameSettings.Options.ANAGLYPH,
~ GameSettings.Options.VIEW_BOBBING, GameSettings.Options.GUI_SCALE, GameSettings.Options.GAMMA,
~ GameSettings.Options.RENDER_CLOUDS, GameSettings.Options.PARTICLES, GameSettings.Options.FXAA,
~ GameSettings.Options.MIPMAP_LEVELS, GameSettings.Options.BLOCK_ALTERNATIVES,
~ GameSettings.Options.ENTITY_SHADOWS, GameSettings.Options.FOG, GameSettings.Options.FULLSCREEN,
~ GameSettings.Options.FNAW_SKINS, GameSettings.Options.HUD_FPS, GameSettings.Options.HUD_COORDS,
~ GameSettings.Options.HUD_PLAYER, GameSettings.Options.HUD_STATS, GameSettings.Options.HUD_WORLD,
~ GameSettings.Options.HUD_24H, GameSettings.Options.CHUNK_FIX };
@ -30,4 +39,8 @@
~ protected void mouseClicked(int parInt1, int parInt2, int parInt3) {
> INSERT 8 : 9 @ 8
+ this.mc.voiceOverlay.setResolution(j, k);
> EOF

View File

@ -84,4 +84,11 @@
~ protected void actionPerformed(GuiButton parGuiButton) {
> INSERT 139 : 143 @ 139
+
+ public boolean blockPTTKey() {
+ return searchField.isFocused();
+ }
> EOF

View File

@ -22,4 +22,11 @@
~ protected void keyTyped(char parChar1, int parInt1) {
> INSERT 68 : 72 @ 68
+
+ public boolean blockPTTKey() {
+ return true;
+ }
> EOF

View File

@ -13,7 +13,20 @@
~ if (entity != null && entity.isSneaking()) {
> CHANGE 31 : 32 @ 31 : 32
> INSERT 21 : 25 @ 21
+ GlStateManager.matrixMode(5890);
+ GlStateManager.pushMatrix();
+ GlStateManager.scale(2.0f, 1.0f, 1.0f);
+ GlStateManager.matrixMode(5888);
> INSERT 1 : 4 @ 1
+ GlStateManager.matrixMode(5890);
+ GlStateManager.popMatrix();
+ GlStateManager.matrixMode(5888);
> CHANGE 9 : 10 @ 9 : 10
~ if (entity != null && entity.isSneaking()) {

View File

@ -17,7 +17,7 @@
+ import net.minecraft.util.ChatComponentText;
> CHANGE 228 : 239 @ 228 : 229
> CHANGE 228 : 240 @ 228 : 229
~ try {
~ this.netClientHandler.getNetworkManager().processReceivedPackets();
@ -30,6 +30,7 @@
~ .closeChannel(new ChatComponentText("Exception thrown: " + ex.toString()));
~ }
~ this.netClientHandler.getSkinCache().flush();
~ this.netClientHandler.getCapeCache().flush();
> CHANGE 96 : 98 @ 96 : 98

View File

@ -9,7 +9,7 @@
> DELETE 4 @ 4 : 6
> INSERT 1 : 19 @ 1
> INSERT 1 : 22 @ 1
+
+ import net.lax1dude.eaglercraft.v1_8.EagRuntime;
@ -19,12 +19,15 @@
+ import com.google.common.collect.Maps;
+
+ import net.lax1dude.eaglercraft.v1_8.netty.Unpooled;
+ import net.lax1dude.eaglercraft.v1_8.profile.CapePackets;
+ import net.lax1dude.eaglercraft.v1_8.profile.ServerCapeCache;
+ import net.lax1dude.eaglercraft.v1_8.profile.ServerSkinCache;
+ import net.lax1dude.eaglercraft.v1_8.profile.SkinPackets;
+ import net.lax1dude.eaglercraft.v1_8.socket.EaglercraftNetworkManager;
+ import net.lax1dude.eaglercraft.v1_8.sp.lan.LANClientNetworkManager;
+ import net.lax1dude.eaglercraft.v1_8.sp.socket.ClientIntegratedServerNetworkManager;
+ import net.lax1dude.eaglercraft.v1_8.update.UpdateService;
+ import net.lax1dude.eaglercraft.v1_8.voice.VoiceClientController;
+ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
+ import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
+ import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerFolderResourcePack;
@ -64,36 +67,51 @@
~ private final Map<EaglercraftUUID, NetworkPlayerInfo> playerInfoMap = Maps.newHashMap();
> CHANGE 2 : 5 @ 2 : 3
> CHANGE 2 : 7 @ 2 : 3
~ private boolean isIntegratedServer = false;
~ private final EaglercraftRandom avRandomizer = new EaglercraftRandom();
~ private final ServerSkinCache skinCache;
~ private final ServerCapeCache capeCache;
~ public boolean currentFNAWSkinAllowedState = true;
> CHANGE 1 : 2 @ 1 : 2
~ public NetHandlerPlayClient(Minecraft mcIn, GuiScreen parGuiScreen, EaglercraftNetworkManager parNetworkManager,
> INSERT 5 : 8 @ 5
> INSERT 5 : 9 @ 5
+ this.skinCache = new ServerSkinCache(parNetworkManager, mcIn.getTextureManager());
+ this.capeCache = new ServerCapeCache(parNetworkManager, mcIn.getTextureManager());
+ this.isIntegratedServer = (parNetworkManager instanceof ClientIntegratedServerNetworkManager)
+ || (parNetworkManager instanceof LANClientNetworkManager);
> INSERT 4 : 5 @ 4
> INSERT 4 : 6 @ 4
+ this.skinCache.destroy();
+ this.capeCache.destroy();
> INSERT 2 : 6 @ 2
> INSERT 2 : 10 @ 2
+ public ServerSkinCache getSkinCache() {
+ return this.skinCache;
+ }
+
+ public ServerCapeCache getCapeCache() {
+ return this.capeCache;
+ }
+
> DELETE 1 @ 1 : 2
> DELETE 19 @ 19 : 20
> INSERT 16 : 20 @ 16
+ if (VoiceClientController.isClientSupported()) {
+ VoiceClientController.initializeVoiceClient((pkt) -> this.netManager
+ .sendPacket(new C17PacketCustomPayload(VoiceClientController.SIGNAL_CHANNEL, pkt)));
+ }
> DELETE 3 @ 3 : 4
> DELETE 105 @ 105 : 106
@ -129,8 +147,11 @@
> DELETE 22 @ 22 : 23
> CHANGE 8 : 11 @ 8 : 9
> CHANGE 8 : 14 @ 8 : 9
~ VoiceClientController.handleServerDisconnect();
~ Minecraft.getMinecraft().getRenderManager()
~ .setEnableFNAWSkins(this.gameController.gameSettings.enableFNAWSkins);
~ if (this.gameController.theWorld != null) {
~ this.gameController.loadWorld((WorldClient) null);
~ }
@ -241,11 +262,12 @@
~ for (int i = 0, l = lst.size(); i < l; ++i) {
~ S38PacketPlayerListItem.AddPlayerData s38packetplayerlistitem$addplayerdata = lst.get(i);
> CHANGE 1 : 4 @ 1 : 2
> CHANGE 1 : 5 @ 1 : 2
~ EaglercraftUUID uuid = s38packetplayerlistitem$addplayerdata.getProfile().getId();
~ this.playerInfoMap.remove(uuid);
~ this.skinCache.evictSkin(uuid);
~ this.capeCache.evictCape(uuid);
> DELETE 34 @ 34 : 35
@ -335,7 +357,7 @@
> DELETE 11 @ 11 : 13
> INSERT 9 : 28 @ 9
> INSERT 9 : 43 @ 9
+ } else if ("EAG|Skins-1.8".equals(packetIn.getChannelName())) {
+ try {
@ -344,6 +366,13 @@
+ logger.error("Couldn't read EAG|Skins-1.8 packet!");
+ logger.error(e);
+ }
+ } else if ("EAG|Capes-1.8".equals(packetIn.getChannelName())) {
+ try {
+ CapePackets.readPluginMessage(packetIn.getBufferData(), capeCache);
+ } catch (IOException e) {
+ logger.error("Couldn't read EAG|Capes-1.8 packet!");
+ logger.error(e);
+ }
+ } else if ("EAG|UpdateCert-1.8".equals(packetIn.getChannelName())) {
+ if (EagRuntime.getConfiguration().allowUpdateSvc()) {
+ try {
@ -356,8 +385,18 @@
+ logger.error(e);
+ }
+ }
+ } else if (VoiceClientController.SIGNAL_CHANNEL.equals(packetIn.getChannelName())) {
+ if (VoiceClientController.isClientSupported()) {
+ VoiceClientController.handleVoiceSignalPacket(packetIn.getBufferData());
+ }
+ } else if ("EAG|FNAWSEn-1.8".equals(packetIn.getChannelName())) {
+ this.currentFNAWSkinAllowedState = packetIn.getBufferData().readBoolean();
+ Minecraft.getMinecraft().getRenderManager().setEnableFNAWSkins(
+ this.currentFNAWSkinAllowedState && Minecraft.getMinecraft().gameSettings.enableFNAWSkins);
> DELETE 5 @ 5 : 6
> DELETE 1 @ 1 : 2
> DELETE 3 @ 3 : 4
> DELETE 19 @ 19 : 20

View File

@ -5,9 +5,10 @@
# Version: 1.0
# Author: lax1dude
> CHANGE 2 : 3 @ 2 : 6
> CHANGE 2 : 4 @ 2 : 6
~ import net.lax1dude.eaglercraft.v1_8.mojang.authlib.GameProfile;
~ import net.lax1dude.eaglercraft.v1_8.profile.SkinModel;
> DELETE 1 @ 1 : 3
@ -22,13 +23,21 @@
~ return Minecraft.getMinecraft().getNetHandler().getSkinCache().getSkin(this.gameProfile)
~ .getSkinModel().profileSkinType;
> CHANGE 3 : 4 @ 3 : 9
> CHANGE 2 : 5 @ 2 : 6
~ public SkinModel getEaglerSkinModel() {
~ return Minecraft.getMinecraft().getNetHandler().getSkinCache().getSkin(this.gameProfile).getSkinModel();
~ }
> CHANGE 1 : 3 @ 1 : 3
~ public ResourceLocation getLocationSkin() {
~ return Minecraft.getMinecraft().getNetHandler().getSkinCache().getSkin(this.gameProfile).getResourceLocation();
> CHANGE 3 : 4 @ 3 : 8
> CHANGE 3 : 5 @ 3 : 8
~ return null;
~ return Minecraft.getMinecraft().getNetHandler().getCapeCache().getCape(this.gameProfile.getId())
~ .getResourceLocation();
> DELETE 6 @ 6 : 33

View File

@ -16,7 +16,7 @@
~ import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom;
~ import net.lax1dude.eaglercraft.v1_8.HString;
> INSERT 1 : 27 @ 1
> INSERT 1 : 28 @ 1
+
+ import com.google.common.base.Predicate;
@ -43,6 +43,7 @@
+ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.gui.GuiShaderConfig;
+ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture.EmissiveItems;
+ import net.lax1dude.eaglercraft.v1_8.vector.Vector4f;
+ import net.lax1dude.eaglercraft.v1_8.voice.VoiceTagRenderer;
+ import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f;
> CHANGE 10 : 13 @ 10 : 20
@ -84,7 +85,12 @@
+ private GameOverlayFramebuffer overlayFramebuffer;
+ private float eagPartialTicks = 0.0f;
> DELETE 2 @ 2 : 3
> INSERT 1 : 3 @ 1
+ public float currentProjMatrixFOV = 0.0f;
+
> DELETE 1 @ 1 : 2
> CHANGE 9 : 10 @ 9 : 10
@ -136,12 +142,12 @@
> CHANGE 6 : 7 @ 6 : 7
~ f = this.mc.gameSettings.keyBindZoomCamera.isKeyDown() ? 17.0f : this.mc.gameSettings.fovSetting;
~ f = this.mc.isZoomKey ? this.mc.adjustedZoomValue : this.mc.gameSettings.fovSetting;
> CHANGE 169 : 173 @ 169 : 172
~ float farPlane = this.farPlaneDistance * 2.0f * MathHelper.SQRT_2;
~ GlStateManager.gluPerspective(this.getFOVModifier(partialTicks, true),
~ GlStateManager.gluPerspective(currentProjMatrixFOV = this.getFOVModifier(partialTicks, true),
~ (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, farPlane);
~ DeferredStateManager.setGBufferNearFarPlanes(0.05f, farPlane);
@ -253,13 +259,18 @@
~ return HString.format("Scaled: (%d, %d). Absolute: (%d, %d). Scale factor of %d",
> DELETE 15 @ 15 : 17
> INSERT 9 : 11 @ 9
+
+ this.mc.voiceOverlay.drawOverlay();
> DELETE 6 @ 6 : 8
> CHANGE 32 : 33 @ 32 : 33
~ EaglercraftGPU.glLineWidth(1.0F);
> INSERT 25 : 33 @ 25
> INSERT 25 : 35 @ 25
+
+ boolean fxaa = !this.mc.gameSettings.shaders
@ -269,6 +280,8 @@
+ EffectPipelineFXAA.begin(this.mc.displayWidth, this.mc.displayHeight);
+ }
+
+ VoiceTagRenderer.clearTagsDrawnSet();
+
> CHANGE 4 : 5 @ 4 : 5
@ -302,16 +315,17 @@
> DELETE 15 @ 15 : 17
> CHANGE 12 : 14 @ 12 : 14
> CHANGE 12 : 15 @ 12 : 14
~ GlStateManager.gluPerspective(this.getFOVModifier(partialTicks, true),
~ (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, this.farPlaneDistance * 4.0F);
~ float vigg = this.getFOVModifier(partialTicks, true);
~ GlStateManager.gluPerspective(vigg, (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F,
~ this.farPlaneDistance * 4.0F);
> CHANGE 4 : 5 @ 4 : 5
> CHANGE 4 : 5 @ 4 : 6
~ GlStateManager.gluPerspective(this.getFOVModifier(partialTicks, true),
~ GlStateManager.gluPerspective(vigg, (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F,
> INSERT 27 : 28 @ 27
> INSERT 26 : 27 @ 26
+ GlStateManager.disableBlend();

View File

@ -64,8 +64,9 @@
~ private final EaglerTextureAtlasSprite[] destroyBlockIcons = new EaglerTextureAtlasSprite[10];
> CHANGE 11 : 12 @ 11 : 12
> CHANGE 11 : 13 @ 11 : 12
~ private float lastViewProjMatrixFOV = Float.MIN_VALUE;
~ private final ChunkUpdateManager renderDispatcher = new ChunkUpdateManager();
> CHANGE 22 : 24 @ 22 : 24
@ -418,7 +419,16 @@
~ return HString.format("C: %d/%d %sD: %d, %s",
> CHANGE 115 : 118 @ 115 : 117
> CHANGE 53 : 55 @ 53 : 54
~ || (double) viewEntity.rotationYaw != this.lastViewEntityYaw
~ || this.mc.entityRenderer.currentProjMatrixFOV != this.lastViewProjMatrixFOV;
> INSERT 5 : 6 @ 5
+ this.lastViewProjMatrixFOV = this.mc.entityRenderer.currentProjMatrixFOV;
> CHANGE 56 : 59 @ 56 : 58
~ EnumFacing[] facings = EnumFacing._VALUES;
~ for (int i = 0; i < facings.length; ++i) {

View File

@ -5,7 +5,7 @@
# Version: 1.0
# Author: lax1dude
> INSERT 2 : 8 @ 2
> INSERT 2 : 11 @ 2
+ import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerTextureAtlasSprite;
+ import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU;
@ -13,8 +13,15 @@
+ import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer;
+ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager;
+ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.NameTagRenderer;
+ import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelStatus;
+ import net.lax1dude.eaglercraft.v1_8.voice.VoiceClientController;
+ import net.lax1dude.eaglercraft.v1_8.voice.VoiceTagRenderer;
> DELETE 3 @ 3 : 4
> INSERT 2 : 3 @ 2
+ import net.minecraft.client.entity.EntityOtherPlayerMP;
> DELETE 1 @ 1 : 2
> DELETE 1 @ 1 : 2
@ -35,7 +42,13 @@
+ }
+
> CHANGE 28 : 30 @ 28 : 30
> INSERT 26 : 29 @ 26
+ if (entity.width == 0 || entity.height == 0) {
+ return;
+ }
> CHANGE 2 : 4 @ 2 : 4
~ EaglerTextureAtlasSprite textureatlassprite = texturemap.getAtlasSprite("minecraft:blocks/fire_layer_0");
~ EaglerTextureAtlasSprite textureatlassprite1 = texturemap.getAtlasSprite("minecraft:blocks/fire_layer_1");
@ -64,4 +77,14 @@
~ EaglercraftGPU.glNormal3f(0.0F, 1.0F, 0.0F);
> INSERT 31 : 38 @ 31
+
+ if (entityIn instanceof EntityOtherPlayerMP) {
+ if (VoiceClientController.getVoiceStatus() == EnumVoiceChannelStatus.CONNECTED) {
+ VoiceTagRenderer.renderVoiceNameTag(Minecraft.getMinecraft(), (EntityOtherPlayerMP) entityIn, b0);
+ }
+ }
+
> EOF

View File

@ -7,7 +7,7 @@
> DELETE 2 @ 2 : 3
> INSERT 1 : 8 @ 1
> INSERT 1 : 9 @ 1
+
+ import com.google.common.collect.Maps;
@ -16,19 +16,39 @@
+ import net.lax1dude.eaglercraft.v1_8.opengl.OpenGlHelper;
+ import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer;
+ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager;
+ import net.lax1dude.eaglercraft.v1_8.profile.RenderHighPoly;
> DELETE 16 @ 16 : 18
> INSERT 3 : 4 @ 3
+ import net.minecraft.client.Minecraft;
> DELETE 13 @ 13 : 15
> DELETE 2 @ 2 : 3
> DELETE 1 @ 1 : 55
> CHANGE 163 : 165 @ 163 : 164
> INSERT 81 : 82 @ 81
+ private RenderPlayer eaglerRenderer;
> CHANGE 82 : 88 @ 82 : 83
~ this.skinMap.put("slim", new RenderPlayer(this, true, false));
~ this.skinMap.put("zombie", new RenderPlayer(this, false, true));
~ this.eaglerRenderer = new RenderHighPoly(this, this.playerRenderer.getMainModel(),
~ this.playerRenderer.shadowSize);
~ this.skinMap.put("eagler",
~ Minecraft.getMinecraft().gameSettings.enableFNAWSkins ? this.eaglerRenderer : this.playerRenderer);
> CHANGE 11 : 12 @ 11 : 12
> INSERT 2 : 6 @ 2
+ public void setEnableFNAWSkins(boolean en) {
+ this.skinMap.put("eagler", en ? this.eaglerRenderer : this.playerRenderer);
+ }
+
> CHANGE 9 : 10 @ 9 : 10
~ render = this.getEntityClassRenderObject((Class<? extends Entity>) parClass1.getSuperclass());

View File

@ -9,8 +9,9 @@
+ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
> INSERT 2 : 3 @ 2
> INSERT 2 : 4 @ 2
+ import net.minecraft.client.model.ModelBase;
+ import net.minecraft.client.model.ModelBiped;
> CHANGE 1 : 2 @ 1 : 4
@ -36,10 +37,17 @@
> CHANGE 8 : 10 @ 8 : 10
~ public ModelBiped getMainModel() {
~ return (ModelBiped) super.getMainModel();
~ protected RenderPlayer(RenderManager renderManager, ModelBase modelBase, float size) {
~ super(renderManager, modelBase, size);
> CHANGE 16 : 17 @ 16 : 17
> INSERT 2 : 6 @ 2
+ public ModelBiped getMainModel() {
+ return (ModelBiped) super.getMainModel();
+ }
+
> CHANGE 14 : 15 @ 14 : 15
~ ModelBiped modelplayer = this.getMainModel();

View File

@ -41,7 +41,12 @@
~ return this.layerRenderers.add((LayerRenderer<T>) layer);
> DELETE 115 @ 115 : 116
> CHANGE 104 : 106 @ 104 : 105
~ logger.error("Couldn\'t render entity");
~ logger.error(exception);
> DELETE 10 @ 10 : 11
> CHANGE 36 : 42 @ 36 : 37

View File

@ -28,8 +28,8 @@
> CHANGE 13 : 22 @ 13 : 18
~ int glTex;
~ if (resource.cachedPointer != null) {
~ TextureUtil.bindTexture(glTex = ((ITextureObject) resource.cachedPointer).getGlTextureId()); // unsafe, lol
~ if (resource.cachedPointerType == ResourceLocation.CACHED_POINTER_TEXTURE) {
~ TextureUtil.bindTexture(glTex = ((ITextureObject) resource.cachedPointer).getGlTextureId());
~ } else {
~ Object object = (ITextureObject) this.mapTextureObjects.get(resource);
~ if (object == null) {
@ -37,9 +37,10 @@
~ this.loadTexture(resource, (ITextureObject) object);
~ }
> CHANGE 1 : 15 @ 1 : 2
> CHANGE 1 : 16 @ 1 : 2
~ resource.cachedPointer = object;
~ resource.cachedPointerType = ResourceLocation.CACHED_POINTER_TEXTURE;
~ TextureUtil.bindTexture(glTex = ((ITextureObject) object).getGlTextureId());
~ }
~ if (DeferredStateManager.isInDeferredPass()) {
@ -66,15 +67,17 @@
~ return textureObj2.getClass().getName();
> INSERT 5 : 6 @ 5
> INSERT 5 : 7 @ 5
+ textureLocation.cachedPointerType = ResourceLocation.CACHED_POINTER_TEXTURE;
+ textureLocation.cachedPointer = textureObj;
> CHANGE 5 : 10 @ 5 : 6
> CHANGE 5 : 11 @ 5 : 6
~ if (textureLocation.cachedPointer != null) {
~ if (textureLocation.cachedPointerType == ResourceLocation.CACHED_POINTER_TEXTURE) {
~ return (ITextureObject) textureLocation.cachedPointer;
~ } else {
~ textureLocation.cachedPointerType = ResourceLocation.CACHED_POINTER_TEXTURE;
~ return (ITextureObject) (textureLocation.cachedPointer = this.mapTextureObjects.get(textureLocation));
~ }

View File

@ -14,10 +14,12 @@
> DELETE 1 @ 1 : 3
> INSERT 3 : 24 @ 3
> INSERT 3 : 27 @ 3
+
+ import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayManager;
+ import net.lax1dude.eaglercraft.v1_8.voice.VoiceClientController;
+
+ import org.json.JSONArray;
+
+ import com.google.common.collect.ImmutableSet;
@ -33,6 +35,7 @@
+ import net.lax1dude.eaglercraft.v1_8.HString;
+ import net.lax1dude.eaglercraft.v1_8.Keyboard;
+ import net.lax1dude.eaglercraft.v1_8.Mouse;
+ import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformType;
+ import net.lax1dude.eaglercraft.v1_8.internal.KeyboardConstants;
+ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
+ import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
@ -53,9 +56,9 @@
~ public boolean fancyGraphics = false;
~ public int ambientOcclusion = 0;
> DELETE 8 @ 8 : 9
> CHANGE 8 : 9 @ 8 : 11
> DELETE 1 @ 1 : 2
~ public boolean enableVsync = EagRuntime.getPlatformType() != EnumPlatformType.DESKTOP;
> CHANGE 5 : 6 @ 5 : 6
@ -88,7 +91,7 @@
~ public int guiScale = 3;
> INSERT 3 : 16 @ 3
> INSERT 3 : 17 @ 3
+ public boolean hudFps = true;
+ public boolean hudCoords = true;
@ -103,9 +106,15 @@
+ public boolean shadersAODisable = false;
+ public EaglerDeferredConfig deferredShaderConf = new EaglerDeferredConfig();
+ public boolean enableUpdateSvc = true;
+ public boolean enableFNAWSkins = true;
> CHANGE 1 : 2 @ 1 : 2
> CHANGE 1 : 7 @ 1 : 2
~ public int voiceListenRadius = 16;
~ public float voiceListenVolume = 0.5f;
~ public float voiceSpeakVolume = 0.5f;
~ public int voicePTTKey = 47; // V
~
~ public GameSettings(Minecraft mcIn) {
> CHANGE 4 : 6 @ 4 : 7
@ -148,7 +157,7 @@
> DELETE 20 @ 20 : 37
> INSERT 13 : 53 @ 13
> INSERT 13 : 62 @ 13
+ if (parOptions == GameSettings.Options.HUD_FPS) {
+ this.hudFps = !this.hudFps;
@ -190,6 +199,15 @@
+ this.mc.toggleFullscreen();
+ }
+
+ if (parOptions == GameSettings.Options.FNAW_SKINS) {
+ this.enableFNAWSkins = !this.enableFNAWSkins;
+ this.mc.getRenderManager().setEnableFNAWSkins(this.mc.getEnableFNAWSkins());
+ }
+
+ if (parOptions == GameSettings.Options.EAGLER_VSYNC) {
+ this.enableVsync = !this.enableVsync;
+ }
+
> CHANGE 23 : 24 @ 23 : 34
@ -199,7 +217,7 @@
> DELETE 2 @ 2 : 4
> INSERT 8 : 26 @ 8
> INSERT 8 : 30 @ 8
+ case HUD_COORDS:
+ return this.hudCoords;
@ -219,6 +237,10 @@
+ return this.fog;
+ case FULLSCREEN:
+ return this.mc.isFullScreen();
+ case FNAW_SKINS:
+ return this.enableFNAWSkins;
+ case EAGLER_VSYNC:
+ return this.enableVsync;
> CHANGE 43 : 46 @ 43 : 47
@ -318,9 +340,11 @@
~ }
~ }
> DELETE 38 @ 38 : 42
> CHANGE 38 : 39 @ 38 : 43
> DELETE 4 @ 4 : 8
~ if (astring[0].equals("enableVsyncEag")) {
> DELETE 3 @ 3 : 7
> CHANGE 52 : 54 @ 52 : 54
@ -395,7 +419,7 @@
> DELETE 2 @ 2 : 10
> CHANGE 6 : 17 @ 6 : 7
> CHANGE 6 : 31 @ 6 : 7
~ if (astring[0].equals("shaders")) {
~ this.shaders = astring[1].equals("true");
@ -405,7 +429,21 @@
~ this.enableUpdateSvc = astring[1].equals("true");
~ }
~
~ Keyboard.setFunctionKeyModifier(keyBindFunction.getKeyCode());
~ if (astring[0].equals("voiceListenRadius")) {
~ voiceListenRadius = Integer.parseInt(astring[1]);
~ }
~
~ if (astring[0].equals("voiceListenVolume")) {
~ voiceListenVolume = this.parseFloat(astring[1]);
~ }
~
~ if (astring[0].equals("voiceSpeakVolume")) {
~ voiceSpeakVolume = this.parseFloat(astring[1]);
~ }
~
~ if (astring[0].equals("voicePTTKey")) {
~ voicePTTKey = Integer.parseInt(astring[1]);
~ }
~
~ for (SoundCategory soundcategory : SoundCategory._VALUES) {
@ -413,14 +451,31 @@
~ for (EnumPlayerModelParts enumplayermodelparts : EnumPlayerModelParts._VALUES) {
> INSERT 4 : 6 @ 4
> INSERT 4 : 10 @ 4
+
+ if (astring[0].equals("enableFNAWSkins")) {
+ this.enableFNAWSkins = astring[1].equals("true");
+ }
+
+ deferredShaderConf.readOption(astring[0], astring[1]);
> DELETE 6 @ 6 : 7
> CHANGE 6 : 13 @ 6 : 7
> INSERT 11 : 20 @ 11
~
~ Keyboard.setFunctionKeyModifier(keyBindFunction.getKeyCode());
~ VoiceClientController.setVoiceListenVolume(voiceListenVolume);
~ VoiceClientController.setVoiceSpeakVolume(voiceSpeakVolume);
~ VoiceClientController.setVoiceProximity(voiceListenRadius);
~ if (this.mc.getRenderManager() != null)
~ this.mc.getRenderManager().setEnableFNAWSkins(this.enableFNAWSkins);
> CHANGE 1 : 3 @ 1 : 2
~ logger.error("Failed to load options");
~ logger.error(exception);
> INSERT 9 : 18 @ 9
+ byte[] data = writeOptions();
+ if (data != null) {
@ -448,13 +503,13 @@
~ printwriter.println("resourcePacks:" + toJSONArray(this.resourcePacks));
~ printwriter.println("incompatibleResourcePacks:" + toJSONArray(this.field_183018_l));
> DELETE 8 @ 8 : 9
> CHANGE 8 : 9 @ 8 : 11
> DELETE 1 @ 1 : 2
~ printwriter.println("enableVsyncEag:" + this.enableVsync);
> DELETE 13 @ 13 : 24
> INSERT 5 : 16 @ 5
> INSERT 5 : 21 @ 5
+ printwriter.println("hudFps:" + this.hudFps);
+ printwriter.println("hudWorld:" + this.hudWorld);
@ -467,6 +522,11 @@
+ printwriter.println("fxaa:" + this.fxaa);
+ printwriter.println("shaders:" + this.shaders);
+ printwriter.println("enableUpdateSvc:" + this.enableUpdateSvc);
+ printwriter.println("voiceListenRadius:" + this.voiceListenRadius);
+ printwriter.println("voiceListenVolume:" + this.voiceListenVolume);
+ printwriter.println("voiceSpeakVolume:" + this.voiceSpeakVolume);
+ printwriter.println("voicePTTKey:" + this.voicePTTKey);
+ printwriter.println("enableFNAWSkins:" + this.enableFNAWSkins);
> CHANGE 5 : 8 @ 5 : 6
@ -487,9 +547,11 @@
+ return bao.toByteArray();
> INSERT 2 : 3 @ 2
> CHANGE 1 : 4 @ 1 : 2
+ return null;
~ logger.error("Failed to save options");
~ logger.error(exception);
~ return null;
> DELETE 2 @ 2 : 3
@ -521,13 +583,15 @@
~ TOUCHSCREEN("options.touchscreen", false, true), CHAT_SCALE("options.chat.scale", true, false),
~ CHAT_WIDTH("options.chat.width", true, false), CHAT_HEIGHT_FOCUSED("options.chat.height.focused", true, false),
> CHANGE 14 : 20 @ 14 : 15
> CHANGE 14 : 22 @ 14 : 15
~ ENTITY_SHADOWS("options.entityShadows", false, true), HUD_FPS("options.hud.fps", false, true),
~ HUD_COORDS("options.hud.coords", false, true), HUD_STATS("options.hud.stats", false, true),
~ HUD_WORLD("options.hud.world", false, true), HUD_PLAYER("options.hud.player", false, true),
~ HUD_24H("options.hud.24h", false, true), CHUNK_FIX("options.chunkFix", false, true),
~ FOG("options.fog", false, true), FXAA("options.fxaa", false, false),
~ FULLSCREEN("options.fullscreen", false, true), FAST_MATH("options.fastMath", false, false);
~ FULLSCREEN("options.fullscreen", false, true),
~ FNAW_SKINS("options.skinCustomisation.enableFNAWSkins", false, true),
~ EAGLER_VSYNC("options.vsync", false, true);
> EOF

View File

@ -26,9 +26,10 @@
> DELETE 2 @ 2 : 3
> INSERT 16 : 18 @ 16
> INSERT 16 : 19 @ 16
+ import net.lax1dude.eaglercraft.v1_8.sp.server.socket.IntegratedServerPlayerNetworkManager;
+ import net.lax1dude.eaglercraft.v1_8.sp.server.voice.IntegratedVoiceService;
+
> CHANGE 1 : 3 @ 1 : 3
@ -186,12 +187,21 @@
+ s = net.minecraft.util.StringUtils.translateControlCodesAlternate(s);
+ }
> INSERT 5 : 24 @ 5
> INSERT 5 : 33 @ 5
+ } else if ("EAG|Skins-1.8".equals(c17packetcustompayload.getChannelName())) {
+ byte[] r = new byte[c17packetcustompayload.getBufferData().readableBytes()];
+ c17packetcustompayload.getBufferData().readBytes(r);
+ ((EaglerMinecraftServer) serverController).getSkinService().processPacket(r, playerEntity);
+ } else if ("EAG|Capes-1.8".equals(c17packetcustompayload.getChannelName())) {
+ byte[] r = new byte[c17packetcustompayload.getBufferData().readableBytes()];
+ c17packetcustompayload.getBufferData().readBytes(r);
+ ((EaglerMinecraftServer) serverController).getCapeService().processPacket(r, playerEntity);
+ } else if ("EAG|Voice-1.8".equals(c17packetcustompayload.getChannelName())) {
+ IntegratedVoiceService vcs = ((EaglerMinecraftServer) serverController).getVoiceService();
+ if (vcs != null) {
+ vcs.processPacket(c17packetcustompayload.getBufferData(), playerEntity);
+ }
+ } else if ("EAG|MyUpdCert-1.8".equals(c17packetcustompayload.getChannelName())) {
+ if (playerEntity.updateCertificate == null) {
+ PacketBuffer pb = c17packetcustompayload.getBufferData();

View File

@ -13,32 +13,40 @@
~ import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
> INSERT 6 : 7 @ 6
> INSERT 6 : 8 @ 6
+ private byte[] skin;
+ private byte[] cape;
> CHANGE 4 : 5 @ 4 : 5
~ public C00PacketLoginStart(GameProfile profileIn, byte[] skin) {
~ public C00PacketLoginStart(GameProfile profileIn, byte[] skin, byte[] cape) {
> INSERT 1 : 2 @ 1
> INSERT 1 : 3 @ 1
+ this.skin = skin;
+ this.cape = cape;
> CHANGE 3 : 5 @ 3 : 4
> CHANGE 3 : 6 @ 3 : 4
~ this.profile = new GameProfile((EaglercraftUUID) null, parPacketBuffer.readStringFromBuffer(16));
~ this.skin = parPacketBuffer.readByteArray();
~ this.cape = parPacketBuffer.readableBytes() > 0 ? parPacketBuffer.readByteArray() : null;
> INSERT 4 : 5 @ 4
> INSERT 4 : 6 @ 4
+ parPacketBuffer.writeByteArray(this.skin);
+ parPacketBuffer.writeByteArray(this.cape);
> INSERT 9 : 13 @ 9
> INSERT 9 : 17 @ 9
+
+ public byte[] getSkin() {
+ return this.skin;
+ }
+
+ public byte[] getCape() {
+ return this.cape;
+ }
> EOF

View File

@ -26,9 +26,11 @@
+ import net.minecraft.util.ChatComponentText;
> CHANGE 12 : 15 @ 12 : 14
> CHANGE 12 : 17 @ 12 : 14
~ import net.lax1dude.eaglercraft.v1_8.sp.server.EaglerMinecraftServer;
~ import net.lax1dude.eaglercraft.v1_8.sp.server.socket.IntegratedServerPlayerNetworkManager;
~ import net.lax1dude.eaglercraft.v1_8.sp.server.voice.IntegratedVoiceService;
~ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
~ import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
@ -119,7 +121,17 @@
~ this.playerStatFiles.remove(entityplayermp.getName());
> CHANGE 6 : 13 @ 6 : 13
> INSERT 2 : 9 @ 2
+ ((EaglerMinecraftServer) mcServer).getSkinService().unregisterPlayer(uuid);
+ ((EaglerMinecraftServer) mcServer).getCapeService().unregisterPlayer(uuid);
+ IntegratedVoiceService vcs = ((EaglerMinecraftServer) mcServer).getVoiceService();
+ if (vcs != null) {
+ vcs.handlePlayerLoggedOut(playerIn);
+ }
+
> CHANGE 4 : 11 @ 4 : 11
~ public String allowUserToConnect(GameProfile gameprofile) {
~ return this.playerEntityList.size() >= this.maxPlayers && !this.func_183023_f(gameprofile)

View File

@ -22,9 +22,10 @@
> DELETE 2 @ 2 : 3
> INSERT 2 : 4 @ 2
> INSERT 2 : 5 @ 2
+ import net.lax1dude.eaglercraft.v1_8.sp.server.socket.IntegratedServerPlayerNetworkManager;
+ import net.lax1dude.eaglercraft.v1_8.sp.server.voice.IntegratedVoiceService;
+
> CHANGE 1 : 3 @ 1 : 3
@ -42,9 +43,10 @@
~ public final IntegratedServerPlayerNetworkManager networkManager;
> INSERT 3 : 4 @ 3
> INSERT 3 : 5 @ 3
+ private byte[] loginSkinPacket;
+ private byte[] loginCapePacket;
> DELETE 1 @ 1 : 2
@ -53,10 +55,18 @@
~ public NetHandlerLoginServer(MinecraftServer parMinecraftServer,
~ IntegratedServerPlayerNetworkManager parNetworkManager) {
> INSERT 15 : 17 @ 15
> INSERT 15 : 25 @ 15
+ ((EaglerMinecraftServer) field_181025_l.mcServer).getSkinService()
+ .processLoginPacket(this.loginSkinPacket, field_181025_l);
+ if (this.loginCapePacket != null) {
+ ((EaglerMinecraftServer) field_181025_l.mcServer).getCapeService()
+ .processLoginPacket(this.loginCapePacket, field_181025_l);
+ }
+ IntegratedVoiceService svc = ((EaglerMinecraftServer) field_181025_l.mcServer).getVoiceService();
+ if (svc != null) {
+ svc.handlePlayerLoggedIn(entityplayermp);
+ }
> CHANGE 23 : 24 @ 23 : 29
@ -68,22 +78,31 @@
+ this.networkManager.setConnectionState(EnumConnectionState.PLAY);
> CHANGE 6 : 10 @ 6 : 8
> CHANGE 6 : 18 @ 6 : 8
~ entityplayermp = this.server.getConfigurationManager().createPlayerForUser(this.loginGameProfile);
~ this.server.getConfigurationManager().initializeConnectionToPlayer(this.networkManager, entityplayermp);
~ ((EaglerMinecraftServer) entityplayermp.mcServer).getSkinService()
~ .processLoginPacket(this.loginSkinPacket, entityplayermp);
~ if (this.loginCapePacket != null) {
~ ((EaglerMinecraftServer) entityplayermp.mcServer).getCapeService()
~ .processLoginPacket(this.loginCapePacket, entityplayermp);
~ }
~ IntegratedVoiceService svc = ((EaglerMinecraftServer) entityplayermp.mcServer).getVoiceService();
~ if (svc != null) {
~ svc.handlePlayerLoggedIn(entityplayermp);
~ }
> CHANGE 11 : 13 @ 11 : 13
~ ? this.loginGameProfile.toString() + " (channel:" + this.networkManager.playerChannel + ")"
~ : ("channel:" + this.networkManager.playerChannel);
> CHANGE 5 : 8 @ 5 : 14
> CHANGE 5 : 9 @ 5 : 14
~ this.loginGameProfile = this.getOfflineProfile(c00packetloginstart.getProfile());
~ this.loginSkinPacket = c00packetloginstart.getSkin();
~ this.loginCapePacket = c00packetloginstart.getCape();
~ this.currentLoginState = NetHandlerLoginServer.LoginState.READY_TO_ACCEPT;
> DELETE 3 @ 3 : 15

View File

@ -5,9 +5,14 @@
# Version: 1.0
# Author: lax1dude
> INSERT 8 : 10 @ 8
> INSERT 8 : 15 @ 8
+ public Object cachedPointer = null;
+ public int cachedPointerType = 0;
+
+ public static final int CACHED_POINTER_NONE = 0;
+ public static final int CACHED_POINTER_TEXTURE = 1;
+ public static final int CACHED_POINTER_EAGLER_MESH = 2;
+
> EOF

View File

@ -113,13 +113,15 @@
~ for (int j = 0, l = this.loadedEntityList.size(); j < l; ++j) {
~ Entity entity = this.loadedEntityList.get(j);
> CHANGE 102 : 105 @ 102 : 103
> CHANGE 102 : 107 @ 102 : 104
~ EnumFacing[] facings = EnumFacing._VALUES;
~ BlockPos tmp = new BlockPos(0, 0, 0);
~ for (int k = 0; k < facings.length; ++k) {
~ EnumFacing enumfacing = facings[k];
~ int j = this.getRedstonePower(pos.offsetEvenFaster(enumfacing, tmp), enumfacing);
> CHANGE 60 : 61 @ 60 : 61
> CHANGE 59 : 60 @ 59 : 60
~ public EntityPlayer getPlayerEntityByUUID(EaglercraftUUID uuid) {

View File

@ -32,11 +32,31 @@
+ } else {
+ ++EaglerMinecraftServer.counterChunkRead;
> INSERT 54 : 55 @ 54
> CHANGE 32 : 34 @ 32 : 33
~ logger.error("Couldn\'t load chunk");
~ logger.error(exception);
> CHANGE 10 : 12 @ 10 : 11
~ logger.error("Couldn\'t save entities");
~ logger.error(exception);
> INSERT 10 : 11 @ 10
+ ++EaglerMinecraftServer.counterChunkWrite;
> CHANGE 36 : 37 @ 36 : 37
> CHANGE 1 : 3 @ 1 : 2
~ logger.error("Couldn\'t save chunk");
~ logger.error(ioexception);
> CHANGE 1 : 3 @ 1 : 3
~ logger.error("Couldn\'t save chunk; already in use by another instance of Minecraft?");
~ logger.error(minecraftexception);
> CHANGE 31 : 32 @ 31 : 32
~ for (int j = 0, l = arraylist.size(); j < l; ++j) {

View File

@ -10,9 +10,9 @@
~ eaglercraft.recording.unsupported=Recording Unsupported!
~ eaglercraft.recording.stop=Stop Recording
~ eaglercraft.recording.start=Record Screen...
~ eaglercraft.soundCategory.voice=Voice
~ eaglercraft.soundCategory.voice=Recording Voice
> INSERT 1 : 230 @ 1
> INSERT 1 : 238 @ 1
+ 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!
@ -37,6 +37,14 @@
+ 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
+
@ -244,7 +252,7 @@
+ eaglercraft.command.clientStub=This command is client side!
+
> INSERT 163 : 350 @ 163
> INSERT 163 : 404 @ 163
+ eaglercraft.singleplayer.busy.killTask=Cancel Task
+ eaglercraft.singleplayer.busy.cancelWarning=Are you sure?
@ -433,6 +441,60 @@
+ 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.
+
> CHANGE 22 : 23 @ 22 : 23
@ -442,7 +504,11 @@
~ lanServer.start=Start Shared World
> CHANGE 280 : 281 @ 280 : 281
> INSERT 175 : 176 @ 175
+ options.skinCustomisation.enableFNAWSkins=Show FNAW Skins
> CHANGE 105 : 106 @ 105 : 106
~ resourcePack.openFolder=Open resource pack

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
@ -104,35 +106,33 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public byte get() {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
return MemoryUtil.memGetByte(address + position++);
return UnsafeUtils.getMemByte(address + position++);
}
@Override
public ByteBuffer put(byte b) {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutByte(address + position++, b);
UnsafeUtils.setMemByte(address + position++, b);
return this;
}
@Override
public byte get(int index) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetByte(address + index);
return UnsafeUtils.getMemByte(address + index);
}
@Override
public ByteBuffer put(int index, byte b) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutByte(address + index, b);
UnsafeUtils.setMemByte(address + index, b);
return this;
}
@Override
public ByteBuffer get(byte[] dst, int offset, int length) {
if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1);
for(int i = 0; i < length; ++i) {
dst[offset + i] = MemoryUtil.memGetByte(address + position + i);
}
UnsafeMemcpy.memcpy(dst, offset, address + position, length);
position += length;
return this;
}
@ -140,9 +140,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public ByteBuffer get(byte[] dst) {
if(position + dst.length > limit) throw new ArrayIndexOutOfBoundsException(position + dst.length - 1);
for(int i = 0; i < dst.length; ++i) {
dst[position + i] = MemoryUtil.memGetByte(address + position + i);
}
UnsafeMemcpy.memcpy(dst, 0, address + position, dst.length);
position += dst.length;
return this;
}
@ -153,14 +151,14 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
EaglerLWJGLByteBuffer c = (EaglerLWJGLByteBuffer)src;
int l = c.limit - c.position;
if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1);
MemoryUtil.memCopy(c.address + c.position, address + position, l);
UnsafeMemcpy.memcpy(address + position, c.address + c.position, l);
position += l;
c.position += l;
}else {
int l = src.remaining();
if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1);
for(int i = 0; i < l; ++i) {
MemoryUtil.memPutByte(address + position + l, src.get());
UnsafeUtils.setMemByte(address + position + l, src.get());
}
position += l;
}
@ -170,9 +168,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public ByteBuffer put(byte[] src, int offset, int length) {
if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1);
for(int i = 0; i < length; ++i) {
MemoryUtil.memPutByte(address + position + i, src[offset + i]);
}
UnsafeMemcpy.memcpy(address + position, src, offset, length);
position += length;
return this;
}
@ -180,9 +176,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public ByteBuffer put(byte[] src) {
if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1);
for(int i = 0; i < src.length; ++i) {
MemoryUtil.memPutByte(address + position + i, src[i]);
}
UnsafeMemcpy.memcpy(address + position, src, 0, src.length);
position += src.length;
return this;
}
@ -203,7 +197,10 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
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, newLen);
return new EaglerLWJGLByteBuffer(newAlloc, newLen, true);
}
@ -211,7 +208,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public char getChar() {
if(position + 2 > limit) throw new ArrayIndexOutOfBoundsException(position);
char c = (char)MemoryUtil.memGetShort(address + position);
char c = UnsafeUtils.getMemChar(address + position);
position += 2;
return c;
}
@ -219,7 +216,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public ByteBuffer putChar(char value) {
if(position + 2 > limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutShort(address + position, (short)value);
UnsafeUtils.setMemChar(address + position, value);
position += 2;
return this;
}
@ -227,20 +224,20 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public char getChar(int index) {
if(index + 2 > limit) throw new ArrayIndexOutOfBoundsException(index);
return (char)MemoryUtil.memGetShort(address + index);
return UnsafeUtils.getMemChar(address + index);
}
@Override
public ByteBuffer putChar(int index, char value) {
if(index + 2 > limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutShort(address + index, (short)value);
UnsafeUtils.setMemChar(address + index, value);
return this;
}
@Override
public short getShort() {
if(position + 2 > limit) throw new ArrayIndexOutOfBoundsException(position);
short s = MemoryUtil.memGetShort(address + position);
short s = UnsafeUtils.getMemShort(address + position);
position += 2;
return s;
}
@ -248,7 +245,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public ByteBuffer putShort(short value) {
if(position + 2 > limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutShort(address + position, value);
UnsafeUtils.setMemShort(address + position, value);
position += 2;
return this;
}
@ -256,13 +253,13 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public short getShort(int index) {
if(index + 2 > limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetShort(address + index);
return UnsafeUtils.getMemShort(address + index);
}
@Override
public ByteBuffer putShort(int index, short value) {
if(index + 2 > limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutShort(address + index, value);
UnsafeUtils.setMemShort(address + index, value);
return this;
}
@ -274,7 +271,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public int getInt() {
if(position + 4 > limit) throw new ArrayIndexOutOfBoundsException(position);
int i = MemoryUtil.memGetInt(address + position);
int i = UnsafeUtils.getMemInt(address + position);
position += 4;
return i;
}
@ -282,7 +279,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public ByteBuffer putInt(int value) {
if(position + 4 > limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutInt(address + position, value);
UnsafeUtils.setMemInt(address + position, value);
position += 4;
return this;
}
@ -290,13 +287,13 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public int getInt(int index) {
if(index + 4 > limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetInt(address + index);
return UnsafeUtils.getMemInt(address + index);
}
@Override
public ByteBuffer putInt(int index, int value) {
if(index + 4 > limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutInt(address + index, value);
UnsafeUtils.setMemInt(address + index, value);
return this;
}
@ -308,7 +305,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public long getLong() {
if(position + 8 > limit) throw new ArrayIndexOutOfBoundsException(position);
long l = MemoryUtil.memGetLong(address + position);
long l = UnsafeUtils.getMemLong(address + position);
position += 8;
return l;
}
@ -316,7 +313,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public ByteBuffer putLong(long value) {
if(position + 8 > limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutLong(address + position, value);
UnsafeUtils.setMemLong(address + position, value);
position += 8;
return this;
}
@ -324,20 +321,20 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public long getLong(int index) {
if(index + 8 > limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetLong(address + index);
return UnsafeUtils.getMemLong(address + index);
}
@Override
public ByteBuffer putLong(int index, long value) {
if(index + 8 > limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutLong(address + index, value);
UnsafeUtils.setMemLong(address + index, value);
return this;
}
@Override
public float getFloat() {
if(position + 4 > limit) throw new ArrayIndexOutOfBoundsException(position);
float f = MemoryUtil.memGetFloat(address + position);
float f = UnsafeUtils.getMemFloat(address + position);
position += 4;
return f;
}
@ -345,7 +342,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public ByteBuffer putFloat(float value) {
if(position + 4 > limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutFloat(address + position, value);
UnsafeUtils.setMemFloat(address + position, value);
position += 4;
return this;
}
@ -353,13 +350,13 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
@Override
public float getFloat(int index) {
if(index + 4 > limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetFloat(address + index);
return UnsafeUtils.getMemFloat(address + index);
}
@Override
public ByteBuffer putFloat(int index, float value) {
if(index + 4 > limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutFloat(address + index, value);
UnsafeUtils.setMemFloat(address + index, value);
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 EaglerLWJGLFloatBuffer implements FloatBuffer {
@Override
public float get() {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
return MemoryUtil.memGetFloat(address + ((position++) << SHIFT));
return UnsafeUtils.getMemFloat(address + ((position++) << SHIFT));
}
@Override
public FloatBuffer put(float b) {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutFloat(address + ((position++) << SHIFT), b);
UnsafeUtils.setMemFloat(address + ((position++) << SHIFT), b);
return this;
}
@Override
public float get(int index) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetFloat(address + (index << SHIFT));
return UnsafeUtils.getMemFloat(address + (index << SHIFT));
}
@Override
public FloatBuffer put(int index, float b) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
MemoryUtil.memPutFloat(address + (index << SHIFT), b);
UnsafeUtils.setMemFloat(address + (index << SHIFT), b);
return this;
}
@Override
public float getElement(int index) {
if(index >= limit) throw new ArrayIndexOutOfBoundsException(index);
return MemoryUtil.memGetFloat(address + (index << SHIFT));
return UnsafeUtils.getMemFloat(address + (index << SHIFT));
}
@Override
public void putElement(int index, float value) {
if(position >= limit) throw new ArrayIndexOutOfBoundsException(position);
MemoryUtil.memPutFloat(address + ((position++) << SHIFT), value);
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.memGetFloat(address + ((position + i) << SHIFT));
}
UnsafeMemcpy.memcpyAlignDst(dst, offset << SHIFT, address + (position << SHIFT), length);
position += length;
return this;
}
@ -154,9 +154,7 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer {
@Override
public FloatBuffer get(float[] dst) {
if(position + dst.length > limit) throw new ArrayIndexOutOfBoundsException(position + dst.length - 1);
for(int i = 0; i < dst.length; ++i) {
dst[i] = MemoryUtil.memGetFloat(address + ((position + i) << SHIFT));
}
UnsafeMemcpy.memcpyAlignDst(dst, 0, address + (position << SHIFT), dst.length);
position += dst.length;
return this;
}
@ -167,14 +165,14 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer {
EaglerLWJGLFloatBuffer c = (EaglerLWJGLFloatBuffer)src;
int l = c.limit - c.position;
if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1);
MemoryUtil.memCopy(c.address + (c.position << SHIFT), address + (position << SHIFT), l << SHIFT);
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.setMemFloat(address + ((position + l) << SHIFT), src.get());
}
position += l;
}
@ -184,9 +182,7 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer {
@Override
public FloatBuffer put(float[] src, int offset, int length) {
if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1);
for(int i = 0; i < length; ++i) {
MemoryUtil.memPutFloat(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 EaglerLWJGLFloatBuffer implements FloatBuffer {
@Override
public FloatBuffer put(float[] src) {
if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1);
for(int i = 0; i < src.length; ++i) {
MemoryUtil.memPutFloat(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 EaglerLWJGLFloatBuffer implements FloatBuffer {
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);
}

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,9 @@ 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

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

@ -10,7 +10,7 @@ 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 projectForkVersion = "u28";
public static final String projectForkVendor = "lax1dude";
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 = "u28";
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 = true;
public static final String updateBundlePackageName = "net.lax1dude.eaglercraft.v1_8.client";
public static final int updateBundlePackageVersionInt = 27;
public static final int updateBundlePackageVersionInt = 28;
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

@ -23,7 +23,7 @@ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
/**
* Copyright (c) 2022-2023 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
@ -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,18 +488,28 @@ 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);
}
private static void createFramebufferHDR16FTexture(int target, int level, int w, int h, int format, boolean allow32bitFallback, ByteBuffer pixelData) {
private static final void createFramebufferHDR16FTexture(int target, int level, int w, int h, int format, boolean allow32bitFallback, ByteBuffer pixelData) {
if(hasFramebufferHDR16FSupport) {
int internalFormat;
switch(format) {
@ -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

@ -11,7 +11,7 @@ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
/**
* Copyright (c) 2022-2023 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
@ -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

@ -42,9 +42,14 @@ public enum DefaultSkins {
CREEPER(20, "Creeper", new ResourceLocation("eagler:skins/21.creeper.png"), SkinModel.STEVE),
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);
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[24];
public static final DefaultSkins[] defaultSkinsMap = new DefaultSkins[29];
public final int id;
public final String name;

View File

@ -16,7 +16,7 @@ import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved.
* 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
@ -37,7 +37,11 @@ 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;
@ -78,6 +82,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();
@ -114,6 +137,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)) {
@ -123,6 +165,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;
@ -139,6 +190,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();
@ -146,6 +213,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"));
}
@ -169,6 +243,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()) {
@ -193,7 +270,21 @@ 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()) {
presetSkinId = 0;
@ -206,12 +297,26 @@ public class EaglerProfile {
}
}
if(presetCapeId == -1) {
if(customCapeId < 0 || customCapeId >= customCapes.size()) {
presetCapeId = 0;
customCapeId = -1;
}
}else {
customCapeId = -1;
if(presetCapeId < 0 || presetCapeId >= DefaultCapes.defaultCapesMap.length) {
presetCapeId = 0;
}
}
}
public static byte[] write() {
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) {
@ -223,6 +328,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);
@ -253,9 +367,14 @@ 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

@ -20,7 +20,7 @@ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import java.io.IOException;
/**
* Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved.
* 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
@ -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,11 +102,25 @@ 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) {
super.drawScreen(0, 0, partialTicks);
@ -114,6 +128,10 @@ public class GuiScreenEditProfile extends GuiScreen {
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;
skinWidth = 140;
@ -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,113 @@
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 {
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,463 @@
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) {
HighPolySkin highPolySkin = abstractclientplayer.getEaglerSkinModel().highPoly;
if(highPolySkin == null) {
super.doRender(abstractclientplayer, d0, d1, d2, f, f1);
return;
}
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();
}
}
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

@ -3,7 +3,7 @@ package net.lax1dude.eaglercraft.v1_8.profile;
import net.lax1dude.eaglercraft.v1_8.opengl.ImageData;
/**
* Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved.
* 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
@ -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

@ -293,6 +293,19 @@ public class ConnectionHandshake {
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) {
bao.reset();

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;
}
}

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