mirror of
https://github.com/Eaglercraft-Archive/Eaglercraftx-1.8.8-src.git
synced 2025-06-27 18:38:14 -05:00
Update #37 - Touch support without userscript, many other feats
This commit is contained in:
@ -116,6 +116,14 @@ public class Base64 extends BaseNCodec {
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 // 70-7a p-z
|
||||
};
|
||||
|
||||
public static int lookupCharInt(char c) {
|
||||
return c < 123 ? DECODE_TABLE[c] : -1;
|
||||
}
|
||||
|
||||
public static char lookupIntChar(int i) {
|
||||
return (char)STANDARD_ENCODE_TABLE[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Base64 uses 6-bit fields.
|
||||
*/
|
||||
|
@ -0,0 +1,152 @@
|
||||
package net.lax1dude.eaglercraft.v1_8;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.client.CPacketGetOtherClientUUIDV4EAG;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.AbstractClientPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
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 ClientUUIDLoadingCache {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger("ClientUUIDLoadingCache");
|
||||
|
||||
public static final EaglercraftUUID NULL_UUID = new EaglercraftUUID(0l, 0l);
|
||||
public static final EaglercraftUUID PENDING_UUID = new EaglercraftUUID(0x6969696969696969l, 0x6969696969696969l);
|
||||
public static final EaglercraftUUID VANILLA_UUID = new EaglercraftUUID(0x1DCE015CD384374El, 0x85030A4DE95E5736l);
|
||||
|
||||
/**
|
||||
* For client devs, allows you to get EaglercraftVersion.clientBrandUUID of
|
||||
* other players on a server, to detect other players who also use your client.
|
||||
*
|
||||
* Requires EaglerXBungee 1.3.0 or EaglerXVelocity 1.1.0
|
||||
*
|
||||
* @return NULL_UUID if not found, PENDING_UUID if pending,
|
||||
* VANILLA_UUID if vanilla, or the remote player's
|
||||
* client's EaglercraftVersion.clientBrandUUID
|
||||
*/
|
||||
public static EaglercraftUUID getPlayerClientBrandUUID(EntityPlayer player) {
|
||||
EaglercraftUUID ret = null;
|
||||
if(player instanceof AbstractClientPlayer) {
|
||||
ret = ((AbstractClientPlayer)player).clientBrandUUIDCache;
|
||||
if(ret == null) {
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
if(mc != null && mc.thePlayer != null && mc.thePlayer.sendQueue.getEaglerMessageProtocol().ver >= 4) {
|
||||
ret = PENDING_UUID;
|
||||
EaglercraftUUID playerUUID = player.getUniqueID();
|
||||
if(!waitingUUIDs.containsKey(playerUUID) && !evictedUUIDs.containsKey(playerUUID)) {
|
||||
int reqID = ++requestId & 0x3FFF;
|
||||
WaitingLookup newLookup = new WaitingLookup(reqID, playerUUID, EagRuntime.steadyTimeMillis(),
|
||||
(AbstractClientPlayer) player);
|
||||
waitingIDs.put(reqID, newLookup);
|
||||
waitingUUIDs.put(playerUUID, newLookup);
|
||||
mc.thePlayer.sendQueue.sendEaglerMessage(
|
||||
new CPacketGetOtherClientUUIDV4EAG(reqID, newLookup.uuid.msb, newLookup.uuid.lsb));
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if(player instanceof EntityPlayerMP) {
|
||||
ret = ((EntityPlayerMP)player).clientBrandUUID;
|
||||
}
|
||||
if(ret == null) {
|
||||
ret = NULL_UUID;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static final Map<Integer,WaitingLookup> waitingIDs = new HashMap<>();
|
||||
private static final Map<EaglercraftUUID,WaitingLookup> waitingUUIDs = new HashMap<>();
|
||||
private static final Map<EaglercraftUUID,Long> evictedUUIDs = new HashMap<>();
|
||||
|
||||
private static int requestId = 0;
|
||||
private static long lastFlushReq = EagRuntime.steadyTimeMillis();
|
||||
private static long lastFlushEvict = EagRuntime.steadyTimeMillis();
|
||||
|
||||
public static void update() {
|
||||
long timestamp = EagRuntime.steadyTimeMillis();
|
||||
if(timestamp - lastFlushReq > 5000l) {
|
||||
lastFlushReq = timestamp;
|
||||
if(!waitingIDs.isEmpty()) {
|
||||
Iterator<WaitingLookup> itr = waitingIDs.values().iterator();
|
||||
while(itr.hasNext()) {
|
||||
WaitingLookup lookup = itr.next();
|
||||
if(timestamp - lookup.timestamp > 15000l) {
|
||||
itr.remove();
|
||||
waitingUUIDs.remove(lookup.uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(timestamp - lastFlushEvict > 1000l) {
|
||||
lastFlushEvict = timestamp;
|
||||
if(!evictedUUIDs.isEmpty()) {
|
||||
Iterator<Long> evictItr = evictedUUIDs.values().iterator();
|
||||
while(evictItr.hasNext()) {
|
||||
if(timestamp - evictItr.next().longValue() > 3000l) {
|
||||
evictItr.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void flushRequestCache() {
|
||||
waitingIDs.clear();
|
||||
waitingUUIDs.clear();
|
||||
evictedUUIDs.clear();
|
||||
}
|
||||
|
||||
public static void handleResponse(int requestId, EaglercraftUUID clientId) {
|
||||
WaitingLookup lookup = waitingIDs.remove(requestId);
|
||||
if(lookup != null) {
|
||||
lookup.player.clientBrandUUIDCache = clientId;
|
||||
waitingUUIDs.remove(lookup.uuid);
|
||||
}else {
|
||||
logger.warn("Unsolicited client brand UUID lookup response #{} recieved! (Brand UUID: {})", requestId, clientId);
|
||||
}
|
||||
}
|
||||
|
||||
public static void evict(EaglercraftUUID clientId) {
|
||||
evictedUUIDs.put(clientId, Long.valueOf(EagRuntime.steadyTimeMillis()));
|
||||
WaitingLookup lk = waitingUUIDs.remove(clientId);
|
||||
if(lk != null) {
|
||||
waitingIDs.remove(lk.reqID);
|
||||
}
|
||||
}
|
||||
|
||||
private static class WaitingLookup {
|
||||
|
||||
private final int reqID;
|
||||
private final EaglercraftUUID uuid;
|
||||
private final long timestamp;
|
||||
private final AbstractClientPlayer player;
|
||||
|
||||
public WaitingLookup(int reqID, EaglercraftUUID uuid, long timestamp, AbstractClientPlayer player) {
|
||||
this.reqID = reqID;
|
||||
this.uuid = uuid;
|
||||
this.timestamp = timestamp;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -20,6 +20,8 @@ import net.lax1dude.eaglercraft.v1_8.internal.PlatformInput;
|
||||
public class Display {
|
||||
|
||||
private static long lastSwap = 0l;
|
||||
private static long lastDPIUpdate = -250l;
|
||||
private static float cacheDPI = 1.0f;
|
||||
|
||||
public static int getWidth() {
|
||||
return PlatformInput.getWindowWidth();
|
||||
@ -29,6 +31,22 @@ public class Display {
|
||||
return PlatformInput.getWindowHeight();
|
||||
}
|
||||
|
||||
public static int getVisualViewportX() {
|
||||
return PlatformInput.getVisualViewportX();
|
||||
}
|
||||
|
||||
public static int getVisualViewportY() {
|
||||
return PlatformInput.getVisualViewportY();
|
||||
}
|
||||
|
||||
public static int getVisualViewportW() {
|
||||
return PlatformInput.getVisualViewportW();
|
||||
}
|
||||
|
||||
public static int getVisualViewportH() {
|
||||
return PlatformInput.getVisualViewportH();
|
||||
}
|
||||
|
||||
public static boolean isActive() {
|
||||
return PlatformInput.getWindowFocused();
|
||||
}
|
||||
@ -61,24 +79,32 @@ public class Display {
|
||||
boolean limitFPS = limitFramerate > 0 && limitFramerate < 1000;
|
||||
|
||||
if(limitFPS) {
|
||||
long millis = System.currentTimeMillis();
|
||||
long millis = EagRuntime.steadyTimeMillis();
|
||||
long frameMillis = (1000l / limitFramerate) - (millis - lastSwap);
|
||||
if(frameMillis > 0l) {
|
||||
EagUtils.sleep(frameMillis);
|
||||
}
|
||||
}
|
||||
|
||||
lastSwap = System.currentTimeMillis();
|
||||
lastSwap = EagRuntime.steadyTimeMillis();
|
||||
}
|
||||
|
||||
public static boolean contextLost() {
|
||||
return PlatformInput.contextLost();
|
||||
}
|
||||
|
||||
|
||||
public static boolean wasResized() {
|
||||
return PlatformInput.wasResized();
|
||||
}
|
||||
|
||||
public static boolean wasVisualViewportResized() {
|
||||
return PlatformInput.wasVisualViewportResized();
|
||||
}
|
||||
|
||||
public static boolean supportsFullscreen() {
|
||||
return PlatformInput.supportsFullscreen();
|
||||
}
|
||||
|
||||
public static boolean isFullscreen() {
|
||||
return PlatformInput.isFullscreen();
|
||||
}
|
||||
@ -87,4 +113,13 @@ public class Display {
|
||||
PlatformInput.toggleFullscreen();
|
||||
}
|
||||
|
||||
public static float getDPI() {
|
||||
long millis = EagRuntime.steadyTimeMillis();
|
||||
if(millis - lastDPIUpdate > 250l) {
|
||||
lastDPIUpdate = millis;
|
||||
cacheDPI = PlatformInput.getDPI();
|
||||
}
|
||||
return cacheDPI;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,17 +3,16 @@ package net.lax1dude.eaglercraft.v1_8;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.io.InputStreamReader;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.EaglerMissingResourceException;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformANGLE;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformAgent;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformOS;
|
||||
@ -26,6 +25,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU;
|
||||
import net.lax1dude.eaglercraft.v1_8.recording.ScreenRecordingController;
|
||||
import net.lax1dude.eaglercraft.v1_8.update.UpdateService;
|
||||
|
||||
/**
|
||||
@ -70,6 +70,8 @@ public class EagRuntime {
|
||||
UpdateService.initialize();
|
||||
EaglerXBungeeVersion.initialize();
|
||||
EaglercraftGPU.warmUpCache();
|
||||
ScreenRecordingController.initialize();
|
||||
PlatformRuntime.postCreate();
|
||||
}
|
||||
|
||||
public static void destroy() {
|
||||
@ -119,11 +121,23 @@ public class EagRuntime {
|
||||
public static void freeFloatBuffer(FloatBuffer byteBuffer) {
|
||||
PlatformRuntime.freeFloatBuffer(byteBuffer);
|
||||
}
|
||||
|
||||
|
||||
public static boolean getResourceExists(String path) {
|
||||
return PlatformAssets.getResourceExists(path);
|
||||
}
|
||||
|
||||
public static byte[] getResourceBytes(String path) {
|
||||
return PlatformAssets.getResourceBytes(path);
|
||||
}
|
||||
|
||||
|
||||
public static byte[] getRequiredResourceBytes(String path) {
|
||||
byte[] ret = PlatformAssets.getResourceBytes(path);
|
||||
if(ret == null) {
|
||||
throw new EaglerMissingResourceException("Could not load required resource from EPK: " + path);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static InputStream getResourceStream(String path) {
|
||||
byte[] b = PlatformAssets.getResourceBytes(path);
|
||||
if(b != null) {
|
||||
@ -132,24 +146,41 @@ public class EagRuntime {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static InputStream getRequiredResourceStream(String path) {
|
||||
byte[] ret = PlatformAssets.getResourceBytes(path);
|
||||
if(ret == null) {
|
||||
throw new EaglerMissingResourceException("Could not load required resource from EPK: " + path);
|
||||
}
|
||||
return new EaglerInputStream(ret);
|
||||
}
|
||||
|
||||
public static String getResourceString(String path) {
|
||||
byte[] bytes = PlatformAssets.getResourceBytes(path);
|
||||
return bytes != null ? new String(bytes, StandardCharsets.UTF_8) : null;
|
||||
}
|
||||
|
||||
|
||||
public static String getRequiredResourceString(String path) {
|
||||
byte[] ret = PlatformAssets.getResourceBytes(path);
|
||||
if(ret == null) {
|
||||
throw new EaglerMissingResourceException("Could not load required resource from EPK: " + path);
|
||||
}
|
||||
return new String(ret, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public static List<String> getResourceLines(String path) {
|
||||
byte[] bytes = PlatformAssets.getResourceBytes(path);
|
||||
if(bytes != null) {
|
||||
List<String> ret = new ArrayList();
|
||||
List<String> ret = new ArrayList<>();
|
||||
try {
|
||||
BufferedReader rd = new BufferedReader(new StringReader(path));
|
||||
BufferedReader rd = new BufferedReader(new InputStreamReader(new EaglerInputStream(bytes), StandardCharsets.UTF_8));
|
||||
String s;
|
||||
while((s = rd.readLine()) != null) {
|
||||
ret.add(s);
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
// ??
|
||||
return null;
|
||||
}
|
||||
return ret;
|
||||
}else {
|
||||
@ -157,6 +188,14 @@ public class EagRuntime {
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getRequiredResourceLines(String path) {
|
||||
List<String> ret = getResourceLines(path);
|
||||
if(ret == null) {
|
||||
throw new EaglerMissingResourceException("Could not load required resource from EPK: " + path);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void debugPrintStackTraceToSTDERR(Throwable t) {
|
||||
debugPrintStackTraceToSTDERR0("", t);
|
||||
Throwable c = t.getCause();
|
||||
@ -180,7 +219,7 @@ public class EagRuntime {
|
||||
}
|
||||
|
||||
public static String[] getStackTraceElements(Throwable t) {
|
||||
List<String> lst = new ArrayList();
|
||||
List<String> lst = new ArrayList<>();
|
||||
PlatformRuntime.getStackTrace(t, (s) -> {
|
||||
lst.add(s);
|
||||
});
|
||||
@ -222,17 +261,23 @@ public class EagRuntime {
|
||||
PlatformRuntime.exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Note to skids: This doesn't do anything in javascript runtime!
|
||||
*/
|
||||
public static long maxMemory() {
|
||||
return PlatformRuntime.maxMemory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Note to skids: This doesn't do anything in TeaVM runtime!
|
||||
* Note to skids: This doesn't do anything in javascript runtime!
|
||||
*/
|
||||
public static long totalMemory() {
|
||||
return PlatformRuntime.totalMemory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Note to skids: This doesn't do anything in javascript runtime!
|
||||
*/
|
||||
public static long freeMemory() {
|
||||
return PlatformRuntime.freeMemory();
|
||||
}
|
||||
@ -289,18 +334,6 @@ public class EagRuntime {
|
||||
return PlatformRuntime.getClientConfigAdapter();
|
||||
}
|
||||
|
||||
public static String getRecText() {
|
||||
return PlatformRuntime.getRecText();
|
||||
}
|
||||
|
||||
public static void toggleRec() {
|
||||
PlatformRuntime.toggleRec();
|
||||
}
|
||||
|
||||
public static boolean recSupported() {
|
||||
return PlatformRuntime.recSupported();
|
||||
}
|
||||
|
||||
public static void openCreditsPopup(String text) {
|
||||
PlatformApplication.openCreditsPopup(text);
|
||||
}
|
||||
@ -317,16 +350,24 @@ public class EagRuntime {
|
||||
PlatformApplication.showDebugConsole();
|
||||
}
|
||||
|
||||
public static Calendar getLocaleCalendar() {
|
||||
return Calendar.getInstance(); //TODO: fix teavm calendar's time zone offset
|
||||
}
|
||||
|
||||
public static <T extends DateFormat> T fixDateFormat(T input) {
|
||||
input.setCalendar(getLocaleCalendar());
|
||||
return input;
|
||||
public static void setDisplayBootMenuNextRefresh(boolean en) {
|
||||
PlatformRuntime.setDisplayBootMenuNextRefresh(en);
|
||||
}
|
||||
|
||||
public static void setMCServerWindowGlobal(String url) {
|
||||
PlatformApplication.setMCServerWindowGlobal(url);
|
||||
}
|
||||
|
||||
public static long steadyTimeMillis() {
|
||||
return PlatformRuntime.steadyTimeMillis();
|
||||
}
|
||||
|
||||
public static long nanoTime() {
|
||||
return PlatformRuntime.nanoTime();
|
||||
}
|
||||
|
||||
public static void immediateContinue() {
|
||||
PlatformRuntime.immediateContinue();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.lax1dude.eaglercraft.v1_8;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
@ -85,4 +86,12 @@ public class EagUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static EaglercraftUUID makeClientBrandUUID(String name) {
|
||||
return EaglercraftUUID.nameUUIDFromBytes(("EaglercraftXClient:" + name).getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public static EaglercraftUUID makeClientBrandUUIDLegacy(String name) {
|
||||
return EaglercraftUUID.nameUUIDFromBytes(("EaglercraftXClientOld:" + name).getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -74,6 +74,11 @@ public class EaglerOutputStream extends OutputStream {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void skipBytes(int num) {
|
||||
ensureCapacity(count + num);
|
||||
count += num;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
}
|
||||
}
|
||||
|
@ -28,10 +28,7 @@ public class EaglerXBungeeVersion {
|
||||
private static String pluginFilename = null;
|
||||
|
||||
public static void initialize() {
|
||||
String pluginVersionJson = EagRuntime.getResourceString("plugin_version.json");
|
||||
if(pluginVersionJson == null) {
|
||||
throw new RuntimeException("File \"plugin_version.json\" is missing in the epk!");
|
||||
}
|
||||
String pluginVersionJson = EagRuntime.getRequiredResourceString("plugin_version.json");
|
||||
JSONObject json = new JSONObject(pluginVersionJson);
|
||||
pluginName = json.getString("pluginName");
|
||||
pluginVersion = json.getString("pluginVersion");
|
||||
@ -76,11 +73,7 @@ public class EaglerXBungeeVersion {
|
||||
}
|
||||
|
||||
public static byte[] getPluginDownload() {
|
||||
byte[] ret = EagRuntime.getResourceBytes(pluginFileEPK);
|
||||
if(ret == null) {
|
||||
throw new RuntimeException("File \"" + pluginFileEPK + "\" is missing in the epk!");
|
||||
}
|
||||
return ret;
|
||||
return EagRuntime.getRequiredResourceBytes(pluginFileEPK);
|
||||
}
|
||||
|
||||
public static void startPluginDownload() {
|
||||
|
@ -130,10 +130,10 @@ public class EaglercraftSoundManager {
|
||||
settings.getSoundLevel(SoundCategory.RECORDS), settings.getSoundLevel(SoundCategory.WEATHER),
|
||||
settings.getSoundLevel(SoundCategory.BLOCKS), settings.getSoundLevel(SoundCategory.MOBS),
|
||||
settings.getSoundLevel(SoundCategory.ANIMALS), settings.getSoundLevel(SoundCategory.PLAYERS),
|
||||
settings.getSoundLevel(SoundCategory.AMBIENT), settings.getSoundLevel(SoundCategory.VOICE)
|
||||
settings.getSoundLevel(SoundCategory.AMBIENT)
|
||||
};
|
||||
activeSounds = new LinkedList();
|
||||
queuedSounds = new LinkedList();
|
||||
activeSounds = new LinkedList<>();
|
||||
queuedSounds = new LinkedList<>();
|
||||
}
|
||||
|
||||
public void unloadSoundSystem() {
|
||||
|
@ -21,6 +21,8 @@ public class EaglercraftUUID implements Comparable<EaglercraftUUID> {
|
||||
|
||||
public final long msb;
|
||||
public final long lsb;
|
||||
private int hash = 0;
|
||||
private boolean hasHash;
|
||||
|
||||
public EaglercraftUUID(long msb, long lsb) {
|
||||
this.msb = msb;
|
||||
@ -125,13 +127,21 @@ public class EaglercraftUUID implements Comparable<EaglercraftUUID> {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
long hilo = msb ^ lsb;
|
||||
return ((int) (hilo >> 32)) ^ (int) hilo;
|
||||
if(hash == 0 && !hasHash) {
|
||||
long hilo = msb ^ lsb;
|
||||
hash = ((int) (hilo >> 32)) ^ (int) hilo;
|
||||
hasHash = true;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return (o instanceof EaglercraftUUID) && ((EaglercraftUUID) o).lsb == lsb && ((EaglercraftUUID) o).msb == msb;
|
||||
if(!(o instanceof EaglercraftUUID)) return false;
|
||||
EaglercraftUUID oo = (EaglercraftUUID)o;
|
||||
return (hasHash && oo.hasHash)
|
||||
? (hash == oo.hash && msb == oo.msb && lsb == oo.lsb)
|
||||
: (msb == oo.msb && lsb == oo.lsb);
|
||||
}
|
||||
|
||||
public long getMostSignificantBits() {
|
||||
|
@ -10,7 +10,7 @@ public class EaglercraftVersion {
|
||||
/// Customize these to fit your fork:
|
||||
|
||||
public static final String projectForkName = "EaglercraftX";
|
||||
public static final String projectForkVersion = "u36";
|
||||
public static final String projectForkVersion = "u37";
|
||||
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 = "u36";
|
||||
public static final String projectOriginVersion = "u37";
|
||||
|
||||
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 = 36;
|
||||
public static final int updateBundlePackageVersionInt = 37;
|
||||
|
||||
public static final String updateLatestLocalStorageKey = "latestUpdate_" + updateBundlePackageName;
|
||||
|
||||
@ -40,6 +40,13 @@ public class EaglercraftVersion {
|
||||
|
||||
|
||||
|
||||
// Client brand identification system configuration
|
||||
|
||||
public static final EaglercraftUUID clientBrandUUID = EagUtils.makeClientBrandUUID(projectForkName);
|
||||
|
||||
public static final EaglercraftUUID legacyClientUUIDInSharedWorld = EagUtils.makeClientBrandUUIDLegacy(projectOriginName);
|
||||
|
||||
|
||||
// Miscellaneous variables:
|
||||
|
||||
public static final String mainMenuStringA = "Minecraft 1.8.8";
|
||||
|
158
sources/main/java/net/lax1dude/eaglercraft/v1_8/Filesystem.java
Normal file
158
sources/main/java/net/lax1dude/eaglercraft/v1_8/Filesystem.java
Normal file
@ -0,0 +1,158 @@
|
||||
package net.lax1dude.eaglercraft.v1_8;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IEaglerFilesystem;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformFilesystem;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.RamdiskFilesystemImpl;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.VFSFilenameIterator;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
|
||||
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 Filesystem {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger("PlatformFilesystem");
|
||||
|
||||
private static final Map<String,FilesystemHandle> openFilesystems = new HashMap<>();
|
||||
|
||||
public static IEaglerFilesystem getHandleFor(String dbName) {
|
||||
FilesystemHandle handle = openFilesystems.get(dbName);
|
||||
if(handle != null) {
|
||||
++handle.refCount;
|
||||
return new FilesystemHandleWrapper(handle);
|
||||
}
|
||||
IEaglerFilesystem handleImpl = null;
|
||||
if(!EagRuntime.getConfiguration().isRamdiskMode()) {
|
||||
handleImpl = PlatformFilesystem.initializePersist(dbName);
|
||||
}
|
||||
if(handleImpl == null) {
|
||||
handleImpl = new RamdiskFilesystemImpl(dbName);
|
||||
}
|
||||
if(handleImpl.isRamdisk()) {
|
||||
logger.warn("Using RAMDisk filesystem for database \"{}\", data will not be saved to local storage!", dbName);
|
||||
}
|
||||
handle = new FilesystemHandle(handleImpl);
|
||||
openFilesystems.put(dbName, handle);
|
||||
return new FilesystemHandleWrapper(handle);
|
||||
}
|
||||
|
||||
public static void closeAllHandles() {
|
||||
for(FilesystemHandle handle : openFilesystems.values()) {
|
||||
handle.refCount = 0;
|
||||
handle.handle.closeHandle();
|
||||
}
|
||||
openFilesystems.clear();
|
||||
}
|
||||
|
||||
private static class FilesystemHandle {
|
||||
|
||||
private final IEaglerFilesystem handle;
|
||||
private int refCount;
|
||||
|
||||
private FilesystemHandle(IEaglerFilesystem handle) {
|
||||
this.handle = handle;
|
||||
this.refCount = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class FilesystemHandleWrapper implements IEaglerFilesystem {
|
||||
|
||||
private final FilesystemHandle handle;
|
||||
private final IEaglerFilesystem handleImpl;
|
||||
private boolean closed;
|
||||
|
||||
private FilesystemHandleWrapper(FilesystemHandle handle) {
|
||||
this.handle = handle;
|
||||
this.handleImpl = handle.handle;
|
||||
this.closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilesystemName() {
|
||||
return handleImpl.getFilesystemName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInternalDBName() {
|
||||
return handleImpl.getInternalDBName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRamdisk() {
|
||||
return handleImpl.isRamdisk();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eaglerDelete(String pathName) {
|
||||
return handleImpl.eaglerDelete(pathName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer eaglerRead(String pathName) {
|
||||
return handleImpl.eaglerRead(pathName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eaglerWrite(String pathName, ByteBuffer data) {
|
||||
handleImpl.eaglerWrite(pathName, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eaglerExists(String pathName) {
|
||||
return handleImpl.eaglerExists(pathName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eaglerMove(String pathNameOld, String pathNameNew) {
|
||||
return handleImpl.eaglerMove(pathNameOld, pathNameNew);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int eaglerCopy(String pathNameOld, String pathNameNew) {
|
||||
return handleImpl.eaglerCopy(pathNameOld, pathNameNew);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int eaglerSize(String pathName) {
|
||||
return handleImpl.eaglerSize(pathName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eaglerIterate(String pathName, VFSFilenameIterator itr, boolean recursive) {
|
||||
handleImpl.eaglerIterate(pathName, itr, recursive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeHandle() {
|
||||
if(!closed && handle.refCount > 0) {
|
||||
closed = true;
|
||||
--handle.refCount;
|
||||
if(handle.refCount <= 0) {
|
||||
logger.info("Releasing filesystem handle for: \"{}\"", handleImpl.getFilesystemName());
|
||||
handleImpl.closeHandle();
|
||||
openFilesystems.remove(handleImpl.getFilesystemName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
115
sources/main/java/net/lax1dude/eaglercraft/v1_8/Gamepad.java
Normal file
115
sources/main/java/net/lax1dude/eaglercraft/v1_8/Gamepad.java
Normal file
@ -0,0 +1,115 @@
|
||||
package net.lax1dude.eaglercraft.v1_8;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.GamepadConstants;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformInput;
|
||||
|
||||
/**
|
||||
* 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 Gamepad {
|
||||
|
||||
private static final boolean[] buttonsLastState = new boolean[24];
|
||||
private static final List<VirtualButtonEvent> buttonEvents = new LinkedList<>();
|
||||
private static VirtualButtonEvent currentVEvent = null;
|
||||
|
||||
private static class VirtualButtonEvent {
|
||||
|
||||
private final int button;
|
||||
private final boolean state;
|
||||
|
||||
public VirtualButtonEvent(int button, boolean state) {
|
||||
this.button = button;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static int getValidDeviceCount() {
|
||||
return PlatformInput.gamepadGetValidDeviceCount();
|
||||
}
|
||||
|
||||
public static String getDeviceName(int deviceId) {
|
||||
return PlatformInput.gamepadGetDeviceName(deviceId);
|
||||
}
|
||||
|
||||
public static void setSelectedDevice(int deviceId) {
|
||||
PlatformInput.gamepadSetSelectedDevice(deviceId);
|
||||
}
|
||||
|
||||
public static void update() {
|
||||
PlatformInput.gamepadUpdate();
|
||||
if(isValid()) {
|
||||
for(int i = 0; i < buttonsLastState.length; ++i) {
|
||||
boolean b = PlatformInput.gamepadGetButtonState(i);
|
||||
if(b != buttonsLastState[i]) {
|
||||
buttonsLastState[i] = b;
|
||||
buttonEvents.add(new VirtualButtonEvent(i, b));
|
||||
if(buttonEvents.size() > 64) {
|
||||
buttonEvents.remove(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else {
|
||||
for(int i = 0; i < buttonsLastState.length; ++i) {
|
||||
buttonsLastState[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean next() {
|
||||
currentVEvent = null;
|
||||
return !buttonEvents.isEmpty() && (currentVEvent = buttonEvents.remove(0)) != null;
|
||||
}
|
||||
|
||||
public static int getEventButton() {
|
||||
return currentVEvent != null ? currentVEvent.button : -1;
|
||||
}
|
||||
|
||||
public static boolean getEventButtonState() {
|
||||
return currentVEvent != null ? currentVEvent.state : false;
|
||||
}
|
||||
|
||||
public static boolean isValid() {
|
||||
return PlatformInput.gamepadIsValid();
|
||||
}
|
||||
|
||||
public static String getName() {
|
||||
return PlatformInput.gamepadGetName();
|
||||
}
|
||||
|
||||
public static boolean getButtonState(int button) {
|
||||
return PlatformInput.gamepadGetButtonState(button);
|
||||
}
|
||||
|
||||
public static String getButtonName(int button) {
|
||||
return GamepadConstants.getButtonName(button);
|
||||
}
|
||||
|
||||
public static float getAxis(int axis) {
|
||||
return PlatformInput.gamepadGetAxis(axis);
|
||||
}
|
||||
|
||||
public static String getAxisName(int button) {
|
||||
return GamepadConstants.getAxisName(button);
|
||||
}
|
||||
|
||||
public static void clearEventBuffer() {
|
||||
buttonEvents.clear();
|
||||
}
|
||||
|
||||
}
|
54
sources/main/java/net/lax1dude/eaglercraft/v1_8/HashKey.java
Normal file
54
sources/main/java/net/lax1dude/eaglercraft/v1_8/HashKey.java
Normal file
@ -0,0 +1,54 @@
|
||||
package net.lax1dude.eaglercraft.v1_8;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 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 HashKey {
|
||||
|
||||
public final byte[] key;
|
||||
public final int hash;
|
||||
|
||||
public HashKey(byte[] key, int hashCode) {
|
||||
this.key = key;
|
||||
this.hash = hashCode;
|
||||
}
|
||||
|
||||
public HashKey(byte[] key) {
|
||||
this.key = key;
|
||||
this.hash = Arrays.hashCode(key);
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
return new HashKey(key, hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null || !(obj instanceof HashKey))
|
||||
return false;
|
||||
HashKey other = (HashKey) obj;
|
||||
return hash == other.hash && Arrays.equals(key, other.key);
|
||||
}
|
||||
|
||||
}
|
@ -32,7 +32,7 @@ public class IOUtils {
|
||||
return Arrays.asList(
|
||||
new String(((EaglerInputStream) parInputStream).getAsArray(), charset).split("(\\r\\n|\\n|\\r)"));
|
||||
}else {
|
||||
List<String> ret = new ArrayList();
|
||||
List<String> ret = new ArrayList<>();
|
||||
try(InputStream is = parInputStream) {
|
||||
BufferedReader rd = new BufferedReader(new InputStreamReader(is, charset));
|
||||
String s;
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.lax1dude.eaglercraft.v1_8;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.EnumFireKeyboardEvent;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.KeyboardConstants;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformInput;
|
||||
|
||||
@ -60,4 +61,8 @@ public class Keyboard {
|
||||
return PlatformInput.keyboardIsRepeatEvent();
|
||||
}
|
||||
|
||||
public static void fireEvent(EnumFireKeyboardEvent eventType, int eagKey, char keyChar) {
|
||||
PlatformInput.keyboardFireEvent(eventType, eagKey, keyChar);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.lax1dude.eaglercraft.v1_8;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.EnumCursorType;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.EnumFireMouseEvent;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformInput;
|
||||
|
||||
/**
|
||||
@ -92,6 +93,22 @@ public class Mouse {
|
||||
return PlatformInput.isMouseGrabbed();
|
||||
}
|
||||
|
||||
public static boolean isMouseGrabSupported() {
|
||||
return PlatformInput.mouseGrabSupported();
|
||||
}
|
||||
|
||||
public static void fireMoveEvent(EnumFireMouseEvent eventType, int posX, int posY) {
|
||||
PlatformInput.mouseFireMoveEvent(eventType, posX, posY);
|
||||
}
|
||||
|
||||
public static void fireButtonEvent(EnumFireMouseEvent eventType, int posX, int posY, int button) {
|
||||
PlatformInput.mouseFireButtonEvent(eventType, posX, posY, button);
|
||||
}
|
||||
|
||||
public static void fireWheelEvent(EnumFireMouseEvent eventType, int posX, int posY, float wheel) {
|
||||
PlatformInput.mouseFireWheelEvent(eventType, posX, posY, wheel);
|
||||
}
|
||||
|
||||
private static int customCursorCounter = 0;
|
||||
private static EnumCursorType currentCursorType = EnumCursorType.DEFAULT;
|
||||
|
||||
|
@ -0,0 +1,257 @@
|
||||
package net.lax1dude.eaglercraft.v1_8;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.ImageData;
|
||||
import net.lax1dude.eaglercraft.v1_8.profile.EaglerSkinTexture;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketCustomizePauseMenuV4EAG;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.PacketImageData;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
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 PauseMenuCustomizeState {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger("PauseMenuCustomizeState");
|
||||
|
||||
public static ResourceLocation icon_title_L;
|
||||
public static float icon_title_L_aspect = 1.0f;
|
||||
public static ResourceLocation icon_title_R;
|
||||
public static float icon_title_R_aspect = 1.0f;
|
||||
public static ResourceLocation icon_backToGame_L;
|
||||
public static float icon_backToGame_L_aspect = 1.0f;
|
||||
public static ResourceLocation icon_backToGame_R;
|
||||
public static float icon_backToGame_R_aspect = 1.0f;
|
||||
public static ResourceLocation icon_achievements_L;
|
||||
public static float icon_achievements_L_aspect = 1.0f;
|
||||
public static ResourceLocation icon_achievements_R;
|
||||
public static float icon_achievements_R_aspect = 1.0f;
|
||||
public static ResourceLocation icon_statistics_L;
|
||||
public static float icon_statistics_L_aspect = 1.0f;
|
||||
public static ResourceLocation icon_statistics_R;
|
||||
public static float icon_statistics_R_aspect = 1.0f;
|
||||
public static ResourceLocation icon_serverInfo_L;
|
||||
public static float icon_serverInfo_L_aspect = 1.0f;
|
||||
public static ResourceLocation icon_serverInfo_R;
|
||||
public static float icon_serverInfo_R_aspect = 1.0f;
|
||||
public static ResourceLocation icon_options_L;
|
||||
public static float icon_options_L_aspect = 1.0f;
|
||||
public static ResourceLocation icon_options_R;
|
||||
public static float icon_options_R_aspect = 1.0f;
|
||||
public static ResourceLocation icon_discord_L;
|
||||
public static float icon_discord_L_aspect = 1.0f;
|
||||
public static ResourceLocation icon_discord_R;
|
||||
public static float icon_discord_R_aspect = 1.0f;
|
||||
public static ResourceLocation icon_disconnect_L;
|
||||
public static float icon_disconnect_L_aspect = 1.0f;
|
||||
public static ResourceLocation icon_disconnect_R;
|
||||
public static float icon_disconnect_R_aspect = 1.0f;
|
||||
public static ResourceLocation icon_background_pause;
|
||||
public static float icon_background_pause_aspect = 1.0f;
|
||||
public static ResourceLocation icon_background_all;
|
||||
public static float icon_background_all_aspect = 1.0f;
|
||||
public static ResourceLocation icon_watermark_pause;
|
||||
public static float icon_watermark_pause_aspect = 1.0f;
|
||||
public static ResourceLocation icon_watermark_all;
|
||||
public static float icon_watermark_all_aspect = 1.0f;
|
||||
|
||||
public static final int SERVER_INFO_MODE_NONE = SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_NONE;
|
||||
public static final int SERVER_INFO_MODE_EXTERNAL_URL = SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_EXTERNAL_URL;
|
||||
public static final int SERVER_INFO_MODE_SHOW_EMBED_OVER_HTTP = SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_SHOW_EMBED_OVER_HTTP;
|
||||
public static final int SERVER_INFO_MODE_SHOW_EMBED_OVER_WS = SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_SHOW_EMBED_OVER_WS;
|
||||
|
||||
public static final int SERVER_INFO_EMBED_PERMS_JAVASCRIPT = SPacketCustomizePauseMenuV4EAG.SERVER_INFO_EMBED_PERMS_JAVASCRIPT;
|
||||
public static final int SERVER_INFO_EMBED_PERMS_MESSAGE_API = SPacketCustomizePauseMenuV4EAG.SERVER_INFO_EMBED_PERMS_MESSAGE_API;
|
||||
public static final int SERVER_INFO_EMBED_PERMS_STRICT_CSP = SPacketCustomizePauseMenuV4EAG.SERVER_INFO_EMBED_PERMS_STRICT_CSP;
|
||||
|
||||
public static final int DISCORD_MODE_NONE = SPacketCustomizePauseMenuV4EAG.DISCORD_MODE_NONE;
|
||||
public static final int DISCORD_MODE_INVITE_URL = SPacketCustomizePauseMenuV4EAG.DISCORD_MODE_INVITE_URL;
|
||||
|
||||
public static int serverInfoMode;
|
||||
public static int serverInfoEmbedPerms = SERVER_INFO_EMBED_PERMS_STRICT_CSP;
|
||||
public static String serverInfoEmbedTitle;
|
||||
public static String serverInfoButtonText;
|
||||
public static String serverInfoURL;
|
||||
public static byte[] serverInfoHash;
|
||||
|
||||
public static int discordButtonMode;
|
||||
public static String discordButtonText;
|
||||
public static String discordInviteURL;
|
||||
|
||||
private static final List<PauseMenuSprite> toFree = new ArrayList<>();
|
||||
|
||||
private static int textureId = 0;
|
||||
|
||||
private static class PauseMenuSprite {
|
||||
|
||||
private final ResourceLocation loc;
|
||||
private final EaglerSkinTexture tex;
|
||||
|
||||
public PauseMenuSprite(EaglerSkinTexture tex) {
|
||||
this.loc = newLoc();
|
||||
this.tex = tex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void loadPacket(SPacketCustomizePauseMenuV4EAG packet) {
|
||||
reset();
|
||||
|
||||
serverInfoMode = packet.serverInfoMode;
|
||||
switch(packet.serverInfoMode) {
|
||||
case SERVER_INFO_MODE_NONE:
|
||||
default:
|
||||
serverInfoButtonText = null;
|
||||
serverInfoURL = null;
|
||||
serverInfoHash = null;
|
||||
break;
|
||||
case SERVER_INFO_MODE_EXTERNAL_URL:
|
||||
serverInfoButtonText = packet.serverInfoButtonText;
|
||||
serverInfoURL = packet.serverInfoURL;
|
||||
break;
|
||||
case SERVER_INFO_MODE_SHOW_EMBED_OVER_HTTP:
|
||||
serverInfoButtonText = packet.serverInfoButtonText;
|
||||
serverInfoEmbedPerms = packet.serverInfoEmbedPerms;
|
||||
serverInfoURL = packet.serverInfoURL;
|
||||
serverInfoEmbedTitle = packet.serverInfoEmbedTitle;
|
||||
break;
|
||||
case SERVER_INFO_MODE_SHOW_EMBED_OVER_WS:
|
||||
serverInfoButtonText = packet.serverInfoButtonText;
|
||||
serverInfoEmbedPerms = packet.serverInfoEmbedPerms;
|
||||
serverInfoHash = packet.serverInfoHash;
|
||||
serverInfoEmbedTitle = packet.serverInfoEmbedTitle;
|
||||
break;
|
||||
}
|
||||
|
||||
discordButtonMode = packet.discordButtonMode;
|
||||
switch(packet.discordButtonMode) {
|
||||
case DISCORD_MODE_NONE:
|
||||
default:
|
||||
discordButtonText = null;
|
||||
serverInfoURL = null;
|
||||
serverInfoHash = null;
|
||||
break;
|
||||
case DISCORD_MODE_INVITE_URL:
|
||||
discordButtonText = packet.discordButtonText;
|
||||
discordInviteURL = packet.discordInviteURL;
|
||||
break;
|
||||
}
|
||||
|
||||
if(packet.imageMappings != null) {
|
||||
Map<Integer, PauseMenuSprite> spriteCache = new HashMap<>();
|
||||
icon_title_L = cacheLoadHelperFunction("icon_title_L", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_title_L_aspect = a);
|
||||
icon_title_R = cacheLoadHelperFunction("icon_title_R", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_title_R_aspect = a);
|
||||
icon_backToGame_L = cacheLoadHelperFunction("icon_backToGame_L", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_backToGame_L_aspect = a);
|
||||
icon_backToGame_R = cacheLoadHelperFunction("icon_backToGame_R", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_backToGame_R_aspect = a);
|
||||
icon_achievements_L = cacheLoadHelperFunction("icon_achievements_L", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_achievements_L_aspect = a);
|
||||
icon_achievements_R = cacheLoadHelperFunction("icon_achievements_R", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_achievements_R_aspect = a);
|
||||
icon_statistics_L = cacheLoadHelperFunction("icon_statistics_L", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_statistics_L_aspect = a);
|
||||
icon_statistics_R = cacheLoadHelperFunction("icon_statistics_R", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_statistics_R_aspect = a);
|
||||
icon_serverInfo_L = cacheLoadHelperFunction("icon_serverInfo_L", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_serverInfo_L_aspect = a);
|
||||
icon_serverInfo_R = cacheLoadHelperFunction("icon_serverInfo_R", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_serverInfo_R_aspect = a);
|
||||
icon_options_L = cacheLoadHelperFunction("icon_options_L", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_options_L_aspect = a);
|
||||
icon_options_R = cacheLoadHelperFunction("icon_options_R", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_options_R_aspect = a);
|
||||
icon_discord_L = cacheLoadHelperFunction("icon_discord_L", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_discord_L_aspect = a);
|
||||
icon_discord_R = cacheLoadHelperFunction("icon_discord_R", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_discord_R_aspect = a);
|
||||
icon_disconnect_L = cacheLoadHelperFunction("icon_disconnect_L", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_disconnect_L_aspect = a);
|
||||
icon_disconnect_R = cacheLoadHelperFunction("icon_disconnect_R", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_disconnect_R_aspect = a);
|
||||
icon_background_pause = cacheLoadHelperFunction("icon_background_pause", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_background_pause_aspect = a);
|
||||
icon_background_all = cacheLoadHelperFunction("icon_background_all", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_background_all_aspect = a);
|
||||
icon_watermark_pause = cacheLoadHelperFunction("icon_watermark_pause", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_watermark_pause_aspect = a);
|
||||
icon_watermark_all = cacheLoadHelperFunction("icon_watermark_all", packet.imageMappings, spriteCache, packet.imageData, (a) -> icon_watermark_all_aspect = a);
|
||||
}
|
||||
}
|
||||
|
||||
private static ResourceLocation cacheLoadHelperFunction(String name, Map<String, Integer> lookup,
|
||||
Map<Integer, PauseMenuSprite> spriteCache,
|
||||
List<PacketImageData> sourceData, Consumer<Float> aspectCB) {
|
||||
Integer i = lookup.get(name);
|
||||
if(i == null) {
|
||||
return null;
|
||||
}
|
||||
PauseMenuSprite ret = spriteCache.get(i);
|
||||
if(ret != null) {
|
||||
if(name.startsWith("icon_background_") && ImageData.isNPOTStatic(ret.tex.getWidth(), ret.tex.getHeight())) {
|
||||
logger.warn("An NPOT (non-power-of-two) texture was used for \"{}\", this texture's width and height must be powers of two for this texture to display properly on all hardware");
|
||||
}
|
||||
aspectCB.accept((float)ret.tex.getWidth() / ret.tex.getHeight());
|
||||
return ret.loc;
|
||||
}
|
||||
int ii = i.intValue();
|
||||
if(ii < 0 || ii >= sourceData.size()) {
|
||||
return null;
|
||||
}
|
||||
PacketImageData data = sourceData.get(ii);
|
||||
ret = new PauseMenuSprite(new EaglerSkinTexture(ImageData.swapRB(data.rgba), data.width, data.height));
|
||||
Minecraft.getMinecraft().getTextureManager().loadTexture(ret.loc, ret.tex);
|
||||
spriteCache.put(i, ret);
|
||||
toFree.add(ret);
|
||||
aspectCB.accept((float)data.width / data.height);
|
||||
return ret.loc;
|
||||
}
|
||||
|
||||
private static ResourceLocation newLoc() {
|
||||
return new ResourceLocation("eagler:gui/server/custom_pause_menu/tex_" + textureId++);
|
||||
}
|
||||
|
||||
public static void reset() {
|
||||
icon_title_L = icon_title_R = null;
|
||||
icon_backToGame_L = icon_backToGame_R = null;
|
||||
icon_achievements_L = icon_achievements_R = null;
|
||||
icon_statistics_L = icon_statistics_R = null;
|
||||
icon_serverInfo_L = icon_serverInfo_R = null;
|
||||
icon_options_L = icon_options_R = null;
|
||||
icon_discord_L = icon_discord_R = null;
|
||||
icon_disconnect_L = icon_disconnect_R = null;
|
||||
icon_background_pause = icon_background_all = null;
|
||||
icon_watermark_pause = icon_watermark_all = null;
|
||||
icon_title_L_aspect = icon_title_R_aspect = 1.0f;
|
||||
icon_backToGame_L_aspect = icon_backToGame_R_aspect = 1.0f;
|
||||
icon_achievements_L_aspect = icon_achievements_R_aspect = 1.0f;
|
||||
icon_statistics_L_aspect = icon_statistics_R_aspect = 1.0f;
|
||||
icon_serverInfo_L_aspect = icon_serverInfo_R_aspect = 1.0f;
|
||||
icon_options_L_aspect = icon_options_R_aspect = 1.0f;
|
||||
icon_discord_L_aspect = icon_discord_R_aspect = 1.0f;
|
||||
icon_disconnect_L_aspect = icon_disconnect_R_aspect = 1.0f;
|
||||
icon_background_pause_aspect = icon_background_all_aspect = 1.0f;
|
||||
icon_watermark_pause_aspect = icon_watermark_all_aspect = 1.0f;
|
||||
serverInfoMode = 0;
|
||||
serverInfoEmbedPerms = SERVER_INFO_EMBED_PERMS_STRICT_CSP;
|
||||
serverInfoButtonText = null;
|
||||
serverInfoURL = null;
|
||||
serverInfoHash = null;
|
||||
serverInfoEmbedTitle = null;
|
||||
discordButtonMode = 0;
|
||||
discordButtonText = null;
|
||||
discordInviteURL = null;
|
||||
if(!toFree.isEmpty()) {
|
||||
TextureManager mgr = Minecraft.getMinecraft().getTextureManager();
|
||||
for(PauseMenuSprite rc : toFree) {
|
||||
mgr.deleteTexture(rc.loc);
|
||||
}
|
||||
toFree.clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,227 @@
|
||||
package net.lax1dude.eaglercraft.v1_8;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.touch_gui.TouchControls;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class PointerInputAbstraction {
|
||||
|
||||
protected static Minecraft mc;
|
||||
protected static int oldMX = -1;
|
||||
protected static int oldMY = -1;
|
||||
protected static int oldTX = -1;
|
||||
protected static int oldTY = -1;
|
||||
protected static int dragStartX = -1;
|
||||
protected static int dragStartY = -1;
|
||||
protected static int dragStepStartX = -1;
|
||||
protected static int dragStepStartY = -1;
|
||||
protected static int dragUID = -1;
|
||||
|
||||
protected static int cursorX = -1;
|
||||
protected static int cursorY = -1;
|
||||
protected static int cursorDX = 0;
|
||||
protected static int cursorDY = 0;
|
||||
protected static boolean touchingScreen = false;
|
||||
protected static boolean touchingScreenNotButton = false;
|
||||
protected static boolean draggingNotTouching = false;
|
||||
protected static boolean touchMode = false;
|
||||
|
||||
public static void init(Minecraft mcIn) {
|
||||
mc = mcIn;
|
||||
oldMX = -1;
|
||||
oldMY = -1;
|
||||
oldTX = -1;
|
||||
oldTY = -1;
|
||||
dragStartX = -1;
|
||||
dragStartY = -1;
|
||||
dragStepStartX = -1;
|
||||
dragStepStartY = -1;
|
||||
dragUID = -1;
|
||||
cursorX = -1;
|
||||
cursorY = -1;
|
||||
cursorDX = 0;
|
||||
cursorDY = 0;
|
||||
touchingScreen = false;
|
||||
touchingScreenNotButton = false;
|
||||
draggingNotTouching = false;
|
||||
touchMode = !mcIn.mouseGrabSupported;
|
||||
}
|
||||
|
||||
public static void runGameLoop() {
|
||||
if(touchMode) {
|
||||
runTouchUpdate();
|
||||
}else {
|
||||
oldTX = -1;
|
||||
oldTY = -1;
|
||||
cursorX = oldMX = Mouse.getX();
|
||||
cursorY = oldMY = Mouse.getY();
|
||||
cursorDX += Mouse.getDX();
|
||||
cursorDY += Mouse.getDY();
|
||||
}
|
||||
}
|
||||
|
||||
private static void runTouchUpdate() {
|
||||
int tc = Touch.touchPointCount();
|
||||
if (tc > 0) {
|
||||
TouchControls.update(true);
|
||||
touchingScreen = true;
|
||||
for(int i = 0; i < tc; ++i) {
|
||||
int uid = Touch.touchPointUID(i);
|
||||
if(TouchControls.touchControls.containsKey(uid)) {
|
||||
continue;
|
||||
}
|
||||
int tx = Touch.touchPointX(i);
|
||||
int ty = Touch.touchPointY(i);
|
||||
if(TouchControls.overlappingControl(tx, ty) != null) {
|
||||
continue;
|
||||
}
|
||||
if(mc.currentScreen == null && mc.ingameGUI.isTouchOverlapEagler(uid, tx, ty)) {
|
||||
continue;
|
||||
}
|
||||
cursorX = oldTX = tx;
|
||||
cursorY = oldTY = ty;
|
||||
oldMX = Mouse.getX();
|
||||
oldMY = Mouse.getY();
|
||||
touchingScreenNotButton = true;
|
||||
runTouchDeltaUpdate(uid);
|
||||
return;
|
||||
}
|
||||
touchingScreenNotButton = false;
|
||||
} else {
|
||||
TouchControls.update(false);
|
||||
touchingScreen = false;
|
||||
touchingScreenNotButton = false;
|
||||
dragStepStartX = -1;
|
||||
dragStepStartY = -1;
|
||||
dragStartX = -1;
|
||||
dragStartY = -1;
|
||||
dragUID = -1;
|
||||
final int tmp = Mouse.getX();
|
||||
final int tmp2 = Mouse.getY();
|
||||
if(oldTX == -1 || oldTY == -1) {
|
||||
cursorX = oldMX = tmp;
|
||||
cursorY = oldMY = tmp2;
|
||||
cursorDX += Mouse.getDX();
|
||||
cursorDY += Mouse.getDY();
|
||||
return;
|
||||
}
|
||||
if (oldMX == -1 || oldMY == -1) {
|
||||
oldMX = tmp;
|
||||
oldMY = tmp2;
|
||||
}
|
||||
if (oldMX == tmp && oldMY == tmp2) {
|
||||
cursorX = oldTX;
|
||||
cursorY = oldTY;
|
||||
}else {
|
||||
cursorX = oldMX = tmp;
|
||||
cursorY = oldMY = tmp2;
|
||||
cursorDX += Mouse.getDX();
|
||||
cursorDY += Mouse.getDY();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void runTouchDeltaUpdate(int uid) {
|
||||
if(uid != dragUID) {
|
||||
dragStartX = oldTX;
|
||||
dragStartY = oldTY;
|
||||
dragStepStartX = -1;
|
||||
dragStepStartY = -1;
|
||||
dragUID = uid;
|
||||
draggingNotTouching = false;
|
||||
return;
|
||||
}
|
||||
if(dragStepStartX != -1) {
|
||||
cursorDX += oldTX - dragStepStartX;
|
||||
}
|
||||
dragStepStartX = oldTX;
|
||||
if(dragStepStartY != -1) {
|
||||
cursorDY += oldTY - dragStepStartY;
|
||||
}
|
||||
dragStepStartY = oldTY;
|
||||
if(dragStartX != -1 && dragStartY != -1) {
|
||||
int dx = oldTX - dragStartX;
|
||||
int dy = oldTY - dragStartY;
|
||||
int len = dx * dx + dy * dy;
|
||||
int dm = Math.max((int)(6 * Display.getDPI()), 2);
|
||||
if(len > dm * dm) {
|
||||
draggingNotTouching = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isTouchMode() {
|
||||
return touchMode;
|
||||
}
|
||||
|
||||
public static boolean isTouchingScreen() {
|
||||
return touchingScreen;
|
||||
}
|
||||
|
||||
public static boolean isTouchingScreenNotButton() {
|
||||
return touchingScreenNotButton;
|
||||
}
|
||||
|
||||
public static boolean isDraggingNotTouching() {
|
||||
return draggingNotTouching;
|
||||
}
|
||||
|
||||
public static void enterTouchModeHook() {
|
||||
if(!touchMode) {
|
||||
touchMode = true;
|
||||
if(mc.mouseGrabSupported) {
|
||||
mc.mouseHelper.ungrabMouseCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void enterMouseModeHook() {
|
||||
if(touchMode) {
|
||||
touchMode = false;
|
||||
touchingScreen = false;
|
||||
touchingScreenNotButton = false;
|
||||
if(mc.inGameHasFocus && mc.mouseGrabSupported) {
|
||||
mc.mouseHelper.grabMouseCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int getVCursorX() {
|
||||
return cursorX;
|
||||
}
|
||||
|
||||
public static int getVCursorY() {
|
||||
return cursorY;
|
||||
}
|
||||
|
||||
public static int getVCursorDX() {
|
||||
int tmp = cursorDX;
|
||||
cursorDX = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
public static int getVCursorDY() {
|
||||
int tmp = cursorDY;
|
||||
cursorDY = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
public static boolean getVCursorButtonDown(int bt) {
|
||||
return (touchingScreenNotButton && bt == 0) || Mouse.isButtonDown(bt);
|
||||
}
|
||||
|
||||
}
|
134
sources/main/java/net/lax1dude/eaglercraft/v1_8/Touch.java
Normal file
134
sources/main/java/net/lax1dude/eaglercraft/v1_8/Touch.java
Normal file
@ -0,0 +1,134 @@
|
||||
package net.lax1dude.eaglercraft.v1_8;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.EnumTouchEvent;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformInput;
|
||||
|
||||
/**
|
||||
* 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 Touch {
|
||||
|
||||
public static boolean next() {
|
||||
return PlatformInput.touchNext();
|
||||
}
|
||||
|
||||
public static EnumTouchEvent getEventType() {
|
||||
return PlatformInput.touchGetEventType();
|
||||
}
|
||||
|
||||
public static int getEventTouchPointCount() {
|
||||
return PlatformInput.touchGetEventTouchPointCount();
|
||||
}
|
||||
|
||||
public static int getEventTouchX(int pointId) {
|
||||
return PlatformInput.touchGetEventTouchX(pointId);
|
||||
}
|
||||
|
||||
public static int getEventTouchY(int pointId) {
|
||||
return PlatformInput.touchGetEventTouchY(pointId);
|
||||
}
|
||||
|
||||
public static float getEventTouchRadiusX(int pointId) {
|
||||
return PlatformInput.touchGetEventTouchRadiusX(pointId);
|
||||
}
|
||||
|
||||
public static float getEventTouchRadiusY(int pointId) {
|
||||
return PlatformInput.touchGetEventTouchRadiusY(pointId);
|
||||
}
|
||||
|
||||
public static float getEventTouchRadiusMixed(int pointId) {
|
||||
return PlatformInput.touchGetEventTouchRadiusMixed(pointId);
|
||||
}
|
||||
|
||||
public static float getEventTouchForce(int pointId) {
|
||||
return PlatformInput.touchGetEventTouchForce(pointId);
|
||||
}
|
||||
|
||||
public static int getEventTouchPointUID(int pointId) {
|
||||
return PlatformInput.touchGetEventTouchPointUID(pointId);
|
||||
}
|
||||
|
||||
public static int touchPointCount() {
|
||||
return PlatformInput.touchPointCount();
|
||||
}
|
||||
|
||||
public static int touchPointX(int pointId) {
|
||||
return PlatformInput.touchPointX(pointId);
|
||||
}
|
||||
|
||||
public static int touchPointY(int pointId) {
|
||||
return PlatformInput.touchPointY(pointId);
|
||||
}
|
||||
|
||||
public static float touchPointRadiusX(int pointId) {
|
||||
return PlatformInput.touchRadiusX(pointId);
|
||||
}
|
||||
|
||||
public static float touchPointRadiusY(int pointId) {
|
||||
return PlatformInput.touchRadiusY(pointId);
|
||||
}
|
||||
|
||||
public static float touchPointRadiusMixed(int pointId) {
|
||||
return PlatformInput.touchRadiusMixed(pointId);
|
||||
}
|
||||
|
||||
public static float touchPointForce(int pointId) {
|
||||
return PlatformInput.touchForce(pointId);
|
||||
}
|
||||
|
||||
public static int touchPointUID(int pointId) {
|
||||
return PlatformInput.touchPointUID(pointId);
|
||||
}
|
||||
|
||||
public static void touchSetOpenKeyboardZone(int x, int y, int w, int h) {
|
||||
PlatformInput.touchSetOpenKeyboardZone(x, y, w, h);
|
||||
}
|
||||
|
||||
public static void closeDeviceKeyboard() {
|
||||
PlatformInput.touchCloseDeviceKeyboard();
|
||||
}
|
||||
|
||||
public static boolean isDeviceKeyboardOpenMAYBE() {
|
||||
return PlatformInput.touchIsDeviceKeyboardOpenMAYBE();
|
||||
}
|
||||
|
||||
public static String getPastedString() {
|
||||
return PlatformInput.touchGetPastedString();
|
||||
}
|
||||
|
||||
public static boolean checkPointTouching(int uid) {
|
||||
int cnt = PlatformInput.touchPointCount();
|
||||
if(cnt > 0) {
|
||||
for(int i = 0; i < cnt; ++i) {
|
||||
if(PlatformInput.touchPointUID(i) == uid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int fetchPointIdx(int uid) {
|
||||
int cnt = PlatformInput.touchPointCount();
|
||||
if(cnt > 0) {
|
||||
for(int i = 0; i < cnt; ++i) {
|
||||
if(PlatformInput.touchPointUID(i) == uid) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.boot_menu;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* 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 GuiScreenEnterBootMenu extends GuiScreen {
|
||||
|
||||
private final GuiScreen parent;
|
||||
|
||||
public GuiScreenEnterBootMenu(GuiScreen parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
EagRuntime.setDisplayBootMenuNextRefresh(true);
|
||||
this.buttonList.clear();
|
||||
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 6 + 96, I18n.format("gui.cancel")));
|
||||
}
|
||||
|
||||
public void onGuiClosed() {
|
||||
EagRuntime.setDisplayBootMenuNextRefresh(false);
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
this.drawCenteredString(fontRendererObj, I18n.format("enterBootMenu.title"), this.width / 2, 70, 11184810);
|
||||
this.drawCenteredString(fontRendererObj, I18n.format("enterBootMenu.text0"), this.width / 2, 90, 16777215);
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if(par1GuiButton.id == 0) {
|
||||
this.mc.displayGuiScreen(parent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -25,7 +25,7 @@ public class EaglerLoadingCache<K, V> {
|
||||
|
||||
public EaglerLoadingCache(EaglerCacheProvider<K, V> provider) {
|
||||
this.provider = provider;
|
||||
this.cacheMap = new HashMap();
|
||||
this.cacheMap = new HashMap<>();
|
||||
}
|
||||
|
||||
public V get(K key) {
|
||||
|
@ -0,0 +1,84 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.cookie;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.cookie.ServerCookieDataStore.ServerCookie;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* 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 GuiScreenInspectSessionToken extends GuiScreen {
|
||||
|
||||
private final GuiScreen parent;
|
||||
private final ServerCookie cookie;
|
||||
|
||||
public GuiScreenInspectSessionToken(GuiScreenRevokeSessionToken parent, ServerCookie cookie) {
|
||||
this.parent = parent;
|
||||
this.cookie = cookie;
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
this.buttonList.clear();
|
||||
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 6 + 106, I18n.format("gui.done")));
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
String[][] toDraw = new String[][] {
|
||||
{
|
||||
I18n.format("inspectSessionToken.details.server"),
|
||||
I18n.format("inspectSessionToken.details.expires"),
|
||||
I18n.format("inspectSessionToken.details.length")
|
||||
},
|
||||
{
|
||||
cookie.server.length() > 32 ? cookie.server.substring(0, 30) + "..." : cookie.server,
|
||||
(new SimpleDateFormat("M/d/yyyy h:mm aa")).format(new Date(cookie.expires)),
|
||||
Integer.toString(cookie.cookie.length)
|
||||
}
|
||||
};
|
||||
int[] maxWidth = new int[2];
|
||||
for(int i = 0; i < 2; ++i) {
|
||||
String[] strs = toDraw[i];
|
||||
int w = 0;
|
||||
for(int j = 0; j < strs.length; ++j) {
|
||||
int k = fontRendererObj.getStringWidth(strs[j]);
|
||||
if(k > w) {
|
||||
w = k;
|
||||
}
|
||||
}
|
||||
maxWidth[i] = w + 10;
|
||||
}
|
||||
int totalWidth = maxWidth[0] + maxWidth[1];
|
||||
this.drawCenteredString(fontRendererObj, I18n.format("inspectSessionToken.title"), this.width / 2, 70, 16777215);
|
||||
this.drawString(fontRendererObj, toDraw[0][0], (this.width - totalWidth) / 2, 90, 11184810);
|
||||
this.drawString(fontRendererObj, toDraw[0][1], (this.width - totalWidth) / 2, 104, 11184810);
|
||||
this.drawString(fontRendererObj, toDraw[0][2], (this.width - totalWidth) / 2, 118, 11184810);
|
||||
this.drawString(fontRendererObj, toDraw[1][0], (this.width - totalWidth) / 2 + maxWidth[0], 90, 11184810);
|
||||
this.drawString(fontRendererObj, toDraw[1][1], (this.width - totalWidth) / 2 + maxWidth[0], 104, 11184810);
|
||||
this.drawString(fontRendererObj, toDraw[1][2], (this.width - totalWidth) / 2 + maxWidth[0], 118, 11184810);
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if(par1GuiButton.id == 0) {
|
||||
this.mc.displayGuiScreen(parent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.cookie;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiSlot;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* 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 GuiScreenRevokeSessionToken extends GuiScreen {
|
||||
protected GuiScreen parentScreen;
|
||||
private GuiScreenRevokeSessionToken.List list;
|
||||
private GuiButton inspectButton;
|
||||
private GuiButton revokeButton;
|
||||
|
||||
public GuiScreenRevokeSessionToken(GuiScreen parent) {
|
||||
this.parentScreen = parent;
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
this.buttonList.clear();
|
||||
this.buttonList.add(this.inspectButton = new GuiButton(10, this.width / 2 - 154, this.height - 38, 100, 20, I18n.format("revokeSessionToken.inspect")));
|
||||
this.buttonList.add(this.revokeButton = new GuiButton(9, this.width / 2 - 50, this.height - 38, 100, 20, I18n.format("revokeSessionToken.revoke")));
|
||||
this.buttonList.add(new GuiButton(6, this.width / 2 + 54, this.height - 38, 100, 20, I18n.format("gui.done")));
|
||||
this.list = new GuiScreenRevokeSessionToken.List(this.mc);
|
||||
this.list.registerScrollButtons(7, 8);
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
public void handleMouseInput() throws IOException {
|
||||
super.handleMouseInput();
|
||||
this.list.handleMouseInput();
|
||||
}
|
||||
|
||||
public void handleTouchInput() throws IOException {
|
||||
super.handleTouchInput();
|
||||
this.list.handleTouchInput();
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton parGuiButton) {
|
||||
if (parGuiButton.enabled) {
|
||||
switch (parGuiButton.id) {
|
||||
case 6:
|
||||
this.mc.displayGuiScreen(this.parentScreen);
|
||||
break;
|
||||
case 9:
|
||||
String s1 = list.getSelectedItem();
|
||||
if(s1 != null) {
|
||||
ServerCookieDataStore.ServerCookie cookie = ServerCookieDataStore.loadCookie(s1);
|
||||
if(cookie != null) {
|
||||
this.mc.displayGuiScreen(new GuiScreenSendRevokeRequest(this, cookie));
|
||||
}else {
|
||||
this.initGui();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
String s2 = list.getSelectedItem();
|
||||
if(s2 != null) {
|
||||
ServerCookieDataStore.ServerCookie cookie = ServerCookieDataStore.loadCookie(s2);
|
||||
if(cookie != null) {
|
||||
this.mc.displayGuiScreen(new GuiScreenInspectSessionToken(this, cookie));
|
||||
}else {
|
||||
this.initGui();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
this.list.actionPerformed(parGuiButton);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateButtons() {
|
||||
inspectButton.enabled = revokeButton.enabled = list.getSelectedItem() != null;
|
||||
}
|
||||
|
||||
public void drawScreen(int i, int j, float f) {
|
||||
this.list.drawScreen(i, j, f);
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("revokeSessionToken.title"), this.width / 2, 16, 16777215);
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("revokeSessionToken.note.0"), this.width / 2, this.height - 66, 8421504);
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("revokeSessionToken.note.1"), this.width / 2, this.height - 56, 8421504);
|
||||
super.drawScreen(i, j, f);
|
||||
}
|
||||
|
||||
class List extends GuiSlot {
|
||||
private final java.util.List<String> cookieNames = Lists.newArrayList();
|
||||
|
||||
public List(Minecraft mcIn) {
|
||||
super(mcIn, GuiScreenRevokeSessionToken.this.width, GuiScreenRevokeSessionToken.this.height, 32, GuiScreenRevokeSessionToken.this.height - 75 + 4, 18);
|
||||
ServerCookieDataStore.flush();
|
||||
cookieNames.addAll(ServerCookieDataStore.getRevokableServers());
|
||||
Collections.sort(cookieNames);
|
||||
}
|
||||
|
||||
protected int getSize() {
|
||||
return this.cookieNames.size();
|
||||
}
|
||||
|
||||
protected void elementClicked(int i, boolean var2, int var3, int var4) {
|
||||
selectedElement = i;
|
||||
GuiScreenRevokeSessionToken.this.updateButtons();
|
||||
}
|
||||
|
||||
protected boolean isSelected(int i) {
|
||||
return selectedElement == i;
|
||||
}
|
||||
|
||||
protected String getSelectedItem() {
|
||||
return selectedElement == -1 ? null : cookieNames.get(selectedElement);
|
||||
}
|
||||
|
||||
protected int getContentHeight() {
|
||||
return this.getSize() * 18;
|
||||
}
|
||||
|
||||
protected void drawBackground() {
|
||||
GuiScreenRevokeSessionToken.this.drawDefaultBackground();
|
||||
}
|
||||
|
||||
protected void drawSlot(int i, int var2, int j, int var4, int var5, int var6) {
|
||||
GuiScreenRevokeSessionToken.this.drawCenteredString(GuiScreenRevokeSessionToken.this.fontRendererObj,
|
||||
this.cookieNames.get(i), this.width / 2, j + 1, 16777215);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,177 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.cookie;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.cookie.ServerCookieDataStore.ServerCookie;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IServerQuery;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.QueryResponse;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.minecraft.GuiScreenGenericErrorMessage;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.ServerQueryDispatch;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* 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 GuiScreenSendRevokeRequest extends GuiScreen {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger("SessionRevokeRequest");
|
||||
|
||||
private GuiScreen parent;
|
||||
private ServerCookie cookie;
|
||||
private String title;
|
||||
private String message;
|
||||
private int timer = 0;
|
||||
private boolean cancelRequested = false;
|
||||
private IServerQuery query = null;
|
||||
private boolean hasSentPacket = false;
|
||||
|
||||
public GuiScreenSendRevokeRequest(GuiScreen parent, ServerCookie cookie) {
|
||||
this.parent = parent;
|
||||
this.cookie = cookie;
|
||||
this.title = I18n.format("revokeSendingScreen.title");
|
||||
this.message = I18n.format("revokeSendingScreen.message.opening", cookie.server);
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
this.buttonList.clear();
|
||||
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 6 + 96, I18n.format("gui.cancel")));
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
this.drawCenteredString(fontRendererObj, title, this.width / 2, 70, 11184810);
|
||||
this.drawCenteredString(fontRendererObj, message, this.width / 2, 90, 16777215);
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
public void updateScreen() {
|
||||
++timer;
|
||||
if (timer > 1) {
|
||||
if(query == null) {
|
||||
logger.info("Attempting to revoke session tokens for: {}", cookie.server);
|
||||
query = ServerQueryDispatch.sendServerQuery(cookie.server, "revoke_session_token");
|
||||
if(query == null) {
|
||||
this.mc.displayGuiScreen(new GuiScreenGenericErrorMessage("revokeFailure.title", "revokeFailure.desc.connectionError", parent));
|
||||
return;
|
||||
}
|
||||
}else {
|
||||
query.update();
|
||||
QueryResponse resp = query.getResponse();
|
||||
if(resp != null) {
|
||||
if(resp.responseType.equalsIgnoreCase("revoke_session_token") && (hasSentPacket ? resp.isResponseJSON() : resp.isResponseString())) {
|
||||
if(!hasSentPacket) {
|
||||
String str = resp.getResponseString();
|
||||
if("ready".equalsIgnoreCase(str)) {
|
||||
hasSentPacket = true;
|
||||
message = I18n.format("revokeSendingScreen.message.sending");
|
||||
query.send(cookie.cookie);
|
||||
return;
|
||||
}else {
|
||||
this.mc.displayGuiScreen(new GuiScreenGenericErrorMessage("revokeFailure.title", "revokeFailure.desc.clientError", parent));
|
||||
return;
|
||||
}
|
||||
}else {
|
||||
JSONObject json = resp.getResponseJSON();
|
||||
String stat = json.optString("status");
|
||||
if("ok".equalsIgnoreCase(stat)) {
|
||||
if(hasSentPacket) {
|
||||
query.close();
|
||||
this.mc.displayGuiScreen(new GuiScreenGenericErrorMessage("revokeSuccess.title", "revokeSuccess.desc", parent));
|
||||
ServerCookieDataStore.clearCookie(cookie.server);
|
||||
return;
|
||||
}else {
|
||||
query.close();
|
||||
this.mc.displayGuiScreen(new GuiScreenGenericErrorMessage("revokeFailure.title", "revokeFailure.desc.clientError", parent));
|
||||
return;
|
||||
}
|
||||
}else if("error".equalsIgnoreCase(stat)) {
|
||||
int code = json.optInt("code", -1);
|
||||
if(code == -1) {
|
||||
query.close();
|
||||
this.mc.displayGuiScreen(new GuiScreenGenericErrorMessage("revokeFailure.title", "revokeFailure.desc.clientError", parent));
|
||||
return;
|
||||
}else {
|
||||
String key;
|
||||
switch(code) {
|
||||
case 1:
|
||||
key = "revokeFailure.desc.notSupported";
|
||||
break;
|
||||
case 2:
|
||||
key = "revokeFailure.desc.notAllowed";
|
||||
break;
|
||||
case 3:
|
||||
key = "revokeFailure.desc.notFound";
|
||||
break;
|
||||
case 4:
|
||||
key = "revokeFailure.desc.serverError";
|
||||
break;
|
||||
default:
|
||||
key = "revokeFailure.desc.genericCode";
|
||||
break;
|
||||
}
|
||||
logger.error("Recieved error code {}! ({})", code, key);
|
||||
query.close();
|
||||
this.mc.displayGuiScreen(new GuiScreenGenericErrorMessage("revokeFailure.title", key, parent));
|
||||
if(json.optBoolean("delete", false)) {
|
||||
ServerCookieDataStore.clearCookie(cookie.server);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}else {
|
||||
logger.error("Recieved unknown status \"{}\"!", stat);
|
||||
query.close();
|
||||
this.mc.displayGuiScreen(new GuiScreenGenericErrorMessage("revokeFailure.title", "revokeFailure.desc.clientError", parent));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}else {
|
||||
query.close();
|
||||
this.mc.displayGuiScreen(new GuiScreenGenericErrorMessage("revokeFailure.title", "revokeFailure.desc.clientError", parent));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(query.isClosed()) {
|
||||
if(!hasSentPacket || query.responsesAvailable() == 0) {
|
||||
this.mc.displayGuiScreen(new GuiScreenGenericErrorMessage("revokeFailure.title", "revokeFailure.desc.connectionError", parent));
|
||||
return;
|
||||
}
|
||||
}else {
|
||||
if(timer > 400) {
|
||||
query.close();
|
||||
this.mc.displayGuiScreen(new GuiScreenGenericErrorMessage("revokeFailure.title", "revokeFailure.desc.connectionError", parent));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(cancelRequested) {
|
||||
query.close();
|
||||
this.mc.displayGuiScreen(new GuiScreenGenericErrorMessage("revokeFailure.title", "revokeFailure.desc.cancelled", parent));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if(par1GuiButton.id == 0) {
|
||||
cancelRequested = true;
|
||||
par1GuiButton.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,294 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.cookie;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IFramebufferGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformAssets;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.DrawUtils;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.GLSLHeader;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.ImageData;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.VSHInputLayoutParser;
|
||||
import net.minecraft.client.renderer.texture.TextureUtil;
|
||||
|
||||
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
|
||||
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
|
||||
import static net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ExtGLEnums.*;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.Base64;
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom;
|
||||
import net.lax1dude.eaglercraft.v1_8.crypto.GeneralDigest;
|
||||
import net.lax1dude.eaglercraft.v1_8.crypto.SHA256Digest;
|
||||
|
||||
/**
|
||||
* 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 HardwareFingerprint {
|
||||
|
||||
// This is used for generating encryption keys for storing cookies,
|
||||
// its supposed to make session hijacking more difficult for skids
|
||||
|
||||
private static final String fingerprintIMG = "/9j/4AAQSkZJRgABAQEBLAEsAAD//gAKZnVjayBvZmb/4gKwSUNDX1BST0ZJTEUAAQEAAAKgbGNtcwRAAABtbnRyUkdCIFhZWiAH6AAGABAAAgArACNhY3NwTVNGVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWxjbXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1kZXNjAAABIAAAAEBjcHJ0AAABYAAAADZ3dHB0AAABmAAAABRjaGFkAAABrAAAACxyWFlaAAAB2AAAABRiWFlaAAAB7AAAABRnWFlaAAACAAAAABRyVFJDAAACFAAAACBnVFJDAAACFAAAACBiVFJDAAACFAAAACBjaHJtAAACNAAAACRkbW5kAAACWAAAACRkbWRkAAACfAAAACRtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACQAAAAcAEcASQBNAFAAIABiAHUAaQBsAHQALQBpAG4AIABzAFIARwBCbWx1YwAAAAAAAAABAAAADGVuVVMAAAAaAAAAHABQAHUAYgBsAGkAYwAgAEQAbwBtAGEAaQBuAABYWVogAAAAAAAA9tYAAQAAAADTLXNmMzIAAAAAAAEMQgAABd7///MlAAAHkwAA/ZD///uh///9ogAAA9wAAMBuWFlaIAAAAAAAAG+gAAA49QAAA5BYWVogAAAAAAAAJJ8AAA+EAAC2xFhZWiAAAAAAAABilwAAt4cAABjZcGFyYQAAAAAAAwAAAAJmZgAA8qcAAA1ZAAAT0AAACltjaHJtAAAAAAADAAAAAKPXAABUfAAATM0AAJmaAAAmZwAAD1xtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAEcASQBNAFBtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEL/2wBDAAoHBwkHBgoJCAkLCwoMDxkQDw4ODx4WFxIZJCAmJSMgIyIoLTkwKCo2KyIjMkQyNjs9QEBAJjBGS0U+Sjk/QD3/2wBDAQsLCw8NDx0QEB09KSMpPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT3/wgARCACAAIADAREAAhEBAxEB/8QAGwAAAgMBAQEAAAAAAAAAAAAAAQIABAUDBgf/xAAYAQEBAQEBAAAAAAAAAAAAAAAAAQIDBP/aAAwDAQACEAMQAAABx95IwaIRghDRCFCElZ+KQhpghGDRCFCQNEzsUjUQjBDRChCENQJn4pDXfNuSvBBUJYK52Q5ahIZ+KSxLtc9jAcbO8OpA0YENodZpdJWszsUm1z3alHnuBZurO+SA5+PVPTQ7zv0zd1MLpnGzSem49OQIPMeslCpA82ueVj05fcuWdtPCBPW8elGzlRIMFCElOPZoJe0+dx2PR8+mdYoSAFQgFHq3ZsWWa+fxZ01+O6lKgqiWhxRhBQpv6mlXgdS1Loct8kAtcjiWBRxQANHWd+vEw5M67HQghXGO4AEFLms+hrxFhrW49KliDhGAABAALes79eI1CbnHpVshzAQhCEIAmpa3nJCbPHpwsgBRBQBGICrlzd1PN1DW5bSBSgAcxElOpQLo3OtX/8QAJxAAAQQBBAEEAgMAAAAAAAAAAQACAxEQBBITICEUIjAxMkEjNFD/2gAIAQEAAQUC/wBNkZevThcDVwtXC1cAXAuAoxOCMbh2iZyPqsX8HG16lhMXTSMqHAZP6jpI/Y2DVcxCCYA9s8JgfiBtaUq+zm7hHAyLATFqo+TTIeSRUbirVq1uW5bluW4K0FCE/wAilCLmkcirV4tWrVq0HprlD9Y039iQ9JXmMtO5qLqV+MbqWmfuZ+gC4we3UPPnL27mxGkTQaOhWjdhp2Na7cre0h99HsTQT20n5JxtzPzkHksX0rV/BpT7gQcyYpEZvtHbjE8x5PlmT8ELP4ItOGuw3zD3vo32r9f/xAAeEQACAQUAAwAAAAAAAAAAAAAAEQEQIDAxUAIhQP/aAAgBAwEBPwHpoQhCEIQr4qsvjSD2TbEk3Rqr5kb+CN59D7s2RrN//8QAIhEAAQMEAgIDAAAAAAAAAAAAAQACEhARIDEDMBNAIUFQ/9oACAECAQE/Af0ybKSkVIqRU1NSUgrjIm1HuiF5SmulgSAg4UBQN8H050XMiuHA3c5P44fK4zcVBvU7o5odteFqAtg5hBuEZu2mNtUejdfXeAna9B2u/ZRHeEfe33jA77BT/8QAJxAAAQIFAwMFAQAAAAAAAAAAAQARAhAhMDEgQVESImEDUGJxgZH/2gAIAQEABj8C9zosme6yVlUMsamVLVQnzDzoMXNh0zVn0xYKY42M4R+2GK7RoPIrMC6RKD7uvOHTRPZYVUL6umTnW+5TbrurpcZVbHhQ/d6hvngByuuEvyJwnxcPzib8CJNZw3PRg4gf+y//xAAkEAEAAgIBBAIDAQEAAAAAAAABABEQITFBUWFxIIGR8PFQsf/aAAgBAQABPyH/AE39Nd4GbulPd+54X8z9jhK/zHpMWqj8wa1/Xyrenl9QAoUGKcXgwMuFQdx/6oldyOPg7hqsdI6zYXz0qBrFwl/2wF1CXvFKdw5bLfcMh3g29ywwt8SBWWRJaV6wnKc4WhppgIBy6nZwoJ054y0vnrKnqeSB7xXNhc9kKwrXjOMOkdOJK/AKwo5htQdfcXWNvbK1juVGBXYldhV7sLWYuBPTEDZLisKuxC0CfyWOOGAgysrkwFkGMqaGo2zzBjudcb4i71HwzXfZBgRiblS/toGM8GGMeJo64uE47XQR03hBILpNyObZvHXHSAXdENsE8YJu33jKM7M4l4Dg64eIABpTeIibDl65XlB8BcSoy5cOMM3bz+49wcAJq8v6VfJNx1OEvC6uauwL3tBj/9oADAMBAAIAAwAAABD9mRbSTt1t0bIAF+n8iJQX9mluqdyUVE09DAPykEK/iOdbRe8nvNsaLtpZ+CB9RFxmQADt+ChzpmW03P7QNkikzbp/AkyUoZrmRKm2JYrYU5LbJaLJU0pbLQ1Z+klOwjL/xAAeEQEAAgIDAQEBAAAAAAAAAAABABEQICEwMUFAUP/aAAgBAwEBPxD+mJlZWUlZXPaI7C3AXglaVKwhErQcXHALa/CWQVGMSsioYcS2oiQo8i3HDip81qVq5qHpHuWsT1unGHsceIW4ZyS+twtw9jK63R7GeZ+fsDj/xAAfEQEAAgIDAAMBAAAAAAAAAAABABEQISAwMUFQYXH/2gAIAQIBAT8Q+zGL8IrT+IHANyqXP2DYwu8hizh6kW6cKQOBbrC2QNYWr+Mvk1UTQxTWEGpQy7UGAVGyAKOPcKEUahh04uevG+gwW1DlXIxbNHDrIYsJs4dhipUlkoZXWYFE8MJeK6TgdhtqX4cul7PdxbyaXZ4x/8QAJRABAAICAgEEAwADAAAAAAAAAQARITFBUWEQcZGhgbHhwdHw/9oACAEBAAE/EBhCDCEGEGXBhCD6DCEIMIQYQYMGDBhB9CEGDCEGEIMIMNQYegwYTVAtL0TKZ4UEAFjdsNePmS1wj2jHgfiL6Z72lLL9xIJSLqhLcAc5fqG4MuDBiZquXoQIDCA4lXuZ8F9S/iZGJdSw8QggXzHMFjupfG/2OA2aA56fMIMJcZp3wf1+oMd63WI/LNqeSMC9yq1vqaTBxMWXS4ykS/CRRTcE4ekf3GNn/BHMGDmcKrS7yiomtzOywRtvMuubjKtmDTGl52MIthPKAjqXYTiPbtv22fEGZmkB7sxbQUuaKqADe03UvVR52BbYQGDFJOU325g2S35jtRa8wEObK4akp9T3RcfVj+G4QKyH0TwImLaIPZEBLwSagO5YbMQnnXmOKy4WW2ntLn+4sOXwn6ZgTlgVmYxYTuWbLuCByahNMWaIhBT1Oj5i5xfvASx7Z+p0AGTmFsIASbaLfMOXbcJXKHuVcWYsxgBXiFgqY8kuWM0suh49AhbwQiUp8wirdaTATjBHIf1CRqVeuf8AD5Jhihwm2wzQsuHUULmLm10cxwUDiWBGZUdzpxD2g2zyRYDxCZNGOo4gMaE+4pKuLVFMBpzoBddwA5izZ+osHLwRzzFqEIllOf8AcpK2Mrr0VI9MVANBlvzEGSUt6QOUF36AT00Udeg/S3jQx9qH5isgUZobxwlkCVPJi+o4bdR+pcCEhdwgdRYnprC1givIW1+R8So0Sq6vcCVL/wAi+DUo5ihYkuLWiOSkjcMSyxC0AlodEEfALlhHUubF/STqcT//2Q==";
|
||||
|
||||
private static final String shaderPrecision = "precision lowp int;\nprecision mediump float;\nprecision mediump sampler2D;\n";
|
||||
|
||||
private static byte[] fingerprint = null;
|
||||
|
||||
public static final Logger logger = LogManager.getLogger("HardwareFingerprint");
|
||||
|
||||
public static byte[] getFingerprint() {
|
||||
if(fingerprint == null) {
|
||||
try {
|
||||
fingerprint = generateFingerprint();
|
||||
}catch(Throwable t) {
|
||||
fingerprint = new byte[0];
|
||||
}
|
||||
if(fingerprint.length == 0) {
|
||||
logger.error("Failed to calculate hardware fingerprint, server cookies will not be encrypted!");
|
||||
}
|
||||
}
|
||||
return fingerprint;
|
||||
}
|
||||
|
||||
private static byte[] generateFingerprint() {
|
||||
ImageData img = PlatformAssets.loadImageFile(Base64.decodeBase64(fingerprintIMG), "image/jpeg");
|
||||
if(img == null) {
|
||||
logger.error("Input image data is corrupt!");
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
int[][] mipmapLevels = TextureUtil.generateMipmapData(7, 128,
|
||||
new int[][] { img.pixels, null, null, null, null, null, null, null });
|
||||
|
||||
int helperTexture = GlStateManager.generateTexture();
|
||||
GlStateManager.bindTexture(helperTexture);
|
||||
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
TextureUtil.allocateTextureImpl(helperTexture, 7, 128, 128);
|
||||
TextureUtil.uploadTextureMipmap(mipmapLevels, 128, 128, 0, 0, false, false);
|
||||
if(checkAnisotropicFilteringSupport()) {
|
||||
_wglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, 16.0f);
|
||||
}
|
||||
|
||||
IShaderGL vert;
|
||||
List<VSHInputLayoutParser.ShaderInput> vertLayout;
|
||||
if(DrawUtils.vshLocal != null) {
|
||||
vert = DrawUtils.vshLocal;
|
||||
vertLayout = DrawUtils.vshLocalLayout;
|
||||
}else {
|
||||
String vshLocalSrc = EagRuntime.getRequiredResourceString("/assets/eagler/glsl/local.vsh");
|
||||
vertLayout = VSHInputLayoutParser.getShaderInputs(vshLocalSrc);
|
||||
vert = _wglCreateShader(GL_VERTEX_SHADER);
|
||||
_wglShaderSource(vert, GLSLHeader.getVertexHeaderCompat(vshLocalSrc, DrawUtils.vertexShaderPrecision));
|
||||
_wglCompileShader(vert);
|
||||
if(_wglGetShaderi(vert, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
_wglDeleteShader(vert);
|
||||
GlStateManager.deleteTexture(helperTexture);
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
|
||||
IShaderGL frag = _wglCreateShader(GL_FRAGMENT_SHADER);
|
||||
_wglShaderSource(frag, GLSLHeader.getFragmentHeaderCompat(EagRuntime.getRequiredResourceString("/assets/eagler/glsl/hw_fingerprint.fsh"), shaderPrecision));
|
||||
_wglCompileShader(frag);
|
||||
if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
_wglDeleteShader(vert);
|
||||
_wglDeleteShader(frag);
|
||||
GlStateManager.deleteTexture(helperTexture);
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
IProgramGL program = _wglCreateProgram();
|
||||
|
||||
_wglAttachShader(program, vert);
|
||||
_wglAttachShader(program, frag);
|
||||
|
||||
if(EaglercraftGPU.checkOpenGLESVersion() == 200) {
|
||||
VSHInputLayoutParser.applyLayout(program, vertLayout);
|
||||
}
|
||||
|
||||
_wglLinkProgram(program);
|
||||
_wglDetachShader(program, vert);
|
||||
_wglDetachShader(program, frag);
|
||||
if(DrawUtils.vshLocal == null) {
|
||||
_wglDeleteShader(vert);
|
||||
}
|
||||
_wglDeleteShader(frag);
|
||||
|
||||
if(_wglGetProgrami(program, GL_LINK_STATUS) != GL_TRUE) {
|
||||
_wglDeleteProgram(program);
|
||||
GlStateManager.deleteTexture(helperTexture);
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
EaglercraftGPU.bindGLShaderProgram(program);
|
||||
_wglUniform1i(_wglGetUniformLocation(program, "u_inputTexture"), 0);
|
||||
|
||||
float fovy = 90.0f;
|
||||
float aspect = 1.0f;
|
||||
float zNear = 0.01f;
|
||||
float zFar = 100.0f;
|
||||
FloatBuffer matrixUploadBuffer = EagRuntime.allocateFloatBuffer(16);
|
||||
float toRad = 0.0174532925f;
|
||||
float cotangent = (float) Math.cos(fovy * toRad * 0.5f) / (float) Math.sin(fovy * toRad * 0.5f);
|
||||
|
||||
matrixUploadBuffer.put(cotangent / aspect);
|
||||
matrixUploadBuffer.put(0.0f);
|
||||
matrixUploadBuffer.put(0.0f);
|
||||
matrixUploadBuffer.put(0.0f);
|
||||
matrixUploadBuffer.put(0.0f);
|
||||
matrixUploadBuffer.put(cotangent);
|
||||
matrixUploadBuffer.put(0.0f);
|
||||
matrixUploadBuffer.put(0.0f);
|
||||
matrixUploadBuffer.put(0.0f);
|
||||
matrixUploadBuffer.put(0.0f);
|
||||
matrixUploadBuffer.put((zFar + zNear) / (zFar - zNear));
|
||||
matrixUploadBuffer.put(2.0f * zFar * zNear / (zFar - zNear));
|
||||
matrixUploadBuffer.put(0.0f);
|
||||
matrixUploadBuffer.put(0.0f);
|
||||
matrixUploadBuffer.put(-1.0f);
|
||||
matrixUploadBuffer.put(0.0f);
|
||||
|
||||
matrixUploadBuffer.flip();
|
||||
_wglUniformMatrix4fv(_wglGetUniformLocation(program, "u_textureMatrix"), false, matrixUploadBuffer);
|
||||
EagRuntime.freeFloatBuffer(matrixUploadBuffer);
|
||||
|
||||
int[] oldViewport = new int[4];
|
||||
EaglercraftGPU.glGetInteger(GL_VIEWPORT, oldViewport);
|
||||
IFramebufferGL framebuffer = _wglCreateFramebuffer();
|
||||
int renderTexture = GlStateManager.generateTexture();
|
||||
GlStateManager.bindTexture(renderTexture);
|
||||
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
int dataLength;
|
||||
int type;
|
||||
if(EaglercraftGPU.checkHDRFramebufferSupport(32)) {
|
||||
dataLength = 256 * 256 * 4 * 4;
|
||||
type = GL_FLOAT;
|
||||
EaglercraftGPU.createFramebufferHDR32FTexture(GL_TEXTURE_2D, 0, 256, 256, GL_RGBA, false);
|
||||
}else if(EaglercraftGPU.checkHDRFramebufferSupport(16)) {
|
||||
dataLength = 256 * 256 * 4 * 2;
|
||||
type = _GL_HALF_FLOAT;
|
||||
EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, 256, 256, GL_RGBA, false);
|
||||
}else {
|
||||
dataLength = 256 * 256 * 4;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
EaglercraftGPU.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null);
|
||||
}
|
||||
|
||||
_wglBindFramebuffer(_GL_FRAMEBUFFER, framebuffer);
|
||||
_wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(renderTexture), 0);
|
||||
_wglDrawBuffers(_GL_COLOR_ATTACHMENT0);
|
||||
|
||||
GlStateManager.viewport(0, 0, 256, 256);
|
||||
GlStateManager.disableBlend();
|
||||
GlStateManager.bindTexture(helperTexture);
|
||||
|
||||
DrawUtils.drawStandardQuad2D();
|
||||
|
||||
_wglDeleteProgram(program);
|
||||
GlStateManager.deleteTexture(helperTexture);
|
||||
|
||||
ByteBuffer readBuffer = EagRuntime.allocateByteBuffer(dataLength);
|
||||
EaglercraftGPU.glReadPixels(0, 0, 256, 256, GL_RGBA, type, readBuffer);
|
||||
|
||||
_wglBindFramebuffer(_GL_FRAMEBUFFER, null);
|
||||
_wglDeleteFramebuffer(framebuffer);
|
||||
GlStateManager.deleteTexture(renderTexture);
|
||||
GlStateManager.viewport(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
|
||||
|
||||
SHA256Digest digest = new SHA256Digest();
|
||||
byte[] copyBuffer = new byte[1024];
|
||||
|
||||
byte[] b = ("eag" + EaglercraftGPU.glGetString(GL_VENDOR) + "; eag " + EaglercraftGPU.glGetString(GL_RENDERER)).getBytes(StandardCharsets.UTF_8);
|
||||
digest.update(b, 0, b.length);
|
||||
|
||||
digestInts(digest, _wglGetInteger(0x8869), _wglGetInteger(0x8DFB), _wglGetInteger(0x8B4C), _wglGetInteger(0x8DFC), copyBuffer);
|
||||
digestInts(digest, _wglGetInteger(0x8DFD), _wglGetInteger(0x8872), _wglGetInteger(0x84E8), 69, copyBuffer);
|
||||
digestInts(digest, _wglGetInteger(0x0D33), _wglGetInteger(0x851C), _wglGetInteger(0x8B4D), 69, copyBuffer);
|
||||
|
||||
if(EaglercraftGPU.checkOpenGLESVersion() >= 300) {
|
||||
digestInts(digest, _wglGetInteger(0x8B4A), _wglGetInteger(0x8A2B), _wglGetInteger(0x9122), _wglGetInteger(0x8B4B), copyBuffer);
|
||||
digestInts(digest, _wglGetInteger(0x8C8A), _wglGetInteger(0x8C8B), _wglGetInteger(0x8C80), _wglGetInteger(0x8B49), copyBuffer);
|
||||
digestInts(digest, _wglGetInteger(0x8A2D), _wglGetInteger(0x9125), _wglGetInteger(0x8904), _wglGetInteger(0x8905), copyBuffer);
|
||||
digestInts(digest, _wglGetInteger(0x8824), _wglGetInteger(0x8073), _wglGetInteger(0x88FF), _wglGetInteger(0x84FD), copyBuffer);
|
||||
digestInts(digest, _wglGetInteger(0x8CDF), _wglGetInteger(0x8A2F), _wglGetInteger(0x8A30), _wglGetInteger(0x8A34), copyBuffer);
|
||||
digestInts(digest, _wglGetInteger(0x8A2E), _wglGetInteger(0x8A31), _wglGetInteger(0x8A33), _wglGetInteger(0x8D57), copyBuffer);
|
||||
}
|
||||
|
||||
try {
|
||||
List<String> exts = Lists.newArrayList(getAllExtensions());
|
||||
Collections.sort(exts);
|
||||
EaglercraftRandom rand = new EaglercraftRandom(6942069420l + exts.size() * 69l + b.length);
|
||||
for (int i = exts.size() - 1; i > 0; --i) {
|
||||
int j = rand.nextInt(i + 1);
|
||||
Collections.swap(exts, i, j);
|
||||
}
|
||||
b = String.join(":>", exts).getBytes(StandardCharsets.UTF_8);
|
||||
digest.update(b, 0, b.length);
|
||||
}catch(Throwable t) {
|
||||
}
|
||||
|
||||
int i;
|
||||
while(readBuffer.hasRemaining()) {
|
||||
i = Math.min(readBuffer.remaining(), copyBuffer.length);
|
||||
readBuffer.get(copyBuffer, 0, i);
|
||||
digest.update(copyBuffer, 0, i);
|
||||
}
|
||||
|
||||
EagRuntime.freeByteBuffer(readBuffer);
|
||||
|
||||
byte[] hashOut = new byte[32];
|
||||
digest.doFinal(hashOut, 0);
|
||||
|
||||
return hashOut;
|
||||
}
|
||||
|
||||
private static void digestInts(GeneralDigest digest, int i1, int i2, int i3, int i4, byte[] tmpBuffer) {
|
||||
tmpBuffer[0] = (byte)(i1 >>> 24);
|
||||
tmpBuffer[1] = (byte)(i1 >>> 16);
|
||||
tmpBuffer[2] = (byte)(i1 >>> 8);
|
||||
tmpBuffer[3] = (byte)(i1 & 0xFF);
|
||||
tmpBuffer[4] = (byte)(i2 >>> 24);
|
||||
tmpBuffer[5] = (byte)(i2 >>> 16);
|
||||
tmpBuffer[6] = (byte)(i2 >>> 8);
|
||||
tmpBuffer[7] = (byte)(i2 & 0xFF);
|
||||
tmpBuffer[8] = (byte)(i3 >>> 24);
|
||||
tmpBuffer[9] = (byte)(i3 >>> 16);
|
||||
tmpBuffer[10] = (byte)(i3 >>> 8);
|
||||
tmpBuffer[11] = (byte)(i3 & 0xFF);
|
||||
tmpBuffer[12] = (byte)(i4 >>> 24);
|
||||
tmpBuffer[13] = (byte)(i4 >>> 16);
|
||||
tmpBuffer[14] = (byte)(i4 >>> 8);
|
||||
tmpBuffer[15] = (byte)(i4 & 0xFF);
|
||||
digest.update(tmpBuffer, 0, 16);
|
||||
}
|
||||
}
|
@ -0,0 +1,396 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.cookie;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.EaglerInputStream;
|
||||
import net.lax1dude.eaglercraft.v1_8.EaglerOutputStream;
|
||||
import net.lax1dude.eaglercraft.v1_8.EaglerZLIB;
|
||||
import net.lax1dude.eaglercraft.v1_8.crypto.AESLightEngine;
|
||||
import net.lax1dude.eaglercraft.v1_8.crypto.SHA1Digest;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformApplication;
|
||||
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 ServerCookieDataStore {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger("ServerCookieDataStore");
|
||||
|
||||
private static final Map<String,ServerCookie> dataStore = new HashMap<>();
|
||||
|
||||
public static final String localStorageKey = "c";
|
||||
|
||||
public static class ServerCookie {
|
||||
|
||||
public final String server;
|
||||
public final byte[] cookie;
|
||||
public final long expires;
|
||||
public final boolean revokeQuerySupported;
|
||||
public final boolean saveCookieToDisk;
|
||||
|
||||
public ServerCookie(String server, byte[] cookie, long expires, boolean revokeQuerySupported, boolean saveCookieToDisk) {
|
||||
this.server = server;
|
||||
this.cookie = cookie;
|
||||
this.expires = expires;
|
||||
this.revokeQuerySupported = revokeQuerySupported;
|
||||
this.saveCookieToDisk = saveCookieToDisk;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
if(EagRuntime.getConfiguration().isEnableServerCookies()) {
|
||||
loadData(HardwareFingerprint.getFingerprint());
|
||||
}
|
||||
}
|
||||
|
||||
public static ServerCookie loadCookie(String server) {
|
||||
if(!EagRuntime.getConfiguration().isEnableServerCookies()) {
|
||||
return null;
|
||||
}
|
||||
server = normalize(server);
|
||||
ServerCookie cookie = dataStore.get(server);
|
||||
if(cookie == null) {
|
||||
return null;
|
||||
}
|
||||
long timestamp = System.currentTimeMillis();
|
||||
if(timestamp > cookie.expires) {
|
||||
dataStore.remove(server);
|
||||
saveData(HardwareFingerprint.getFingerprint());
|
||||
return null;
|
||||
}
|
||||
return cookie;
|
||||
}
|
||||
|
||||
public static void saveCookie(String server, long expires, byte[] data, boolean revokeQuerySupported, boolean saveCookieToDisk) {
|
||||
if(!EagRuntime.getConfiguration().isEnableServerCookies()) {
|
||||
return;
|
||||
}
|
||||
server = normalize(server);
|
||||
if(expires > 604800l) {
|
||||
clearCookie(server);
|
||||
logger.error("Server \"{}\" tried to set a cookie for {} days! (The max is 7 days)", server, (expires / 604800l));
|
||||
return;
|
||||
}
|
||||
if(data.length > 255) {
|
||||
clearCookie(server);
|
||||
logger.error("Server \"{}\" tried to set a {} byte cookie! (The max length is 255 bytes)", server, data.length);
|
||||
return;
|
||||
}
|
||||
if(expires < 0l || data.length == 0) {
|
||||
clearCookie(server);
|
||||
return;
|
||||
}
|
||||
long expiresRelative = System.currentTimeMillis() + expires * 1000l;
|
||||
dataStore.put(server, new ServerCookie(server, data, expiresRelative, revokeQuerySupported, saveCookieToDisk));
|
||||
saveData(HardwareFingerprint.getFingerprint());
|
||||
}
|
||||
|
||||
public static void clearCookie(String server) {
|
||||
if(!EagRuntime.getConfiguration().isEnableServerCookies()) {
|
||||
return;
|
||||
}
|
||||
if(dataStore.remove(normalize(server)) != null) {
|
||||
saveData(HardwareFingerprint.getFingerprint());
|
||||
}
|
||||
}
|
||||
|
||||
public static void clearCookiesLow() {
|
||||
dataStore.clear();
|
||||
}
|
||||
|
||||
private static String normalize(String server) {
|
||||
int j = server.indexOf('/');
|
||||
if(j != -1) {
|
||||
int i = server.indexOf("://");
|
||||
if(i != -1) {
|
||||
j = server.indexOf('/', i + 3);
|
||||
if(j == -1) {
|
||||
return server.toLowerCase();
|
||||
}else {
|
||||
return server.substring(0, j).toLowerCase() + server.substring(j);
|
||||
}
|
||||
}else {
|
||||
return server.substring(0, j).toLowerCase() + server.substring(j);
|
||||
}
|
||||
}else {
|
||||
return server.toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getAllServers() {
|
||||
return dataStore.keySet();
|
||||
}
|
||||
|
||||
public static List<String> getRevokableServers() {
|
||||
List<String> ret = new ArrayList<>(dataStore.size());
|
||||
for(ServerCookie c : dataStore.values()) {
|
||||
if(c.revokeQuerySupported) {
|
||||
ret.add(c.server);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int size() {
|
||||
return dataStore.size();
|
||||
}
|
||||
|
||||
public static int numRevokable() {
|
||||
int i = 0;
|
||||
for(ServerCookie c : dataStore.values()) {
|
||||
if(c.revokeQuerySupported) {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public static void flush() {
|
||||
Iterator<ServerCookie> itr = dataStore.values().iterator();
|
||||
boolean changed = false;
|
||||
while(itr.hasNext()) {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
ServerCookie cookie = itr.next();
|
||||
if(timestamp > cookie.expires) {
|
||||
itr.remove();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if(changed) {
|
||||
saveData(HardwareFingerprint.getFingerprint());
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadData(byte[] key) {
|
||||
dataStore.clear();
|
||||
byte[] cookiesTag = PlatformApplication.getLocalStorage(localStorageKey, false);
|
||||
if(cookiesTag == null) {
|
||||
return;
|
||||
}
|
||||
if(cookiesTag.length <= 25) {
|
||||
PlatformApplication.setLocalStorage(localStorageKey, null, false);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
byte[] decrypted;
|
||||
int decryptedLen;
|
||||
switch(cookiesTag[0]) {
|
||||
case 2:
|
||||
if(key == null || key.length == 0) {
|
||||
throw new IOException("Data is encrypted!");
|
||||
}
|
||||
decrypted = new byte[cookiesTag.length - 5];
|
||||
decryptedLen = (cookiesTag[1] << 24) | (cookiesTag[2] << 16) | (cookiesTag[3] << 8) | (cookiesTag[4] & 0xFF);
|
||||
if(decryptedLen < 25) {
|
||||
throw new IOException("too short!");
|
||||
}
|
||||
AESLightEngine aes = new AESLightEngine();
|
||||
aes.init(false, key);
|
||||
int bs = aes.getBlockSize();
|
||||
if(decrypted.length % bs != 0) {
|
||||
throw new IOException("length not aligned to block size!");
|
||||
}
|
||||
byte[] cbcHelper = new byte[] { (byte) 29, (byte) 163, (byte) 4, (byte) 20, (byte) 207, (byte) 26,
|
||||
(byte) 140, (byte) 55, (byte) 246, (byte) 250, (byte) 141, (byte) 183, (byte) 153, (byte) 154,
|
||||
(byte) 59, (byte) 4 };
|
||||
for(int i = 0; i < decryptedLen; i += bs) {
|
||||
processBlockDecryptHelper(aes, cookiesTag, 5 + i, decrypted, i, bs, Math.min(decryptedLen - i, bs), cbcHelper);
|
||||
}
|
||||
if(decrypted[0] != (byte)0x69) {
|
||||
throw new IOException("Data is corrupt!");
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if(key != null && key.length > 0) {
|
||||
throw new IOException("Data isn't encrypted!");
|
||||
}
|
||||
decrypted = cookiesTag;
|
||||
decryptedLen = cookiesTag.length;
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Unknown type!");
|
||||
}
|
||||
SHA1Digest digest = new SHA1Digest();
|
||||
digest.update(decrypted, 25, decryptedLen - 25);
|
||||
byte[] digestOut = new byte[20];
|
||||
digest.doFinal(digestOut, 0);
|
||||
for(int i = 0; i < 20; ++i) {
|
||||
if(digestOut[i] != decrypted[5 + i]) {
|
||||
throw new IOException("Invalid checksum!");
|
||||
}
|
||||
}
|
||||
int decompressedLen = (decrypted[1] << 24) | (decrypted[2] << 16) | (decrypted[3] << 8) | (decrypted[4] & 0xFF);
|
||||
byte[] decompressed = new byte[decompressedLen];
|
||||
try (InputStream zstream = EaglerZLIB.newInflaterInputStream(new EaglerInputStream(decrypted, 25, decryptedLen - 25))) {
|
||||
int i = 0, j;
|
||||
while(i < decompressedLen && (j = zstream.read(decompressed, i, decompressedLen - i)) != -1) {
|
||||
i += j;
|
||||
}
|
||||
if(i != decompressedLen) {
|
||||
throw new IOException("Length does not match!");
|
||||
}
|
||||
}
|
||||
DataInputStream dis = new DataInputStream(new EaglerInputStream(decompressed));
|
||||
int readCount = dis.readInt();
|
||||
long time = System.currentTimeMillis();
|
||||
for(int i = 0; i < readCount; ++i) {
|
||||
byte flags = dis.readByte();
|
||||
long expires = dis.readLong();
|
||||
int len = dis.readUnsignedShort();
|
||||
String server = dis.readUTF();
|
||||
if(len == 0) {
|
||||
continue;
|
||||
}
|
||||
if(expires < time) {
|
||||
dis.skipBytes(len);
|
||||
continue;
|
||||
}
|
||||
byte[] cookieData = new byte[len];
|
||||
dis.readFully(cookieData);
|
||||
server = normalize(server);
|
||||
dataStore.put(server, new ServerCookie(server, cookieData, expires, (flags & 1) != 0, (flags & 2) != 0));
|
||||
}
|
||||
if(dis.available() > 0) {
|
||||
throw new IOException("Extra bytes remaining!");
|
||||
}
|
||||
}catch (IOException e) {
|
||||
dataStore.clear();
|
||||
PlatformApplication.setLocalStorage(localStorageKey, null, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private static void saveData(byte[] key) {
|
||||
Iterator<ServerCookie> itr = dataStore.values().iterator();
|
||||
List<ServerCookie> toSave = new ArrayList<>(dataStore.size());
|
||||
while(itr.hasNext()) {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
ServerCookie cookie = itr.next();
|
||||
if(timestamp > cookie.expires || cookie.cookie.length > 255 || cookie.cookie.length == 0) {
|
||||
itr.remove();
|
||||
}else if(cookie.saveCookieToDisk) {
|
||||
toSave.add(cookie);
|
||||
}
|
||||
}
|
||||
if(toSave.size() == 0) {
|
||||
PlatformApplication.setLocalStorage(localStorageKey, null, false);
|
||||
}else {
|
||||
EaglerOutputStream bao = new EaglerOutputStream(1024);
|
||||
bao.skipBytes(25);
|
||||
int totalUncompressedLen;
|
||||
try(DataOutputStream zstream = new DataOutputStream(EaglerZLIB.newDeflaterOutputStream(bao))) {
|
||||
zstream.writeInt(dataStore.size());
|
||||
for(Entry<String,ServerCookie> etr : dataStore.entrySet()) {
|
||||
ServerCookie cookie = etr.getValue();
|
||||
zstream.writeByte((cookie.revokeQuerySupported ? 1 : 0) | (cookie.saveCookieToDisk ? 2 : 0));
|
||||
zstream.writeLong(cookie.expires);
|
||||
zstream.writeShort(cookie.cookie.length);
|
||||
zstream.writeUTF(etr.getKey());
|
||||
zstream.write(cookie.cookie);
|
||||
}
|
||||
totalUncompressedLen = zstream.size();
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to write cookies to local storage!");
|
||||
return;
|
||||
}
|
||||
byte[] toEncrypt = bao.toByteArray();
|
||||
SHA1Digest hash = new SHA1Digest();
|
||||
hash.update(toEncrypt, 25, toEncrypt.length - 25);
|
||||
hash.doFinal(toEncrypt, 5);
|
||||
toEncrypt[1] = (byte)(totalUncompressedLen >>> 24);
|
||||
toEncrypt[2] = (byte)(totalUncompressedLen >>> 16);
|
||||
toEncrypt[3] = (byte)(totalUncompressedLen >>> 8);
|
||||
toEncrypt[4] = (byte)(totalUncompressedLen & 0xFF);
|
||||
if(key != null && key.length > 0) {
|
||||
toEncrypt[0] = (byte)0x69;
|
||||
AESLightEngine aes = new AESLightEngine();
|
||||
aes.init(true, key);
|
||||
int bs = aes.getBlockSize();
|
||||
int blockCount = (toEncrypt.length % bs) != 0 ? (toEncrypt.length / bs + 1) : (toEncrypt.length / bs);
|
||||
byte[] encrypted = new byte[blockCount * bs + 5];
|
||||
encrypted[0] = (byte)2;
|
||||
encrypted[1] = (byte)(toEncrypt.length >>> 24);
|
||||
encrypted[2] = (byte)(toEncrypt.length >>> 16);
|
||||
encrypted[3] = (byte)(toEncrypt.length >>> 8);
|
||||
encrypted[4] = (byte)(toEncrypt.length & 0xFF);
|
||||
byte[] cbcHelper = new byte[] { (byte) 29, (byte) 163, (byte) 4, (byte) 20, (byte) 207, (byte) 26,
|
||||
(byte) 140, (byte) 55, (byte) 246, (byte) 250, (byte) 141, (byte) 183, (byte) 153, (byte) 154,
|
||||
(byte) 59, (byte) 4 };
|
||||
for(int i = 0; i < toEncrypt.length; i += bs) {
|
||||
processBlockEncryptHelper(aes, toEncrypt, i, encrypted, 5 + i, bs, cbcHelper);
|
||||
}
|
||||
PlatformApplication.setLocalStorage(localStorageKey, encrypted, false);
|
||||
}else {
|
||||
toEncrypt[0] = (byte)1;
|
||||
PlatformApplication.setLocalStorage(localStorageKey, toEncrypt, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void processBlockEncryptHelper(AESLightEngine aes, byte[] in, int inOff, byte[] out, int outOff,
|
||||
int len, byte[] cbcHelper) {
|
||||
int clampedBlockLength = Math.min(in.length - inOff, len);
|
||||
if(clampedBlockLength == len) {
|
||||
for(int i = 0; i < len; ++i) {
|
||||
in[i + inOff] ^= cbcHelper[i];
|
||||
}
|
||||
aes.processBlock(in, inOff, out, outOff);
|
||||
System.arraycopy(out, outOff, cbcHelper, 0, len);
|
||||
}else {
|
||||
byte[] paddedBlock = new byte[len];
|
||||
System.arraycopy(in, inOff, paddedBlock, 0, clampedBlockLength);
|
||||
byte padValue = (byte)(len - clampedBlockLength);
|
||||
for(byte i = 0; i < padValue; ++i) {
|
||||
paddedBlock[clampedBlockLength + i] = padValue;
|
||||
}
|
||||
for(int i = 0; i < len; ++i) {
|
||||
paddedBlock[i] ^= cbcHelper[i];
|
||||
}
|
||||
aes.processBlock(paddedBlock, 0, out, outOff);
|
||||
}
|
||||
}
|
||||
|
||||
private static void processBlockDecryptHelper(AESLightEngine aes, byte[] in, int inOff, byte[] out, int outOff,
|
||||
int paddedLen, int unpaddedLen, byte[] cbcHelper) throws IOException {
|
||||
aes.processBlock(in, inOff, out, outOff);
|
||||
for(int i = 0; i < paddedLen; ++i) {
|
||||
out[i + outOff] ^= cbcHelper[i];
|
||||
}
|
||||
if(unpaddedLen == paddedLen) {
|
||||
System.arraycopy(in, inOff, cbcHelper, 0, paddedLen);
|
||||
}else {
|
||||
byte padValue = (byte)(paddedLen - unpaddedLen);
|
||||
for(byte i = 0; i < padValue; ++i) {
|
||||
if(out[outOff + unpaddedLen + i] != padValue) {
|
||||
throw new IOException("Invalid padding!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,527 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2021 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package net.lax1dude.eaglercraft.v1_8.crypto;
|
||||
|
||||
/**
|
||||
* an implementation of the AES (Rijndael), from FIPS-197.
|
||||
* <p>
|
||||
* For further details see: <a href="https://csrc.nist.gov/encryption/aes/">https://csrc.nist.gov/encryption/aes/</a>.
|
||||
*
|
||||
* This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
|
||||
* <a href="https://fp.gladman.plus.com/cryptography_technology/rijndael/">https://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
|
||||
*
|
||||
* There are three levels of tradeoff of speed vs memory
|
||||
* Because java has no preprocessor, they are written as three separate classes from which to choose
|
||||
*
|
||||
* The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
|
||||
* and 4 for decryption.
|
||||
*
|
||||
* The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
|
||||
* adding 12 rotate operations per round to compute the values contained in the other tables from
|
||||
* the contents of the first
|
||||
*
|
||||
* The slowest version uses no static tables at all and computes the values
|
||||
* in each round.
|
||||
* <p>
|
||||
* This file contains the slowest performance version with no static tables
|
||||
* for round precomputation, but it has the smallest foot print.
|
||||
*
|
||||
*/
|
||||
public class AESLightEngine {
|
||||
// The S box
|
||||
private static final byte[] S = { (byte) 99, (byte) 124, (byte) 119, (byte) 123, (byte) 242, (byte) 107, (byte) 111,
|
||||
(byte) 197, (byte) 48, (byte) 1, (byte) 103, (byte) 43, (byte) 254, (byte) 215, (byte) 171, (byte) 118,
|
||||
(byte) 202, (byte) 130, (byte) 201, (byte) 125, (byte) 250, (byte) 89, (byte) 71, (byte) 240, (byte) 173,
|
||||
(byte) 212, (byte) 162, (byte) 175, (byte) 156, (byte) 164, (byte) 114, (byte) 192, (byte) 183, (byte) 253,
|
||||
(byte) 147, (byte) 38, (byte) 54, (byte) 63, (byte) 247, (byte) 204, (byte) 52, (byte) 165, (byte) 229,
|
||||
(byte) 241, (byte) 113, (byte) 216, (byte) 49, (byte) 21, (byte) 4, (byte) 199, (byte) 35, (byte) 195,
|
||||
(byte) 24, (byte) 150, (byte) 5, (byte) 154, (byte) 7, (byte) 18, (byte) 128, (byte) 226, (byte) 235,
|
||||
(byte) 39, (byte) 178, (byte) 117, (byte) 9, (byte) 131, (byte) 44, (byte) 26, (byte) 27, (byte) 110,
|
||||
(byte) 90, (byte) 160, (byte) 82, (byte) 59, (byte) 214, (byte) 179, (byte) 41, (byte) 227, (byte) 47,
|
||||
(byte) 132, (byte) 83, (byte) 209, (byte) 0, (byte) 237, (byte) 32, (byte) 252, (byte) 177, (byte) 91,
|
||||
(byte) 106, (byte) 203, (byte) 190, (byte) 57, (byte) 74, (byte) 76, (byte) 88, (byte) 207, (byte) 208,
|
||||
(byte) 239, (byte) 170, (byte) 251, (byte) 67, (byte) 77, (byte) 51, (byte) 133, (byte) 69, (byte) 249,
|
||||
(byte) 2, (byte) 127, (byte) 80, (byte) 60, (byte) 159, (byte) 168, (byte) 81, (byte) 163, (byte) 64,
|
||||
(byte) 143, (byte) 146, (byte) 157, (byte) 56, (byte) 245, (byte) 188, (byte) 182, (byte) 218, (byte) 33,
|
||||
(byte) 16, (byte) 255, (byte) 243, (byte) 210, (byte) 205, (byte) 12, (byte) 19, (byte) 236, (byte) 95,
|
||||
(byte) 151, (byte) 68, (byte) 23, (byte) 196, (byte) 167, (byte) 126, (byte) 61, (byte) 100, (byte) 93,
|
||||
(byte) 25, (byte) 115, (byte) 96, (byte) 129, (byte) 79, (byte) 220, (byte) 34, (byte) 42, (byte) 144,
|
||||
(byte) 136, (byte) 70, (byte) 238, (byte) 184, (byte) 20, (byte) 222, (byte) 94, (byte) 11, (byte) 219,
|
||||
(byte) 224, (byte) 50, (byte) 58, (byte) 10, (byte) 73, (byte) 6, (byte) 36, (byte) 92, (byte) 194,
|
||||
(byte) 211, (byte) 172, (byte) 98, (byte) 145, (byte) 149, (byte) 228, (byte) 121, (byte) 231, (byte) 200,
|
||||
(byte) 55, (byte) 109, (byte) 141, (byte) 213, (byte) 78, (byte) 169, (byte) 108, (byte) 86, (byte) 244,
|
||||
(byte) 234, (byte) 101, (byte) 122, (byte) 174, (byte) 8, (byte) 186, (byte) 120, (byte) 37, (byte) 46,
|
||||
(byte) 28, (byte) 166, (byte) 180, (byte) 198, (byte) 232, (byte) 221, (byte) 116, (byte) 31, (byte) 75,
|
||||
(byte) 189, (byte) 139, (byte) 138, (byte) 112, (byte) 62, (byte) 181, (byte) 102, (byte) 72, (byte) 3,
|
||||
(byte) 246, (byte) 14, (byte) 97, (byte) 53, (byte) 87, (byte) 185, (byte) 134, (byte) 193, (byte) 29,
|
||||
(byte) 158, (byte) 225, (byte) 248, (byte) 152, (byte) 17, (byte) 105, (byte) 217, (byte) 142, (byte) 148,
|
||||
(byte) 155, (byte) 30, (byte) 135, (byte) 233, (byte) 206, (byte) 85, (byte) 40, (byte) 223, (byte) 140,
|
||||
(byte) 161, (byte) 137, (byte) 13, (byte) 191, (byte) 230, (byte) 66, (byte) 104, (byte) 65, (byte) 153,
|
||||
(byte) 45, (byte) 15, (byte) 176, (byte) 84, (byte) 187, (byte) 22, };
|
||||
|
||||
// The inverse S-box
|
||||
private static final byte[] Si = { (byte) 82, (byte) 9, (byte) 106, (byte) 213, (byte) 48, (byte) 54, (byte) 165,
|
||||
(byte) 56, (byte) 191, (byte) 64, (byte) 163, (byte) 158, (byte) 129, (byte) 243, (byte) 215, (byte) 251,
|
||||
(byte) 124, (byte) 227, (byte) 57, (byte) 130, (byte) 155, (byte) 47, (byte) 255, (byte) 135, (byte) 52,
|
||||
(byte) 142, (byte) 67, (byte) 68, (byte) 196, (byte) 222, (byte) 233, (byte) 203, (byte) 84, (byte) 123,
|
||||
(byte) 148, (byte) 50, (byte) 166, (byte) 194, (byte) 35, (byte) 61, (byte) 238, (byte) 76, (byte) 149,
|
||||
(byte) 11, (byte) 66, (byte) 250, (byte) 195, (byte) 78, (byte) 8, (byte) 46, (byte) 161, (byte) 102,
|
||||
(byte) 40, (byte) 217, (byte) 36, (byte) 178, (byte) 118, (byte) 91, (byte) 162, (byte) 73, (byte) 109,
|
||||
(byte) 139, (byte) 209, (byte) 37, (byte) 114, (byte) 248, (byte) 246, (byte) 100, (byte) 134, (byte) 104,
|
||||
(byte) 152, (byte) 22, (byte) 212, (byte) 164, (byte) 92, (byte) 204, (byte) 93, (byte) 101, (byte) 182,
|
||||
(byte) 146, (byte) 108, (byte) 112, (byte) 72, (byte) 80, (byte) 253, (byte) 237, (byte) 185, (byte) 218,
|
||||
(byte) 94, (byte) 21, (byte) 70, (byte) 87, (byte) 167, (byte) 141, (byte) 157, (byte) 132, (byte) 144,
|
||||
(byte) 216, (byte) 171, (byte) 0, (byte) 140, (byte) 188, (byte) 211, (byte) 10, (byte) 247, (byte) 228,
|
||||
(byte) 88, (byte) 5, (byte) 184, (byte) 179, (byte) 69, (byte) 6, (byte) 208, (byte) 44, (byte) 30,
|
||||
(byte) 143, (byte) 202, (byte) 63, (byte) 15, (byte) 2, (byte) 193, (byte) 175, (byte) 189, (byte) 3,
|
||||
(byte) 1, (byte) 19, (byte) 138, (byte) 107, (byte) 58, (byte) 145, (byte) 17, (byte) 65, (byte) 79,
|
||||
(byte) 103, (byte) 220, (byte) 234, (byte) 151, (byte) 242, (byte) 207, (byte) 206, (byte) 240, (byte) 180,
|
||||
(byte) 230, (byte) 115, (byte) 150, (byte) 172, (byte) 116, (byte) 34, (byte) 231, (byte) 173, (byte) 53,
|
||||
(byte) 133, (byte) 226, (byte) 249, (byte) 55, (byte) 232, (byte) 28, (byte) 117, (byte) 223, (byte) 110,
|
||||
(byte) 71, (byte) 241, (byte) 26, (byte) 113, (byte) 29, (byte) 41, (byte) 197, (byte) 137, (byte) 111,
|
||||
(byte) 183, (byte) 98, (byte) 14, (byte) 170, (byte) 24, (byte) 190, (byte) 27, (byte) 252, (byte) 86,
|
||||
(byte) 62, (byte) 75, (byte) 198, (byte) 210, (byte) 121, (byte) 32, (byte) 154, (byte) 219, (byte) 192,
|
||||
(byte) 254, (byte) 120, (byte) 205, (byte) 90, (byte) 244, (byte) 31, (byte) 221, (byte) 168, (byte) 51,
|
||||
(byte) 136, (byte) 7, (byte) 199, (byte) 49, (byte) 177, (byte) 18, (byte) 16, (byte) 89, (byte) 39,
|
||||
(byte) 128, (byte) 236, (byte) 95, (byte) 96, (byte) 81, (byte) 127, (byte) 169, (byte) 25, (byte) 181,
|
||||
(byte) 74, (byte) 13, (byte) 45, (byte) 229, (byte) 122, (byte) 159, (byte) 147, (byte) 201, (byte) 156,
|
||||
(byte) 239, (byte) 160, (byte) 224, (byte) 59, (byte) 77, (byte) 174, (byte) 42, (byte) 245, (byte) 176,
|
||||
(byte) 200, (byte) 235, (byte) 187, (byte) 60, (byte) 131, (byte) 83, (byte) 153, (byte) 97, (byte) 23,
|
||||
(byte) 43, (byte) 4, (byte) 126, (byte) 186, (byte) 119, (byte) 214, (byte) 38, (byte) 225, (byte) 105,
|
||||
(byte) 20, (byte) 99, (byte) 85, (byte) 33, (byte) 12, (byte) 125, };
|
||||
|
||||
// vector used in calculating key schedule (powers of x in GF(256))
|
||||
private static final int[] rcon = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab,
|
||||
0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
|
||||
|
||||
private static int shift(int r, int shift) {
|
||||
return (r >>> shift) | (r << -shift);
|
||||
}
|
||||
|
||||
/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
|
||||
|
||||
private static final int m1 = 0x80808080;
|
||||
private static final int m2 = 0x7f7f7f7f;
|
||||
private static final int m3 = 0x0000001b;
|
||||
private static final int m4 = 0xC0C0C0C0;
|
||||
private static final int m5 = 0x3f3f3f3f;
|
||||
|
||||
private static int FFmulX(int x) {
|
||||
return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
|
||||
}
|
||||
|
||||
private static int FFmulX2(int x) {
|
||||
int t0 = (x & m5) << 2;
|
||||
int t1 = (x & m4);
|
||||
t1 ^= (t1 >>> 1);
|
||||
return t0 ^ (t1 >>> 2) ^ (t1 >>> 5);
|
||||
}
|
||||
|
||||
/*
|
||||
The following defines provide alternative definitions of FFmulX that might
|
||||
give improved performance if a fast 32-bit multiply is not available.
|
||||
|
||||
private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
|
||||
private static final int m4 = 0x1b1b1b1b;
|
||||
private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
|
||||
|
||||
*/
|
||||
|
||||
private static int mcol(int x) {
|
||||
int t0, t1;
|
||||
t0 = shift(x, 8);
|
||||
t1 = x ^ t0;
|
||||
return shift(t1, 16) ^ t0 ^ FFmulX(t1);
|
||||
}
|
||||
|
||||
private static int inv_mcol(int x) {
|
||||
int t0, t1;
|
||||
t0 = x;
|
||||
t1 = t0 ^ shift(t0, 8);
|
||||
t0 ^= FFmulX(t1);
|
||||
t1 ^= FFmulX2(t0);
|
||||
t0 ^= t1 ^ shift(t1, 16);
|
||||
return t0;
|
||||
}
|
||||
|
||||
private static int subWord(int x) {
|
||||
return (S[x & 255] & 255 | ((S[(x >> 8) & 255] & 255) << 8) | ((S[(x >> 16) & 255] & 255) << 16)
|
||||
| S[(x >> 24) & 255] << 24);
|
||||
}
|
||||
|
||||
private static int littleEndianToInt(byte[] bs, int off) {
|
||||
int n = bs[off] & 0xff;
|
||||
n |= (bs[++off] & 0xff) << 8;
|
||||
n |= (bs[++off] & 0xff) << 16;
|
||||
n |= bs[++off] << 24;
|
||||
return n;
|
||||
}
|
||||
|
||||
public static void intToLittleEndian(int n, byte[] bs, int off) {
|
||||
bs[off] = (byte) (n);
|
||||
bs[++off] = (byte) (n >>> 8);
|
||||
bs[++off] = (byte) (n >>> 16);
|
||||
bs[++off] = (byte) (n >>> 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the necessary round keys
|
||||
* The number of calculations depends on key size and block size
|
||||
* AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
|
||||
* This code is written assuming those are the only possible values
|
||||
*/
|
||||
private int[][] generateWorkingKey(byte[] key, boolean forEncryption) {
|
||||
int keyLen = key.length;
|
||||
if (keyLen < 16 || keyLen > 32 || (keyLen & 7) != 0) {
|
||||
throw new IllegalArgumentException("Key length not 128/192/256 bits.");
|
||||
}
|
||||
|
||||
int KC = keyLen >>> 2;
|
||||
ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block
|
||||
// sizes
|
||||
int[][] W = new int[ROUNDS + 1][4]; // 4 words in a block
|
||||
|
||||
switch (KC) {
|
||||
case 4: {
|
||||
int col0 = littleEndianToInt(key, 0);
|
||||
W[0][0] = col0;
|
||||
int col1 = littleEndianToInt(key, 4);
|
||||
W[0][1] = col1;
|
||||
int col2 = littleEndianToInt(key, 8);
|
||||
W[0][2] = col2;
|
||||
int col3 = littleEndianToInt(key, 12);
|
||||
W[0][3] = col3;
|
||||
|
||||
for (int i = 1; i <= 10; ++i) {
|
||||
int colx = subWord(shift(col3, 8)) ^ rcon[i - 1];
|
||||
col0 ^= colx;
|
||||
W[i][0] = col0;
|
||||
col1 ^= col0;
|
||||
W[i][1] = col1;
|
||||
col2 ^= col1;
|
||||
W[i][2] = col2;
|
||||
col3 ^= col2;
|
||||
W[i][3] = col3;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
int col0 = littleEndianToInt(key, 0);
|
||||
W[0][0] = col0;
|
||||
int col1 = littleEndianToInt(key, 4);
|
||||
W[0][1] = col1;
|
||||
int col2 = littleEndianToInt(key, 8);
|
||||
W[0][2] = col2;
|
||||
int col3 = littleEndianToInt(key, 12);
|
||||
W[0][3] = col3;
|
||||
|
||||
int col4 = littleEndianToInt(key, 16);
|
||||
int col5 = littleEndianToInt(key, 20);
|
||||
|
||||
int i = 1, rcon = 1, colx;
|
||||
for (;;) {
|
||||
W[i][0] = col4;
|
||||
W[i][1] = col5;
|
||||
colx = subWord(shift(col5, 8)) ^ rcon;
|
||||
rcon <<= 1;
|
||||
col0 ^= colx;
|
||||
W[i][2] = col0;
|
||||
col1 ^= col0;
|
||||
W[i][3] = col1;
|
||||
|
||||
col2 ^= col1;
|
||||
W[i + 1][0] = col2;
|
||||
col3 ^= col2;
|
||||
W[i + 1][1] = col3;
|
||||
col4 ^= col3;
|
||||
W[i + 1][2] = col4;
|
||||
col5 ^= col4;
|
||||
W[i + 1][3] = col5;
|
||||
|
||||
colx = subWord(shift(col5, 8)) ^ rcon;
|
||||
rcon <<= 1;
|
||||
col0 ^= colx;
|
||||
W[i + 2][0] = col0;
|
||||
col1 ^= col0;
|
||||
W[i + 2][1] = col1;
|
||||
col2 ^= col1;
|
||||
W[i + 2][2] = col2;
|
||||
col3 ^= col2;
|
||||
W[i + 2][3] = col3;
|
||||
|
||||
if ((i += 3) >= 13) {
|
||||
break;
|
||||
}
|
||||
|
||||
col4 ^= col3;
|
||||
col5 ^= col4;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
int col0 = littleEndianToInt(key, 0);
|
||||
W[0][0] = col0;
|
||||
int col1 = littleEndianToInt(key, 4);
|
||||
W[0][1] = col1;
|
||||
int col2 = littleEndianToInt(key, 8);
|
||||
W[0][2] = col2;
|
||||
int col3 = littleEndianToInt(key, 12);
|
||||
W[0][3] = col3;
|
||||
|
||||
int col4 = littleEndianToInt(key, 16);
|
||||
W[1][0] = col4;
|
||||
int col5 = littleEndianToInt(key, 20);
|
||||
W[1][1] = col5;
|
||||
int col6 = littleEndianToInt(key, 24);
|
||||
W[1][2] = col6;
|
||||
int col7 = littleEndianToInt(key, 28);
|
||||
W[1][3] = col7;
|
||||
|
||||
int i = 2, rcon = 1, colx;
|
||||
for (;;) {
|
||||
colx = subWord(shift(col7, 8)) ^ rcon;
|
||||
rcon <<= 1;
|
||||
col0 ^= colx;
|
||||
W[i][0] = col0;
|
||||
col1 ^= col0;
|
||||
W[i][1] = col1;
|
||||
col2 ^= col1;
|
||||
W[i][2] = col2;
|
||||
col3 ^= col2;
|
||||
W[i][3] = col3;
|
||||
++i;
|
||||
|
||||
if (i >= 15) {
|
||||
break;
|
||||
}
|
||||
|
||||
colx = subWord(col3);
|
||||
col4 ^= colx;
|
||||
W[i][0] = col4;
|
||||
col5 ^= col4;
|
||||
W[i][1] = col5;
|
||||
col6 ^= col5;
|
||||
W[i][2] = col6;
|
||||
col7 ^= col6;
|
||||
W[i][3] = col7;
|
||||
++i;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new IllegalStateException("Should never get here");
|
||||
}
|
||||
}
|
||||
|
||||
if (!forEncryption) {
|
||||
for (int j = 1; j < ROUNDS; j++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
W[j][i] = inv_mcol(W[j][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return W;
|
||||
}
|
||||
|
||||
private int ROUNDS;
|
||||
private int[][] WorkingKey = null;
|
||||
private boolean forEncryption;
|
||||
|
||||
private static final int BLOCK_SIZE = 16;
|
||||
|
||||
/**
|
||||
* default constructor - 128 bit block size.
|
||||
*/
|
||||
public AESLightEngine() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* initialise an AES cipher.
|
||||
*
|
||||
* @param forEncryption whether or not we are for encryption.
|
||||
* @param params the parameters required to set up the cipher.
|
||||
* @exception IllegalArgumentException if the params argument is
|
||||
* inappropriate.
|
||||
*/
|
||||
public void init(boolean forEncryption, byte[] key) {
|
||||
WorkingKey = generateWorkingKey(key, forEncryption);
|
||||
this.forEncryption = forEncryption;
|
||||
return;
|
||||
}
|
||||
|
||||
public String getAlgorithmName() {
|
||||
return "AES";
|
||||
}
|
||||
|
||||
public int getBlockSize() {
|
||||
return BLOCK_SIZE;
|
||||
}
|
||||
|
||||
public int processBlock(byte[] in, int inOff, byte[] out, int outOff) {
|
||||
if (WorkingKey == null) {
|
||||
throw new IllegalStateException("AES engine not initialised");
|
||||
}
|
||||
|
||||
if (inOff > (in.length - BLOCK_SIZE)) {
|
||||
throw new IndexOutOfBoundsException("input buffer too short");
|
||||
}
|
||||
|
||||
if (outOff > (out.length - BLOCK_SIZE)) {
|
||||
throw new IndexOutOfBoundsException("output buffer too short");
|
||||
}
|
||||
|
||||
if (forEncryption) {
|
||||
encryptBlock(in, inOff, out, outOff, WorkingKey);
|
||||
} else {
|
||||
decryptBlock(in, inOff, out, outOff, WorkingKey);
|
||||
}
|
||||
|
||||
return BLOCK_SIZE;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
}
|
||||
|
||||
private void encryptBlock(byte[] in, int inOff, byte[] out, int outOff, int[][] KW) {
|
||||
int C0 = littleEndianToInt(in, inOff + 0);
|
||||
int C1 = littleEndianToInt(in, inOff + 4);
|
||||
int C2 = littleEndianToInt(in, inOff + 8);
|
||||
int C3 = littleEndianToInt(in, inOff + 12);
|
||||
|
||||
int t0 = C0 ^ KW[0][0];
|
||||
int t1 = C1 ^ KW[0][1];
|
||||
int t2 = C2 ^ KW[0][2];
|
||||
|
||||
int r = 1, r0, r1, r2, r3 = C3 ^ KW[0][3];
|
||||
while (r < ROUNDS - 1) {
|
||||
r0 = mcol((S[t0 & 255] & 255) ^ ((S[(t1 >> 8) & 255] & 255) << 8) ^ ((S[(t2 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(r3 >> 24) & 255] << 24)) ^ KW[r][0];
|
||||
r1 = mcol((S[t1 & 255] & 255) ^ ((S[(t2 >> 8) & 255] & 255) << 8) ^ ((S[(r3 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(t0 >> 24) & 255] << 24)) ^ KW[r][1];
|
||||
r2 = mcol((S[t2 & 255] & 255) ^ ((S[(r3 >> 8) & 255] & 255) << 8) ^ ((S[(t0 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(t1 >> 24) & 255] << 24)) ^ KW[r][2];
|
||||
r3 = mcol((S[r3 & 255] & 255) ^ ((S[(t0 >> 8) & 255] & 255) << 8) ^ ((S[(t1 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(t2 >> 24) & 255] << 24)) ^ KW[r++][3];
|
||||
t0 = mcol((S[r0 & 255] & 255) ^ ((S[(r1 >> 8) & 255] & 255) << 8) ^ ((S[(r2 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(r3 >> 24) & 255] << 24)) ^ KW[r][0];
|
||||
t1 = mcol((S[r1 & 255] & 255) ^ ((S[(r2 >> 8) & 255] & 255) << 8) ^ ((S[(r3 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(r0 >> 24) & 255] << 24)) ^ KW[r][1];
|
||||
t2 = mcol((S[r2 & 255] & 255) ^ ((S[(r3 >> 8) & 255] & 255) << 8) ^ ((S[(r0 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(r1 >> 24) & 255] << 24)) ^ KW[r][2];
|
||||
r3 = mcol((S[r3 & 255] & 255) ^ ((S[(r0 >> 8) & 255] & 255) << 8) ^ ((S[(r1 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(r2 >> 24) & 255] << 24)) ^ KW[r++][3];
|
||||
}
|
||||
|
||||
r0 = mcol((S[t0 & 255] & 255) ^ ((S[(t1 >> 8) & 255] & 255) << 8) ^ ((S[(t2 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(r3 >> 24) & 255] << 24)) ^ KW[r][0];
|
||||
r1 = mcol((S[t1 & 255] & 255) ^ ((S[(t2 >> 8) & 255] & 255) << 8) ^ ((S[(r3 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(t0 >> 24) & 255] << 24)) ^ KW[r][1];
|
||||
r2 = mcol((S[t2 & 255] & 255) ^ ((S[(r3 >> 8) & 255] & 255) << 8) ^ ((S[(t0 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(t1 >> 24) & 255] << 24)) ^ KW[r][2];
|
||||
r3 = mcol((S[r3 & 255] & 255) ^ ((S[(t0 >> 8) & 255] & 255) << 8) ^ ((S[(t1 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(t2 >> 24) & 255] << 24)) ^ KW[r++][3];
|
||||
|
||||
// the final round is a simple function of S
|
||||
|
||||
C0 = (S[r0 & 255] & 255) ^ ((S[(r1 >> 8) & 255] & 255) << 8) ^ ((S[(r2 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(r3 >> 24) & 255] << 24) ^ KW[r][0];
|
||||
C1 = (S[r1 & 255] & 255) ^ ((S[(r2 >> 8) & 255] & 255) << 8) ^ ((S[(r3 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(r0 >> 24) & 255] << 24) ^ KW[r][1];
|
||||
C2 = (S[r2 & 255] & 255) ^ ((S[(r3 >> 8) & 255] & 255) << 8) ^ ((S[(r0 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(r1 >> 24) & 255] << 24) ^ KW[r][2];
|
||||
C3 = (S[r3 & 255] & 255) ^ ((S[(r0 >> 8) & 255] & 255) << 8) ^ ((S[(r1 >> 16) & 255] & 255) << 16)
|
||||
^ (S[(r2 >> 24) & 255] << 24) ^ KW[r][3];
|
||||
|
||||
intToLittleEndian(C0, out, outOff + 0);
|
||||
intToLittleEndian(C1, out, outOff + 4);
|
||||
intToLittleEndian(C2, out, outOff + 8);
|
||||
intToLittleEndian(C3, out, outOff + 12);
|
||||
}
|
||||
|
||||
private void decryptBlock(byte[] in, int inOff, byte[] out, int outOff, int[][] KW) {
|
||||
int C0 = littleEndianToInt(in, inOff + 0);
|
||||
int C1 = littleEndianToInt(in, inOff + 4);
|
||||
int C2 = littleEndianToInt(in, inOff + 8);
|
||||
int C3 = littleEndianToInt(in, inOff + 12);
|
||||
|
||||
int t0 = C0 ^ KW[ROUNDS][0];
|
||||
int t1 = C1 ^ KW[ROUNDS][1];
|
||||
int t2 = C2 ^ KW[ROUNDS][2];
|
||||
|
||||
int r = ROUNDS - 1, r0, r1, r2, r3 = C3 ^ KW[ROUNDS][3];
|
||||
while (r > 1) {
|
||||
r0 = inv_mcol((Si[t0 & 255] & 255) ^ ((Si[(r3 >> 8) & 255] & 255) << 8)
|
||||
^ ((Si[(t2 >> 16) & 255] & 255) << 16) ^ (Si[(t1 >> 24) & 255] << 24)) ^ KW[r][0];
|
||||
r1 = inv_mcol((Si[t1 & 255] & 255) ^ ((Si[(t0 >> 8) & 255] & 255) << 8)
|
||||
^ ((Si[(r3 >> 16) & 255] & 255) << 16) ^ (Si[(t2 >> 24) & 255] << 24)) ^ KW[r][1];
|
||||
r2 = inv_mcol((Si[t2 & 255] & 255) ^ ((Si[(t1 >> 8) & 255] & 255) << 8)
|
||||
^ ((Si[(t0 >> 16) & 255] & 255) << 16) ^ (Si[(r3 >> 24) & 255] << 24)) ^ KW[r][2];
|
||||
r3 = inv_mcol((Si[r3 & 255] & 255) ^ ((Si[(t2 >> 8) & 255] & 255) << 8)
|
||||
^ ((Si[(t1 >> 16) & 255] & 255) << 16) ^ (Si[(t0 >> 24) & 255] << 24)) ^ KW[r--][3];
|
||||
t0 = inv_mcol((Si[r0 & 255] & 255) ^ ((Si[(r3 >> 8) & 255] & 255) << 8)
|
||||
^ ((Si[(r2 >> 16) & 255] & 255) << 16) ^ (Si[(r1 >> 24) & 255] << 24)) ^ KW[r][0];
|
||||
t1 = inv_mcol((Si[r1 & 255] & 255) ^ ((Si[(r0 >> 8) & 255] & 255) << 8)
|
||||
^ ((Si[(r3 >> 16) & 255] & 255) << 16) ^ (Si[(r2 >> 24) & 255] << 24)) ^ KW[r][1];
|
||||
t2 = inv_mcol((Si[r2 & 255] & 255) ^ ((Si[(r1 >> 8) & 255] & 255) << 8)
|
||||
^ ((Si[(r0 >> 16) & 255] & 255) << 16) ^ (Si[(r3 >> 24) & 255] << 24)) ^ KW[r][2];
|
||||
r3 = inv_mcol((Si[r3 & 255] & 255) ^ ((Si[(r2 >> 8) & 255] & 255) << 8)
|
||||
^ ((Si[(r1 >> 16) & 255] & 255) << 16) ^ (Si[(r0 >> 24) & 255] << 24)) ^ KW[r--][3];
|
||||
}
|
||||
|
||||
r0 = inv_mcol((Si[t0 & 255] & 255) ^ ((Si[(r3 >> 8) & 255] & 255) << 8) ^ ((Si[(t2 >> 16) & 255] & 255) << 16)
|
||||
^ (Si[(t1 >> 24) & 255] << 24)) ^ KW[r][0];
|
||||
r1 = inv_mcol((Si[t1 & 255] & 255) ^ ((Si[(t0 >> 8) & 255] & 255) << 8) ^ ((Si[(r3 >> 16) & 255] & 255) << 16)
|
||||
^ (Si[(t2 >> 24) & 255] << 24)) ^ KW[r][1];
|
||||
r2 = inv_mcol((Si[t2 & 255] & 255) ^ ((Si[(t1 >> 8) & 255] & 255) << 8) ^ ((Si[(t0 >> 16) & 255] & 255) << 16)
|
||||
^ (Si[(r3 >> 24) & 255] << 24)) ^ KW[r][2];
|
||||
r3 = inv_mcol((Si[r3 & 255] & 255) ^ ((Si[(t2 >> 8) & 255] & 255) << 8) ^ ((Si[(t1 >> 16) & 255] & 255) << 16)
|
||||
^ (Si[(t0 >> 24) & 255] << 24)) ^ KW[r][3];
|
||||
|
||||
// the final round's table is a simple function of Si
|
||||
|
||||
C0 = (Si[r0 & 255] & 255) ^ ((Si[(r3 >> 8) & 255] & 255) << 8) ^ ((Si[(r2 >> 16) & 255] & 255) << 16)
|
||||
^ (Si[(r1 >> 24) & 255] << 24) ^ KW[0][0];
|
||||
C1 = (Si[r1 & 255] & 255) ^ ((Si[(r0 >> 8) & 255] & 255) << 8) ^ ((Si[(r3 >> 16) & 255] & 255) << 16)
|
||||
^ (Si[(r2 >> 24) & 255] << 24) ^ KW[0][1];
|
||||
C2 = (Si[r2 & 255] & 255) ^ ((Si[(r1 >> 8) & 255] & 255) << 8) ^ ((Si[(r0 >> 16) & 255] & 255) << 16)
|
||||
^ (Si[(r3 >> 24) & 255] << 24) ^ KW[0][2];
|
||||
C3 = (Si[r3 & 255] & 255) ^ ((Si[(r2 >> 8) & 255] & 255) << 8) ^ ((Si[(r1 >> 16) & 255] & 255) << 16)
|
||||
^ (Si[(r0 >> 24) & 255] << 24) ^ KW[0][3];
|
||||
|
||||
intToLittleEndian(C0, out, outOff + 0);
|
||||
intToLittleEndian(C1, out, outOff + 4);
|
||||
intToLittleEndian(C2, out, outOff + 8);
|
||||
intToLittleEndian(C3, out, outOff + 12);
|
||||
}
|
||||
|
||||
private int bitsOfSecurity() {
|
||||
if (WorkingKey == null) {
|
||||
return 256;
|
||||
}
|
||||
return (WorkingKey.length - 7) << 5;
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ import java.util.concurrent.Executor;
|
||||
*/
|
||||
public class ListenableFutureTask<V> extends FutureTask<V> implements ListenableFuture<V> {
|
||||
|
||||
private final List<Runnable> listeners = new ArrayList();
|
||||
private final List<Runnable> listeners = new ArrayList<>();
|
||||
|
||||
public ListenableFutureTask(Callable<V> callable) {
|
||||
super(callable);
|
||||
@ -54,7 +54,7 @@ public class ListenableFutureTask<V> extends FutureTask<V> implements Listenable
|
||||
}
|
||||
|
||||
public static <V> ListenableFutureTask<V> create(Callable<V> callableToSchedule) {
|
||||
return new ListenableFutureTask(callableToSchedule);
|
||||
return new ListenableFutureTask<>(callableToSchedule);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,227 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 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 abstract class AbstractWebSocketClient implements IWebSocketClient {
|
||||
|
||||
protected volatile int availableStringFrames = 0;
|
||||
protected volatile int availableBinaryFrames = 0;
|
||||
protected final List<IWebSocketFrame> recievedPacketBuffer = new LinkedList<>();
|
||||
protected String currentURI;
|
||||
|
||||
protected AbstractWebSocketClient(String currentURI) {
|
||||
this.currentURI = currentURI;
|
||||
}
|
||||
|
||||
protected void addRecievedFrame(IWebSocketFrame frame) {
|
||||
boolean str = frame.isString();
|
||||
synchronized(recievedPacketBuffer) {
|
||||
recievedPacketBuffer.add(frame);
|
||||
if(str) {
|
||||
++availableStringFrames;
|
||||
}else {
|
||||
++availableBinaryFrames;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int availableFrames() {
|
||||
synchronized(recievedPacketBuffer) {
|
||||
return availableStringFrames + availableBinaryFrames;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWebSocketFrame getNextFrame() {
|
||||
synchronized(recievedPacketBuffer) {
|
||||
if(!recievedPacketBuffer.isEmpty()) {
|
||||
IWebSocketFrame frame = recievedPacketBuffer.remove(0);
|
||||
if(frame.isString()) {
|
||||
--availableStringFrames;
|
||||
}else {
|
||||
--availableBinaryFrames;
|
||||
}
|
||||
return frame;
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IWebSocketFrame> getNextFrames() {
|
||||
synchronized(recievedPacketBuffer) {
|
||||
if(!recievedPacketBuffer.isEmpty()) {
|
||||
List<IWebSocketFrame> ret = new ArrayList<>(recievedPacketBuffer);
|
||||
recievedPacketBuffer.clear();
|
||||
availableStringFrames = 0;
|
||||
availableBinaryFrames = 0;
|
||||
return ret;
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearFrames() {
|
||||
synchronized(recievedPacketBuffer) {
|
||||
recievedPacketBuffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int availableStringFrames() {
|
||||
synchronized(recievedPacketBuffer) {
|
||||
return availableStringFrames;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWebSocketFrame getNextStringFrame() {
|
||||
synchronized(recievedPacketBuffer) {
|
||||
if(availableStringFrames > 0) {
|
||||
Iterator<IWebSocketFrame> itr = recievedPacketBuffer.iterator();
|
||||
while(itr.hasNext()) {
|
||||
IWebSocketFrame r = itr.next();
|
||||
if(r.isString()) {
|
||||
itr.remove();
|
||||
--availableStringFrames;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
availableStringFrames = 0;
|
||||
return null;
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IWebSocketFrame> getNextStringFrames() {
|
||||
synchronized(recievedPacketBuffer) {
|
||||
if(availableStringFrames > 0) {
|
||||
List<IWebSocketFrame> ret = new ArrayList<>(availableStringFrames);
|
||||
Iterator<IWebSocketFrame> itr = recievedPacketBuffer.iterator();
|
||||
while(itr.hasNext()) {
|
||||
IWebSocketFrame r = itr.next();
|
||||
if(r.isString()) {
|
||||
itr.remove();
|
||||
ret.add(r);
|
||||
}
|
||||
}
|
||||
availableStringFrames = 0;
|
||||
return ret;
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearStringFrames() {
|
||||
synchronized(recievedPacketBuffer) {
|
||||
if(availableStringFrames > 0) {
|
||||
Iterator<IWebSocketFrame> itr = recievedPacketBuffer.iterator();
|
||||
while(itr.hasNext()) {
|
||||
IWebSocketFrame r = itr.next();
|
||||
if(r.isString()) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
availableStringFrames = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int availableBinaryFrames() {
|
||||
synchronized(recievedPacketBuffer) {
|
||||
return availableBinaryFrames;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWebSocketFrame getNextBinaryFrame() {
|
||||
synchronized(recievedPacketBuffer) {
|
||||
if(availableBinaryFrames > 0) {
|
||||
Iterator<IWebSocketFrame> itr = recievedPacketBuffer.iterator();
|
||||
while(itr.hasNext()) {
|
||||
IWebSocketFrame r = itr.next();
|
||||
if(!r.isString()) {
|
||||
itr.remove();
|
||||
--availableBinaryFrames;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
availableBinaryFrames = 0;
|
||||
return null;
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IWebSocketFrame> getNextBinaryFrames() {
|
||||
synchronized(recievedPacketBuffer) {
|
||||
if(availableBinaryFrames > 0) {
|
||||
List<IWebSocketFrame> ret = new ArrayList<>(availableBinaryFrames);
|
||||
Iterator<IWebSocketFrame> itr = recievedPacketBuffer.iterator();
|
||||
while(itr.hasNext()) {
|
||||
IWebSocketFrame r = itr.next();
|
||||
if(!r.isString()) {
|
||||
itr.remove();
|
||||
ret.add(r);
|
||||
}
|
||||
}
|
||||
availableBinaryFrames = 0;
|
||||
return ret;
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearBinaryFrames() {
|
||||
synchronized(recievedPacketBuffer) {
|
||||
if(availableBinaryFrames > 0) {
|
||||
Iterator<IWebSocketFrame> itr = recievedPacketBuffer.iterator();
|
||||
while(itr.hasNext()) {
|
||||
IWebSocketFrame r = itr.next();
|
||||
if(!r.isString()) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
availableBinaryFrames = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentURI() {
|
||||
return currentURI;
|
||||
}
|
||||
|
||||
}
|
@ -1,11 +1,7 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
* 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
|
||||
@ -19,27 +15,21 @@ import java.io.IOException;
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket06ClientFailure extends IPacket {
|
||||
|
||||
public String clientId;
|
||||
|
||||
public IPacket06ClientFailure() {
|
||||
}
|
||||
|
||||
public IPacket06ClientFailure(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
clientId = readASCII8(input);
|
||||
public class EaglerMissingResourceException extends RuntimeException {
|
||||
|
||||
public EaglerMissingResourceException() {
|
||||
}
|
||||
|
||||
public void write(DataOutputStream output) throws IOException {
|
||||
writeASCII8(output, clientId);
|
||||
public EaglerMissingResourceException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public int packetLength() {
|
||||
return 1 + clientId.length();
|
||||
|
||||
public EaglerMissingResourceException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
public EaglerMissingResourceException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
/**
|
||||
* 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 EnumFireKeyboardEvent {
|
||||
KEY_DOWN, KEY_UP, KEY_REPEAT;
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
/**
|
||||
* 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 EnumFireMouseEvent {
|
||||
MOUSE_DOWN, MOUSE_UP, MOUSE_MOVE, MOUSE_WHEEL;
|
||||
}
|
@ -18,6 +18,7 @@ package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
public enum EnumPlatformANGLE {
|
||||
|
||||
DEFAULT(225281 /* GLFW_ANGLE_PLATFORM_TYPE_NONE */, "default", "Default"),
|
||||
D3D9(225284 /* GLFW_ANGLE_PLATFORM_TYPE_D3D9 */, "d3d9", "Direct3D9"),
|
||||
D3D11(225285 /* GLFW_ANGLE_PLATFORM_TYPE_D3D11 */, "d3d11", "Direct3D11"),
|
||||
OPENGL(225282 /* GLFW_ANGLE_PLATFORM_TYPE_OPENGL */, "opengl", "OpenGL"),
|
||||
OPENGLES(225283 /* GLFW_ANGLE_PLATFORM_TYPE_OPENGLES */, "opengles", "OpenGL ES"),
|
||||
@ -41,6 +42,8 @@ public enum EnumPlatformANGLE {
|
||||
public static EnumPlatformANGLE fromId(String id) {
|
||||
if(id.equals("d3d11") || id.equals("d3d") || id.equals("dx11")) {
|
||||
return D3D11;
|
||||
}else if(id.equals("d3d9") || id.equals("dx9")) {
|
||||
return D3D9;
|
||||
}else if(id.equals("opengl")) {
|
||||
return OPENGL;
|
||||
}else if(id.equals("opengles")) {
|
||||
@ -58,6 +61,8 @@ public enum EnumPlatformANGLE {
|
||||
str = str.toLowerCase();
|
||||
if(str.contains("direct3d11") || str.contains("d3d11")) {
|
||||
return D3D11;
|
||||
}else if(str.contains("direct3d9") || str.contains("d3d9")) {
|
||||
return D3D9;
|
||||
}else if(str.contains("opengl es")) {
|
||||
return OPENGLES;
|
||||
}else if(str.contains("opengl")) {
|
||||
|
@ -35,12 +35,15 @@ public enum EnumPlatformAgent {
|
||||
}
|
||||
|
||||
public static EnumPlatformAgent getFromUA(String ua) {
|
||||
if(ua == null) {
|
||||
return UNKNOWN;
|
||||
}
|
||||
ua = " " + ua.toLowerCase();
|
||||
if(ua.contains(" edg/")) {
|
||||
return EDGE;
|
||||
}else if(ua.contains(" opr/")) {
|
||||
return OPERA;
|
||||
}else if(ua.contains(" chrome/")) {
|
||||
}else if(ua.contains(" chrome/") || ua.contains(" chromium/")) {
|
||||
return CHROME;
|
||||
}else if(ua.contains(" firefox/")) {
|
||||
return FIREFOX;
|
||||
|
@ -42,6 +42,9 @@ public enum EnumPlatformOS {
|
||||
}
|
||||
|
||||
public static EnumPlatformOS getFromJVM(String osNameProperty) {
|
||||
if(osNameProperty == null) {
|
||||
return OTHER;
|
||||
}
|
||||
osNameProperty = osNameProperty.toLowerCase();
|
||||
if(osNameProperty.contains("chrome")) {
|
||||
return CHROMEBOOK_LINUX;
|
||||
@ -57,6 +60,9 @@ public enum EnumPlatformOS {
|
||||
}
|
||||
|
||||
public static EnumPlatformOS getFromUA(String ua) {
|
||||
if(ua == null) {
|
||||
return OTHER;
|
||||
}
|
||||
ua = " " + ua.toLowerCase();
|
||||
if(ua.contains(" cros")) {
|
||||
return CHROMEBOOK_LINUX;
|
||||
|
@ -1,11 +1,7 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
* 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
|
||||
@ -19,27 +15,29 @@ import java.io.IOException;
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket05ClientSuccess extends IPacket {
|
||||
public enum EnumTouchEvent {
|
||||
TOUCHSTART(0), TOUCHMOVE(1), TOUCHEND(2);
|
||||
|
||||
public String clientId;
|
||||
public final int id;
|
||||
|
||||
public IPacket05ClientSuccess() {
|
||||
private EnumTouchEvent(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public IPacket05ClientSuccess(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
clientId = readASCII8(input);
|
||||
}
|
||||
|
||||
public void write(DataOutputStream output) throws IOException {
|
||||
writeASCII8(output, clientId);
|
||||
public static EnumTouchEvent getById(int id) {
|
||||
if(id >= 0 && id < lookup.length) {
|
||||
return lookup[id];
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public int packetLength() {
|
||||
return 1 + clientId.length();
|
||||
}
|
||||
private static final EnumTouchEvent[] lookup = new EnumTouchEvent[3];
|
||||
|
||||
static {
|
||||
EnumTouchEvent[] v = values();
|
||||
for(int i = 0; i < v.length; ++i) {
|
||||
lookup[v[i].id] = v[i];
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
/**
|
||||
* 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 EnumWebViewContentMode {
|
||||
URL_BASED, BLOB_BASED;
|
||||
}
|
@ -71,4 +71,11 @@ public class GLObjectMap<T> {
|
||||
values = new Object[size];
|
||||
System.arraycopy(oldValues, 0, values, 0, oldSize);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
if(allocatedObjects == 0) return;
|
||||
values = new Object[size];
|
||||
insertIndex = 0;
|
||||
allocatedObjects = 0;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,134 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
/**
|
||||
* 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 GamepadConstants {
|
||||
|
||||
private static final String[] buttonNames = new String[24];
|
||||
private static final String[] axisNames = new String[4];
|
||||
private static final int[] eaglerButtonsToGLFW = new int[24];
|
||||
private static final int[] glfwButtonsToEagler = new int[24];
|
||||
|
||||
public static final int GAMEPAD_NONE = -1;
|
||||
public static final int GAMEPAD_A = 0;
|
||||
public static final int GAMEPAD_B = 1;
|
||||
public static final int GAMEPAD_X = 2;
|
||||
public static final int GAMEPAD_Y = 3;
|
||||
public static final int GAMEPAD_LEFT_BUTTON = 4;
|
||||
public static final int GAMEPAD_RIGHT_BUTTON = 5;
|
||||
public static final int GAMEPAD_LEFT_TRIGGER = 6;
|
||||
public static final int GAMEPAD_RIGHT_TRIGGER = 7;
|
||||
public static final int GAMEPAD_BACK = 8;
|
||||
public static final int GAMEPAD_START = 9;
|
||||
public static final int GAMEPAD_LEFT_STICK_BUTTON = 10;
|
||||
public static final int GAMEPAD_RIGHT_STICK_BUTTON = 11;
|
||||
public static final int GAMEPAD_DPAD_UP = 12;
|
||||
public static final int GAMEPAD_DPAD_DOWN = 13;
|
||||
public static final int GAMEPAD_DPAD_LEFT = 14;
|
||||
public static final int GAMEPAD_DPAD_RIGHT = 15;
|
||||
public static final int GAMEPAD_GUIDE = 16;
|
||||
|
||||
public static final int GAMEPAD_AXIS_NONE = -1;
|
||||
public static final int GAMEPAD_AXIS_LEFT_STICK_X = 0;
|
||||
public static final int GAMEPAD_AXIS_LEFT_STICK_Y = 1;
|
||||
public static final int GAMEPAD_AXIS_RIGHT_STICK_X = 2;
|
||||
public static final int GAMEPAD_AXIS_RIGHT_STICK_Y = 3;
|
||||
|
||||
private static final int GLFW_GAMEPAD_BUTTON_A = 0, GLFW_GAMEPAD_BUTTON_B = 1, GLFW_GAMEPAD_BUTTON_X = 2,
|
||||
GLFW_GAMEPAD_BUTTON_Y = 3, GLFW_GAMEPAD_BUTTON_LEFT_BUMPER = 4, GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER = 5,
|
||||
GLFW_GAMEPAD_BUTTON_BACK = 6, GLFW_GAMEPAD_BUTTON_START = 7, GLFW_GAMEPAD_BUTTON_GUIDE = 8,
|
||||
GLFW_GAMEPAD_BUTTON_LEFT_THUMB = 9, GLFW_GAMEPAD_BUTTON_RIGHT_THUMB = 10, GLFW_GAMEPAD_BUTTON_DPAD_UP = 11,
|
||||
GLFW_GAMEPAD_BUTTON_DPAD_RIGHT = 12, GLFW_GAMEPAD_BUTTON_DPAD_DOWN = 13, GLFW_GAMEPAD_BUTTON_DPAD_LEFT = 14;
|
||||
|
||||
private static void registerBtn(int eaglerBtn, int glfwBtn, String name) {
|
||||
if(eaglerButtonsToGLFW[eaglerBtn] != 0) throw new IllegalArgumentException("Duplicate eaglerButtonsToGLFW entry: " + eaglerBtn + " -> " + glfwBtn);
|
||||
if(glfwBtn != -1 && glfwButtonsToEagler[glfwBtn] != 0) throw new IllegalArgumentException("Duplicate glfwButtonsToEAGLER entry: " + glfwBtn + " -> " + eaglerBtn);
|
||||
eaglerButtonsToGLFW[eaglerBtn] = glfwBtn;
|
||||
if(glfwBtn != -1) glfwButtonsToEagler[glfwBtn] = eaglerBtn;
|
||||
if(buttonNames[eaglerBtn] != null) throw new IllegalArgumentException("Duplicate buttonNames entry: " + eaglerBtn);
|
||||
buttonNames[eaglerBtn] = name;
|
||||
}
|
||||
|
||||
private static void registerAxis(int eaglerAxis, String name) {
|
||||
if(axisNames[eaglerAxis] != null) throw new IllegalArgumentException("Duplicate axisNames entry: " + eaglerAxis);
|
||||
axisNames[eaglerAxis] = name;
|
||||
}
|
||||
|
||||
static {
|
||||
registerBtn(GAMEPAD_A, GLFW_GAMEPAD_BUTTON_A, "A");
|
||||
registerBtn(GAMEPAD_B, GLFW_GAMEPAD_BUTTON_B, "B");
|
||||
registerBtn(GAMEPAD_X, GLFW_GAMEPAD_BUTTON_X, "X");
|
||||
registerBtn(GAMEPAD_Y, GLFW_GAMEPAD_BUTTON_Y, "Y");
|
||||
registerBtn(GAMEPAD_LEFT_BUTTON, GLFW_GAMEPAD_BUTTON_LEFT_BUMPER, "Left Button");
|
||||
registerBtn(GAMEPAD_LEFT_TRIGGER, -1, "Left Trigger");
|
||||
registerBtn(GAMEPAD_RIGHT_BUTTON, GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER, "Right Button");
|
||||
registerBtn(GAMEPAD_RIGHT_TRIGGER, -1, "Right Trigger");
|
||||
registerBtn(GAMEPAD_BACK, GLFW_GAMEPAD_BUTTON_BACK, "Back");
|
||||
registerBtn(GAMEPAD_START, GLFW_GAMEPAD_BUTTON_START, "Start");
|
||||
registerBtn(GAMEPAD_LEFT_STICK_BUTTON, GLFW_GAMEPAD_BUTTON_LEFT_THUMB, "L. Stick Button");
|
||||
registerBtn(GAMEPAD_RIGHT_STICK_BUTTON, GLFW_GAMEPAD_BUTTON_RIGHT_THUMB, "R. Stick Button");
|
||||
registerBtn(GAMEPAD_DPAD_UP, GLFW_GAMEPAD_BUTTON_DPAD_UP, "D-Pad Up");
|
||||
registerBtn(GAMEPAD_DPAD_DOWN, GLFW_GAMEPAD_BUTTON_DPAD_DOWN, "D-Pad Down");
|
||||
registerBtn(GAMEPAD_DPAD_LEFT, GLFW_GAMEPAD_BUTTON_DPAD_LEFT, "D-Pad Left");
|
||||
registerBtn(GAMEPAD_DPAD_RIGHT, GLFW_GAMEPAD_BUTTON_DPAD_RIGHT, "D-Pad Right");
|
||||
registerBtn(GAMEPAD_GUIDE, GLFW_GAMEPAD_BUTTON_GUIDE, "Guide");
|
||||
registerAxis(GAMEPAD_AXIS_LEFT_STICK_X, "Left Stick X");
|
||||
registerAxis(GAMEPAD_AXIS_LEFT_STICK_Y, "Left Stick Y");
|
||||
registerAxis(GAMEPAD_AXIS_RIGHT_STICK_X, "Right Stick X");
|
||||
registerAxis(GAMEPAD_AXIS_RIGHT_STICK_Y, "Right Stick Y");
|
||||
}
|
||||
|
||||
public static int getEaglerButtonFromBrowser(int button) {
|
||||
return button;
|
||||
}
|
||||
|
||||
public static int getBrowserButtonFromEagler(int button) {
|
||||
return button;
|
||||
}
|
||||
|
||||
public static int getEaglerButtonFromGLFW(int button) {
|
||||
if(button >= 0 && button < glfwButtonsToEagler.length) {
|
||||
return glfwButtonsToEagler[button];
|
||||
}else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getGLFWButtonFromEagler(int button) {
|
||||
if(button >= 0 && button < eaglerButtonsToGLFW.length) {
|
||||
return eaglerButtonsToGLFW[button];
|
||||
}else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getButtonName(int button) {
|
||||
if(button >= 0 && button < buttonNames.length) {
|
||||
return buttonNames[button];
|
||||
}else {
|
||||
return "Button " + button;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getAxisName(int button) {
|
||||
if(button >= 0 && button < axisNames.length) {
|
||||
return axisNames[button];
|
||||
}else {
|
||||
return "Axis " + button;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -26,10 +26,12 @@ public interface IClientConfigAdapter {
|
||||
|
||||
public final String name;
|
||||
public final String addr;
|
||||
public final boolean hideAddress;
|
||||
|
||||
public DefaultServer(String name, String addr) {
|
||||
public DefaultServer(String name, String addr, boolean hideAddress) {
|
||||
this.name = name;
|
||||
this.addr = addr;
|
||||
this.hideAddress = hideAddress;
|
||||
}
|
||||
|
||||
}
|
||||
@ -76,6 +78,24 @@ public interface IClientConfigAdapter {
|
||||
|
||||
boolean isEnableMinceraft();
|
||||
|
||||
boolean isEnableServerCookies();
|
||||
|
||||
boolean isAllowServerRedirects();
|
||||
|
||||
boolean isOpenDebugConsoleOnLaunch();
|
||||
|
||||
boolean isForceWebViewSupport();
|
||||
|
||||
boolean isEnableWebViewCSP();
|
||||
|
||||
boolean isAllowBootMenu();
|
||||
|
||||
boolean isForceProfanityFilter();
|
||||
|
||||
boolean isEaglerNoDelay();
|
||||
|
||||
boolean isRamdiskMode();
|
||||
|
||||
IClientConfigAdapterHooks getHooks();
|
||||
|
||||
}
|
||||
|
@ -25,4 +25,6 @@ public interface IClientConfigAdapterHooks {
|
||||
|
||||
void callCrashReportHook(String crashReport, Consumer<String> customMessageCB);
|
||||
|
||||
void callScreenChangedHook(String screenName, int scaledWidth, int scaledHeight, int realWidth, int realHeight, int scaleFactor);
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,46 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
|
||||
|
||||
/**
|
||||
* 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 interface IEaglerFilesystem {
|
||||
|
||||
String getFilesystemName();
|
||||
|
||||
String getInternalDBName();
|
||||
|
||||
boolean isRamdisk();
|
||||
|
||||
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);
|
||||
|
||||
void closeHandle();
|
||||
|
||||
}
|
@ -2,6 +2,8 @@ package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
@ -42,6 +44,8 @@ public interface IServerQuery {
|
||||
|
||||
}
|
||||
|
||||
void update();
|
||||
|
||||
void send(String str);
|
||||
|
||||
default void send(JSONObject json) {
|
||||
@ -73,8 +77,8 @@ public interface IServerQuery {
|
||||
EnumServerRateLimit getRateLimit();
|
||||
|
||||
default boolean awaitResponseAvailable(long timeout) {
|
||||
long start = System.currentTimeMillis();
|
||||
while(isOpen() && responsesAvailable() <= 0 && (timeout <= 0l || System.currentTimeMillis() - start < timeout)) {
|
||||
long start = EagRuntime.steadyTimeMillis();
|
||||
while(isOpen() && responsesAvailable() <= 0 && (timeout <= 0l || EagRuntime.steadyTimeMillis() - start < timeout)) {
|
||||
try {
|
||||
Thread.sleep(0l, 250000);
|
||||
} catch (InterruptedException e) {
|
||||
@ -88,8 +92,8 @@ public interface IServerQuery {
|
||||
}
|
||||
|
||||
default boolean awaitResponseBinaryAvailable(long timeout) {
|
||||
long start = System.currentTimeMillis();
|
||||
while(isOpen() && binaryResponsesAvailable() <= 0 && (timeout <= 0l || System.currentTimeMillis() - start < timeout)) {
|
||||
long start = EagRuntime.steadyTimeMillis();
|
||||
while(isOpen() && binaryResponsesAvailable() <= 0 && (timeout <= 0l || EagRuntime.steadyTimeMillis() - start < timeout)) {
|
||||
try {
|
||||
Thread.sleep(0l, 250000);
|
||||
} catch (InterruptedException e) {
|
||||
|
@ -1,12 +1,9 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
* 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
|
||||
@ -20,31 +17,46 @@ import java.util.List;
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket07LocalWorlds extends IPacket {
|
||||
|
||||
public static class LocalWorld {
|
||||
|
||||
public final String worldName;
|
||||
public final String worldCode;
|
||||
|
||||
public LocalWorld(String worldName, String worldCode) {
|
||||
this.worldName = worldName;
|
||||
this.worldCode = worldCode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final List<LocalWorld> worldsList;
|
||||
|
||||
public IPacket07LocalWorlds() {
|
||||
this.worldsList = new ArrayList();
|
||||
}
|
||||
public interface IWebSocketClient {
|
||||
|
||||
EnumEaglerConnectionState getState();
|
||||
|
||||
boolean connectBlocking(int timeoutMS);
|
||||
|
||||
boolean isOpen();
|
||||
|
||||
boolean isClosed();
|
||||
|
||||
void close();
|
||||
|
||||
int availableFrames();
|
||||
|
||||
IWebSocketFrame getNextFrame();
|
||||
|
||||
List<IWebSocketFrame> getNextFrames();
|
||||
|
||||
void clearFrames();
|
||||
|
||||
int availableStringFrames();
|
||||
|
||||
IWebSocketFrame getNextStringFrame();
|
||||
|
||||
List<IWebSocketFrame> getNextStringFrames();
|
||||
|
||||
void clearStringFrames();
|
||||
|
||||
int availableBinaryFrames();
|
||||
|
||||
IWebSocketFrame getNextBinaryFrame();
|
||||
|
||||
List<IWebSocketFrame> getNextBinaryFrames();
|
||||
|
||||
void clearBinaryFrames();
|
||||
|
||||
void send(String str);
|
||||
|
||||
void send(byte[] bytes);
|
||||
|
||||
String getCurrentURI();
|
||||
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
int l = input.read();
|
||||
for(int i = 0; i < l; ++i) {
|
||||
worldsList.add(new LocalWorld(readASCII8(input), readASCII8(input)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 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 interface IWebSocketFrame {
|
||||
|
||||
boolean isString();
|
||||
|
||||
String getString();
|
||||
|
||||
byte[] getByteArray();
|
||||
|
||||
InputStream getInputStream();
|
||||
|
||||
int getLength();
|
||||
|
||||
long getTimestamp();
|
||||
|
||||
}
|
@ -2,6 +2,8 @@ package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
@ -37,7 +39,7 @@ public class QueryResponse {
|
||||
this.serverBrand = obj.getString("brand");
|
||||
this.serverName = obj.getString("name");
|
||||
this.serverTime = obj.getLong("time");
|
||||
this.clientTime = System.currentTimeMillis();
|
||||
this.clientTime = EagRuntime.steadyTimeMillis();
|
||||
this.serverCracked = obj.optBoolean("cracked", false);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,131 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
|
||||
|
||||
/**
|
||||
* 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 RamdiskFilesystemImpl implements IEaglerFilesystem {
|
||||
|
||||
protected final String filesystemName;
|
||||
protected final Map<String,byte[]> filesystemMap = new TreeMap<>();
|
||||
|
||||
public RamdiskFilesystemImpl(String filesystemName) {
|
||||
this.filesystemName = filesystemName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilesystemName() {
|
||||
return filesystemName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInternalDBName() {
|
||||
return "ramdisk:" + filesystemName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRamdisk() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eaglerDelete(String pathName) {
|
||||
return filesystemMap.remove(pathName) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer eaglerRead(String pathName) {
|
||||
byte[] data = filesystemMap.get(pathName);
|
||||
if(data != null) {
|
||||
ByteBuffer buf = PlatformRuntime.castPrimitiveByteArray(data);
|
||||
if(buf == null) {
|
||||
buf = PlatformRuntime.allocateByteBuffer(data.length);
|
||||
buf.put(data);
|
||||
buf.flip();
|
||||
}
|
||||
return buf;
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eaglerWrite(String pathName, ByteBuffer data) {
|
||||
byte[] arr = PlatformRuntime.castNativeByteBuffer(data);
|
||||
if(arr == null) {
|
||||
arr = new byte[data.remaining()];
|
||||
int i = data.position();
|
||||
data.get(arr);
|
||||
data.position(i);
|
||||
}
|
||||
filesystemMap.put(pathName, arr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eaglerExists(String pathName) {
|
||||
return filesystemMap.containsKey(pathName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eaglerMove(String pathNameOld, String pathNameNew) {
|
||||
byte[] dat = filesystemMap.remove(pathNameOld);
|
||||
if(dat != null) {
|
||||
filesystemMap.put(pathNameNew, dat);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int eaglerCopy(String pathNameOld, String pathNameNew) {
|
||||
byte[] dat = filesystemMap.get(pathNameOld);
|
||||
if(dat != null) {
|
||||
filesystemMap.put(pathNameNew, dat);
|
||||
return dat.length;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int eaglerSize(String pathName) {
|
||||
byte[] dat = filesystemMap.get(pathName);
|
||||
return dat != null ? dat.length : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eaglerIterate(String pathName, VFSFilenameIterator itr, boolean recursive) {
|
||||
if(!recursive) {
|
||||
eaglerIterate(pathName, new VFSFilenameIteratorNonRecursive(itr,
|
||||
VFSFilenameIteratorNonRecursive.countSlashes(pathName) + 1), true);
|
||||
}else {
|
||||
boolean b = pathName.length() == 0;
|
||||
for(String key : filesystemMap.keySet()) {
|
||||
if(b || key.startsWith(pathName)) {
|
||||
itr.next(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeHandle() {
|
||||
filesystemMap.clear();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.recording.EnumScreenRecordingCodec;
|
||||
|
||||
/**
|
||||
* 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 ScreenRecordParameters {
|
||||
|
||||
public final EnumScreenRecordingCodec codec;
|
||||
public final int resolutionDivisior;
|
||||
public final int videoBitsPerSecond;
|
||||
public final int audioBitsPerSecond;
|
||||
public final int captureFrameRate;
|
||||
|
||||
public ScreenRecordParameters(EnumScreenRecordingCodec codec, int resolutionDivisior, int videoBitsPerSecond,
|
||||
int audioBitsPerSecond, int captureFrameRate) {
|
||||
this.codec = codec;
|
||||
this.resolutionDivisior = resolutionDivisior;
|
||||
this.videoBitsPerSecond = videoBitsPerSecond;
|
||||
this.audioBitsPerSecond = audioBitsPerSecond;
|
||||
this.captureFrameRate = captureFrameRate;
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,7 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
* Copyright (c) 2022-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
@ -18,28 +15,33 @@ import java.io.IOException;
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket69Pong extends IPacket {
|
||||
public class VFSFilenameIteratorNonRecursive implements VFSFilenameIterator {
|
||||
|
||||
public int protcolVersion;
|
||||
public String comment;
|
||||
public String brand;
|
||||
|
||||
public IPacket69Pong(int protcolVersion, String comment, String brand) {
|
||||
if(comment.length() > 255) {
|
||||
comment = comment.substring(0, 256);
|
||||
private final VFSFilenameIterator child;
|
||||
private final int pathCount;
|
||||
|
||||
public VFSFilenameIteratorNonRecursive(VFSFilenameIterator child, int pathCount) {
|
||||
this.child = child;
|
||||
this.pathCount = pathCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void next(String entry) {
|
||||
int i = countSlashes(entry);
|
||||
if(i == pathCount) {
|
||||
child.next(entry);
|
||||
}
|
||||
this.protcolVersion = protcolVersion;
|
||||
this.comment = comment;
|
||||
this.brand = brand;
|
||||
}
|
||||
|
||||
public IPacket69Pong() {
|
||||
public static int countSlashes(String str) {
|
||||
if(str.length() == 0) return -1;
|
||||
int j = 0;
|
||||
for(int i = 0, l = str.length(); i < l; ++i) {
|
||||
if(str.charAt(i) == '/') {
|
||||
++j;
|
||||
}
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
public void read(DataInputStream output) throws IOException {
|
||||
protcolVersion = output.read();
|
||||
comment = readASCII8(output);
|
||||
brand = readASCII8(output);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
|
||||
|
||||
/**
|
||||
* 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 WebViewOptions {
|
||||
|
||||
public EnumWebViewContentMode contentMode = EnumWebViewContentMode.BLOB_BASED;
|
||||
public String fallbackTitle = "WebView";
|
||||
public boolean scriptEnabled = false;
|
||||
public boolean strictCSPEnable = true;
|
||||
public boolean serverMessageAPIEnabled = false;
|
||||
public URI url = null;
|
||||
public byte[] blob = null;
|
||||
public EaglercraftUUID permissionsOriginUUID = null;
|
||||
|
||||
public WebViewOptions() {
|
||||
}
|
||||
|
||||
public WebViewOptions(boolean script, boolean serverMessageAPIEnabled, boolean strictCSPEnable, URI url) {
|
||||
this.contentMode = EnumWebViewContentMode.URL_BASED;
|
||||
this.scriptEnabled = script;
|
||||
this.strictCSPEnable = strictCSPEnable;
|
||||
this.serverMessageAPIEnabled = serverMessageAPIEnabled;
|
||||
this.url = url;
|
||||
this.permissionsOriginUUID = getURLOriginUUID(url);
|
||||
}
|
||||
|
||||
public WebViewOptions(boolean script, boolean serverMessageAPIEnabled, boolean strictCSPEnable, byte[] data, EaglercraftUUID permissionsOriginUUID) {
|
||||
this.contentMode = EnumWebViewContentMode.BLOB_BASED;
|
||||
this.scriptEnabled = script;
|
||||
this.strictCSPEnable = strictCSPEnable;
|
||||
this.serverMessageAPIEnabled = serverMessageAPIEnabled;
|
||||
this.blob = data;
|
||||
this.permissionsOriginUUID = permissionsOriginUUID;
|
||||
}
|
||||
|
||||
public static EaglercraftUUID getURLOriginUUID(URI url) {
|
||||
return EaglercraftUUID.nameUUIDFromBytes(("URLOrigin:" + url.toString()).getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public static EaglercraftUUID getEmbedOriginUUID(byte[] sha256) {
|
||||
byte[] vigg = "BlobOrigin:".getBytes(StandardCharsets.UTF_8);
|
||||
byte[] eagler = new byte[sha256.length + vigg.length];
|
||||
System.arraycopy(vigg, 0, eagler, 0, vigg.length);
|
||||
System.arraycopy(sha256, 0, eagler, vigg.length, sha256.length);
|
||||
return EaglercraftUUID.nameUUIDFromBytes(eagler);
|
||||
}
|
||||
|
||||
}
|
@ -41,14 +41,14 @@ public interface Buffer {
|
||||
|
||||
boolean hasRemaining();
|
||||
|
||||
boolean isReadOnly();
|
||||
|
||||
boolean hasArray();
|
||||
|
||||
Object array();
|
||||
|
||||
int arrayOffset();
|
||||
|
||||
boolean isDirect();
|
||||
|
||||
static IndexOutOfBoundsException makeIOOBE(int idx) {
|
||||
return new IndexOutOfBoundsException("Index out of range: " + idx);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,12 +18,8 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer;
|
||||
*/
|
||||
public interface ByteBuffer extends Buffer {
|
||||
|
||||
ByteBuffer slice();
|
||||
|
||||
ByteBuffer duplicate();
|
||||
|
||||
ByteBuffer asReadOnlyBuffer();
|
||||
|
||||
byte get();
|
||||
|
||||
ByteBuffer put(byte b);
|
||||
@ -42,10 +38,6 @@ public interface ByteBuffer extends Buffer {
|
||||
|
||||
ByteBuffer put(byte[] src);
|
||||
|
||||
int arrayOffset();
|
||||
|
||||
ByteBuffer compact();
|
||||
|
||||
char getChar();
|
||||
|
||||
ByteBuffer putChar(char value);
|
||||
@ -54,7 +46,7 @@ public interface ByteBuffer extends Buffer {
|
||||
|
||||
ByteBuffer putChar(int index, char value);
|
||||
|
||||
public abstract short getShort();
|
||||
short getShort();
|
||||
|
||||
ByteBuffer putShort(short value);
|
||||
|
||||
@ -106,4 +98,6 @@ public interface ByteBuffer extends Buffer {
|
||||
|
||||
ByteBuffer position(int newPosition);
|
||||
|
||||
byte[] array();
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
|
@ -17,12 +17,8 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer;
|
||||
*/
|
||||
public interface FloatBuffer extends Buffer {
|
||||
|
||||
FloatBuffer slice();
|
||||
|
||||
FloatBuffer duplicate();
|
||||
|
||||
FloatBuffer asReadOnlyBuffer();
|
||||
|
||||
float get();
|
||||
|
||||
FloatBuffer put(float b);
|
||||
@ -45,10 +41,6 @@ public interface FloatBuffer extends Buffer {
|
||||
|
||||
FloatBuffer put(float[] src);
|
||||
|
||||
int getArrayOffset();
|
||||
|
||||
FloatBuffer compact();
|
||||
|
||||
boolean isDirect();
|
||||
|
||||
FloatBuffer mark();
|
||||
@ -64,6 +56,8 @@ public interface FloatBuffer extends Buffer {
|
||||
FloatBuffer limit(int newLimit);
|
||||
|
||||
FloatBuffer position(int newPosition);
|
||||
|
||||
|
||||
float[] array();
|
||||
|
||||
}
|
||||
|
||||
|
@ -17,12 +17,8 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer;
|
||||
*/
|
||||
public interface IntBuffer extends Buffer {
|
||||
|
||||
IntBuffer slice();
|
||||
|
||||
IntBuffer duplicate();
|
||||
|
||||
IntBuffer asReadOnlyBuffer();
|
||||
|
||||
int get();
|
||||
|
||||
IntBuffer put(int b);
|
||||
@ -45,10 +41,6 @@ public interface IntBuffer extends Buffer {
|
||||
|
||||
IntBuffer put(int[] src);
|
||||
|
||||
int getArrayOffset();
|
||||
|
||||
IntBuffer compact();
|
||||
|
||||
boolean isDirect();
|
||||
|
||||
IntBuffer mark();
|
||||
@ -64,6 +56,8 @@ public interface IntBuffer extends Buffer {
|
||||
IntBuffer limit(int newLimit);
|
||||
|
||||
IntBuffer position(int newPosition);
|
||||
|
||||
|
||||
int[] array();
|
||||
|
||||
}
|
||||
|
||||
|
@ -17,12 +17,8 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer;
|
||||
*/
|
||||
public interface ShortBuffer extends Buffer {
|
||||
|
||||
ShortBuffer slice();
|
||||
|
||||
ShortBuffer duplicate();
|
||||
|
||||
ShortBuffer asReadOnlyBuffer();
|
||||
|
||||
short get();
|
||||
|
||||
ShortBuffer put(short b);
|
||||
@ -45,10 +41,6 @@ public interface ShortBuffer extends Buffer {
|
||||
|
||||
ShortBuffer put(short[] src);
|
||||
|
||||
int getArrayOffset();
|
||||
|
||||
ShortBuffer compact();
|
||||
|
||||
boolean isDirect();
|
||||
|
||||
ShortBuffer mark();
|
||||
@ -64,5 +56,7 @@ public interface ShortBuffer extends Buffer {
|
||||
ShortBuffer limit(int newLimit);
|
||||
|
||||
ShortBuffer position(int newPosition);
|
||||
|
||||
|
||||
short[] array();
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal.vfs2;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IEaglerFilesystem;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.VFSFilenameIterator;
|
||||
|
||||
/**
|
||||
@ -19,15 +20,17 @@ import net.lax1dude.eaglercraft.v1_8.internal.VFSFilenameIterator;
|
||||
*/
|
||||
class VFSFilenameIteratorImpl implements VFSFilenameIterator {
|
||||
|
||||
protected IEaglerFilesystem fs;
|
||||
protected VFSIterator2 itr;
|
||||
|
||||
VFSFilenameIteratorImpl(VFSIterator2 itr) {
|
||||
VFSFilenameIteratorImpl(IEaglerFilesystem fs, VFSIterator2 itr) {
|
||||
this.fs = fs;
|
||||
this.itr = itr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void next(String entry) {
|
||||
itr.next(new VFile2(entry));
|
||||
itr.next(VFile2.create(fs, entry));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package net.lax1dude.eaglercraft.v1_8.internal.vfs2;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IEaglerFilesystem;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.VFSFilenameIterator;
|
||||
|
||||
/**
|
||||
@ -21,15 +22,17 @@ import net.lax1dude.eaglercraft.v1_8.internal.VFSFilenameIterator;
|
||||
*/
|
||||
class VFSListFilesIteratorImpl implements VFSFilenameIterator {
|
||||
|
||||
protected IEaglerFilesystem fs;
|
||||
protected List<VFile2> list;
|
||||
|
||||
VFSListFilesIteratorImpl(List<VFile2> list) {
|
||||
VFSListFilesIteratorImpl(IEaglerFilesystem fs, List<VFile2> list) {
|
||||
this.fs = fs;
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void next(String entry) {
|
||||
list.add(new VFile2(entry));
|
||||
list.add(VFile2.create(fs, entry));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,9 +5,10 @@ import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagUtils;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformFilesystem;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IEaglerFilesystem;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
|
||||
|
||||
@ -31,6 +32,12 @@ public class VFile2 {
|
||||
public static final String pathSeperator = "/";
|
||||
public static final String[] altPathSeperator = new String[] { "\\" };
|
||||
|
||||
static IEaglerFilesystem primaryFilesystem = null;
|
||||
|
||||
public static void setPrimaryFilesystem(IEaglerFilesystem fs) {
|
||||
primaryFilesystem = fs;
|
||||
}
|
||||
|
||||
public static String normalizePath(String p) {
|
||||
for(int i = 0; i < altPathSeperator.length; ++i) {
|
||||
p = p.replace(altPathSeperator[i], pathSeperator);
|
||||
@ -53,9 +60,11 @@ public class VFile2 {
|
||||
}
|
||||
|
||||
protected String path;
|
||||
protected IEaglerFilesystem myFilesystem;
|
||||
protected Supplier<IEaglerFilesystem> myFilesystemProvider;
|
||||
|
||||
public static String createPath(Object... p) {
|
||||
ArrayList<String> r = new ArrayList();
|
||||
ArrayList<String> r = new ArrayList<>();
|
||||
for(int i = 0; i < p.length; ++i) {
|
||||
if(p[i] == null) {
|
||||
continue;
|
||||
@ -94,13 +103,45 @@ public class VFile2 {
|
||||
}
|
||||
}
|
||||
|
||||
public VFile2(Object... p) {
|
||||
this.path = createPath(p);
|
||||
public static VFile2 create(IEaglerFilesystem fs, Object... path) {
|
||||
return new VFile2(createPath(path), fs);
|
||||
}
|
||||
|
||||
public static VFile2 create(Supplier<IEaglerFilesystem> fs, Object... path) {
|
||||
return new VFile2(createPath(path), fs);
|
||||
}
|
||||
|
||||
public VFile2(Object... path) {
|
||||
this(createPath(path), primaryFilesystem);
|
||||
}
|
||||
|
||||
private VFile2(String path, IEaglerFilesystem fs) {
|
||||
this.path = path;
|
||||
this.myFilesystem = fs;
|
||||
}
|
||||
|
||||
private VFile2(String path, Supplier<IEaglerFilesystem> fs) {
|
||||
this.path = path;
|
||||
this.myFilesystemProvider = fs;
|
||||
}
|
||||
|
||||
protected IEaglerFilesystem getFS() {
|
||||
if(myFilesystem == null) {
|
||||
if(myFilesystemProvider != null) {
|
||||
myFilesystem = myFilesystemProvider.get();
|
||||
}else {
|
||||
myFilesystem = primaryFilesystem;
|
||||
}
|
||||
if(myFilesystem == null) {
|
||||
throw new IllegalStateException("The filesystem has not been initialized yet!");
|
||||
}
|
||||
}
|
||||
return myFilesystem;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
assertNotRelative();
|
||||
return new VFileInputStream(PlatformFilesystem.eaglerRead(path));
|
||||
return new VFileInputStream(getFS().eaglerRead(path));
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
@ -121,7 +162,7 @@ public class VFile2 {
|
||||
}
|
||||
|
||||
public boolean canRead() {
|
||||
return !isRelative() && PlatformFilesystem.eaglerExists(path);
|
||||
return !isRelative() && getFS().eaglerExists(path);
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
@ -160,15 +201,15 @@ public class VFile2 {
|
||||
}
|
||||
|
||||
public boolean exists() {
|
||||
return !isRelative() && PlatformFilesystem.eaglerExists(path);
|
||||
return !isRelative() && getFS().eaglerExists(path);
|
||||
}
|
||||
|
||||
public boolean delete() {
|
||||
return !isRelative() && PlatformFilesystem.eaglerDelete(path);
|
||||
return !isRelative() && getFS().eaglerDelete(path);
|
||||
}
|
||||
|
||||
public boolean renameTo(String p) {
|
||||
if(!isRelative() && PlatformFilesystem.eaglerMove(path, p)) {
|
||||
if(!isRelative() && getFS().eaglerMove(path, p)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -179,7 +220,7 @@ public class VFile2 {
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return isRelative() ? -1 : PlatformFilesystem.eaglerSize(path);
|
||||
return isRelative() ? -1 : getFS().eaglerSize(path);
|
||||
}
|
||||
|
||||
public byte[] getAllBytes() {
|
||||
@ -187,7 +228,7 @@ public class VFile2 {
|
||||
if(!exists()) {
|
||||
return null;
|
||||
}
|
||||
ByteBuffer readBuffer = PlatformFilesystem.eaglerRead(path);
|
||||
ByteBuffer readBuffer = getFS().eaglerRead(path);
|
||||
byte[] copyBuffer = PlatformRuntime.castNativeByteBuffer(readBuffer);
|
||||
if(copyBuffer != null) {
|
||||
return copyBuffer;
|
||||
@ -225,14 +266,14 @@ public class VFile2 {
|
||||
assertNotRelative();
|
||||
ByteBuffer copyBuffer = PlatformRuntime.castPrimitiveByteArray(bytes);
|
||||
if(copyBuffer != null) {
|
||||
PlatformFilesystem.eaglerWrite(path, copyBuffer);
|
||||
getFS().eaglerWrite(path, copyBuffer);
|
||||
return;
|
||||
}
|
||||
copyBuffer = PlatformRuntime.allocateByteBuffer(bytes.length);
|
||||
try {
|
||||
copyBuffer.put(bytes);
|
||||
copyBuffer.flip();
|
||||
PlatformFilesystem.eaglerWrite(path, copyBuffer);
|
||||
getFS().eaglerWrite(path, copyBuffer);
|
||||
}finally {
|
||||
PlatformRuntime.freeByteBuffer(copyBuffer);
|
||||
}
|
||||
@ -240,24 +281,30 @@ public class VFile2 {
|
||||
|
||||
public void iterateFiles(VFSIterator2 itr, boolean recursive) {
|
||||
assertNotRelative();
|
||||
PlatformFilesystem.eaglerIterate(path, new VFSFilenameIteratorImpl(itr), recursive);
|
||||
IEaglerFilesystem fs = getFS();
|
||||
fs.eaglerIterate(path, new VFSFilenameIteratorImpl(fs, itr), recursive);
|
||||
}
|
||||
|
||||
public List<String> listFilenames(boolean recursive) {
|
||||
List<String> ret = new ArrayList();
|
||||
PlatformFilesystem.eaglerIterate(path, new VFSListFilenamesIteratorImpl(ret), recursive);
|
||||
List<String> ret = new ArrayList<>();
|
||||
getFS().eaglerIterate(path, new VFSListFilenamesIteratorImpl(ret), recursive);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public List<VFile2> listFiles(boolean recursive) {
|
||||
List<VFile2> ret = new ArrayList();
|
||||
PlatformFilesystem.eaglerIterate(path, new VFSListFilesIteratorImpl(ret), recursive);
|
||||
List<VFile2> ret = new ArrayList<>();
|
||||
IEaglerFilesystem fs = getFS();
|
||||
fs.eaglerIterate(path, new VFSListFilesIteratorImpl(fs, ret), recursive);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int copyFile(VFile2 src, VFile2 dst) {
|
||||
src.assertNotRelative();
|
||||
dst.assertNotRelative();
|
||||
return PlatformFilesystem.eaglerCopy(src.path, dst.path);
|
||||
IEaglerFilesystem sfs = src.getFS();
|
||||
if(sfs != dst.getFS()) {
|
||||
throw new UnsupportedOperationException("Cannot copy file between filesystems!");
|
||||
}
|
||||
return sfs.eaglerCopy(src.path, dst.path);
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@ package net.lax1dude.eaglercraft.v1_8.internal.vfs2;
|
||||
import java.io.IOException;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EaglerOutputStream;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformFilesystem;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
|
||||
|
||||
@ -41,7 +40,7 @@ class VFileOutputStream extends EaglerOutputStream {
|
||||
copyBuffer.put(buf, 0, count);
|
||||
copyBuffer.flip();
|
||||
try {
|
||||
PlatformFilesystem.eaglerWrite(vfsFile.path, copyBuffer);
|
||||
vfsFile.getFS().eaglerWrite(vfsFile.path, copyBuffer);
|
||||
}catch(Throwable t) {
|
||||
throw new IOException("Could not write stream contents to file!", t);
|
||||
}
|
||||
|
@ -54,10 +54,10 @@ import net.minecraft.world.gen.ChunkProviderSettings;
|
||||
*/
|
||||
public class JSONTypeProvider {
|
||||
|
||||
private static final Map<Class<?>,JSONTypeSerializer<?,?>> serializers = new HashMap();
|
||||
private static final Map<Class<?>,JSONTypeDeserializer<?,?>> deserializers = new HashMap();
|
||||
private static final Map<Class<?>,JSONTypeSerializer<?,?>> serializers = new HashMap<>();
|
||||
private static final Map<Class<?>,JSONTypeDeserializer<?,?>> deserializers = new HashMap<>();
|
||||
|
||||
private static final List<JSONDataParserImpl> parsers = new ArrayList();
|
||||
private static final List<JSONDataParserImpl> parsers = new ArrayList<>();
|
||||
|
||||
public static <J> J serialize(Object object) throws JSONException {
|
||||
JSONTypeSerializer<Object,J> ser = (JSONTypeSerializer<Object,J>) serializers.get(object.getClass());
|
||||
|
@ -30,7 +30,7 @@ public class SoundMapDeserializer implements JSONTypeDeserializer<JSONObject, So
|
||||
|
||||
@Override
|
||||
public SoundMap deserialize(JSONObject json) throws JSONException {
|
||||
Map<String, SoundList> soundsMap = new HashMap();
|
||||
Map<String, SoundList> soundsMap = new HashMap<>();
|
||||
for(String str : json.keySet()) {
|
||||
soundsMap.put(str, JSONTypeProvider.deserialize(json.getJSONObject(str), SoundList.class));
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class LogManager {
|
||||
|
||||
private static final Map<String,Logger> loggerInstances = new HashMap();
|
||||
private static final Map<String,Logger> loggerInstances = new HashMap<>();
|
||||
|
||||
public static final Object logLock = new Object();
|
||||
public static Level logLevel = Level.DEBUG;
|
||||
|
@ -101,7 +101,7 @@ public class Logger {
|
||||
log(Level.FATAL, msg);
|
||||
}
|
||||
|
||||
private static final SimpleDateFormat fmt = EagRuntime.fixDateFormat(new SimpleDateFormat("hh:mm:ss+SSS"));
|
||||
private static final SimpleDateFormat fmt = new SimpleDateFormat("hh:mm:ss+SSS");
|
||||
private static final Date dateInstance = new Date();
|
||||
|
||||
public void log(Level level, String msg) {
|
||||
|
@ -5,6 +5,7 @@ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU;
|
||||
@ -35,7 +36,7 @@ public class ChunkUpdateManager {
|
||||
private int chunkUpdatesQueuedLast = 0;
|
||||
private long chunkUpdatesTotalLastUpdate = 0l;
|
||||
|
||||
private final List<ChunkCompileTaskGenerator> queue = new LinkedList();
|
||||
private final List<ChunkCompileTaskGenerator> queue = new LinkedList<>();
|
||||
|
||||
public ChunkUpdateManager() {
|
||||
worldVertexUploader = new WorldVertexBufferUploader();
|
||||
@ -108,8 +109,8 @@ public class ChunkUpdateManager {
|
||||
return false;
|
||||
}else {
|
||||
boolean flag = false;
|
||||
long millis = System.currentTimeMillis();
|
||||
List<ChunkCompileTaskGenerator> droppedUpdates = new LinkedList();
|
||||
long millis = EagRuntime.steadyTimeMillis();
|
||||
List<ChunkCompileTaskGenerator> droppedUpdates = new LinkedList<>();
|
||||
while(!queue.isEmpty()) {
|
||||
ChunkCompileTaskGenerator generator = queue.remove(0);
|
||||
|
||||
@ -125,7 +126,7 @@ public class ChunkUpdateManager {
|
||||
|
||||
++chunkUpdatesTotal;
|
||||
|
||||
if(timeout < System.nanoTime()) {
|
||||
if(timeout < EagRuntime.nanoTime()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -176,7 +177,7 @@ public class ChunkUpdateManager {
|
||||
if (chunkcompiletaskgenerator == null) {
|
||||
return true;
|
||||
}
|
||||
chunkcompiletaskgenerator.goddamnFuckingTimeout = System.currentTimeMillis();
|
||||
chunkcompiletaskgenerator.goddamnFuckingTimeout = EagRuntime.steadyTimeMillis();
|
||||
if(queue.size() < 100) {
|
||||
chunkcompiletaskgenerator.addFinishRunnable(new Runnable() {
|
||||
@Override
|
||||
@ -219,7 +220,7 @@ public class ChunkUpdateManager {
|
||||
}
|
||||
|
||||
public String getDebugInfo() {
|
||||
long millis = System.currentTimeMillis();
|
||||
long millis = EagRuntime.steadyTimeMillis();
|
||||
|
||||
if(millis - chunkUpdatesTotalLastUpdate > 500l) {
|
||||
chunkUpdatesTotalLastUpdate = millis;
|
||||
|
@ -105,7 +105,7 @@ public class EaglerFolderResourcePack extends AbstractResourcePack {
|
||||
}
|
||||
try {
|
||||
JSONArray json = (new JSONObject(str)).getJSONArray("resourcePacks");
|
||||
List<EaglerFolderResourcePack> ret = new ArrayList(json.length());
|
||||
List<EaglerFolderResourcePack> ret = new ArrayList<>(json.length());
|
||||
for(int i = 0, l = json.length(); i < l; ++i) {
|
||||
JSONObject jp = json.getJSONObject(i);
|
||||
String folderName = jp.getString("folder");
|
||||
|
@ -30,6 +30,15 @@ public class EaglerFontRenderer extends FontRenderer {
|
||||
|
||||
private final int[] temporaryCodepointArray = new int[6553];
|
||||
|
||||
public static FontRenderer createSupportedFontRenderer(GameSettings gameSettingsIn, ResourceLocation location,
|
||||
TextureManager textureManagerIn, boolean unicode) {
|
||||
if(EaglercraftGPU.checkInstancingCapable()) {
|
||||
return new EaglerFontRenderer(gameSettingsIn, location, textureManagerIn, unicode);
|
||||
}else {
|
||||
return new FontRenderer(gameSettingsIn, location, textureManagerIn, unicode);
|
||||
}
|
||||
}
|
||||
|
||||
public EaglerFontRenderer(GameSettings gameSettingsIn, ResourceLocation location, TextureManager textureManagerIn,
|
||||
boolean unicode) {
|
||||
super(gameSettingsIn, location, textureManagerIn, unicode);
|
||||
@ -116,15 +125,16 @@ public class EaglerFontRenderer extends FontRenderer {
|
||||
++i;
|
||||
} else {
|
||||
int j = temporaryCodepointArray[i];
|
||||
if(j > 255) continue;
|
||||
|
||||
if (this.randomStyle && j != -1) {
|
||||
int k = this.getCharWidth(c0);
|
||||
String chars = "\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000";
|
||||
char[] chars = FontRenderer.codepointLookup;
|
||||
|
||||
char c1;
|
||||
while (true) {
|
||||
j = this.fontRandom.nextInt(chars.length());
|
||||
c1 = chars.charAt(j);
|
||||
j = this.fontRandom.nextInt(chars.length);
|
||||
c1 = chars[j];
|
||||
if (k == this.getCharWidth(c1)) {
|
||||
break;
|
||||
}
|
||||
@ -220,8 +230,7 @@ public class EaglerFontRenderer extends FontRenderer {
|
||||
|
||||
private boolean decodeASCIICodepointsAndValidate(String str) {
|
||||
for(int i = 0, l = str.length(); i < l; ++i) {
|
||||
int j = "\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000\u00a7"
|
||||
.indexOf(str.charAt(i));
|
||||
int j = FontMappingHelper.lookupChar(str.charAt(i), true);
|
||||
if(j != -1) {
|
||||
temporaryCodepointArray[i] = j;
|
||||
}else {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.minecraft;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
@ -229,10 +228,10 @@ public class EaglerTextureAtlasSprite {
|
||||
int l = i;
|
||||
this.height = this.width;
|
||||
if (meta.getFrameCount() > 0) {
|
||||
Iterator iterator = meta.getFrameIndexSet().iterator();
|
||||
Iterator<Integer> iterator = meta.getFrameIndexSet().iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
int i1 = ((Integer) iterator.next()).intValue();
|
||||
int i1 = iterator.next().intValue();
|
||||
if (i1 >= j1) {
|
||||
throw new RuntimeException("invalid frameindex " + i1);
|
||||
}
|
||||
@ -243,7 +242,7 @@ public class EaglerTextureAtlasSprite {
|
||||
|
||||
this.animationMetadata = meta;
|
||||
} else {
|
||||
ArrayList arraylist = Lists.newArrayList();
|
||||
List<AnimationFrame> arraylist = Lists.newArrayList();
|
||||
|
||||
for (int l1 = 0; l1 < j1; ++l1) {
|
||||
this.framesTextureData.add(getFrameTextureData(aint, k1, l, l1));
|
||||
@ -258,10 +257,10 @@ public class EaglerTextureAtlasSprite {
|
||||
}
|
||||
|
||||
public void generateMipmaps(int level) {
|
||||
ArrayList arraylist = Lists.newArrayList();
|
||||
List<int[][]> arraylist = Lists.newArrayList();
|
||||
|
||||
for (int i = 0; i < this.framesTextureData.size(); ++i) {
|
||||
final int[][] aint = (int[][]) this.framesTextureData.get(i);
|
||||
final int[][] aint = this.framesTextureData.get(i);
|
||||
if (aint != null) {
|
||||
try {
|
||||
arraylist.add(TextureUtil.generateMipmapData(level, this.width, aint));
|
||||
|
@ -0,0 +1,20 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.minecraft;
|
||||
|
||||
/**
|
||||
* 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 EnumInputEvent {
|
||||
CLIPBOARD_COPY, CLIPBOARD_PASTE;
|
||||
}
|
@ -0,0 +1,525 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.minecraft;
|
||||
|
||||
/**
|
||||
* 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 FontMappingHelper {
|
||||
|
||||
public static int lookupChar(char c, boolean incSel) {
|
||||
switch(c) {
|
||||
case 167:
|
||||
return incSel ? 256 : -1;
|
||||
case 192:
|
||||
return 0;
|
||||
case 193:
|
||||
return 1;
|
||||
case 194:
|
||||
return 2;
|
||||
case 200:
|
||||
return 3;
|
||||
case 202:
|
||||
return 4;
|
||||
case 203:
|
||||
return 5;
|
||||
case 205:
|
||||
return 6;
|
||||
case 211:
|
||||
return 7;
|
||||
case 212:
|
||||
return 8;
|
||||
case 213:
|
||||
return 9;
|
||||
case 218:
|
||||
return 10;
|
||||
case 223:
|
||||
return 11;
|
||||
case 227:
|
||||
return 12;
|
||||
case 245:
|
||||
return 13;
|
||||
case 287:
|
||||
return 14;
|
||||
case 304:
|
||||
return 15;
|
||||
case 305:
|
||||
return 16;
|
||||
case 338:
|
||||
return 17;
|
||||
case 339:
|
||||
return 18;
|
||||
case 350:
|
||||
return 19;
|
||||
case 351:
|
||||
return 20;
|
||||
case 372:
|
||||
return 21;
|
||||
case 373:
|
||||
return 22;
|
||||
case 382:
|
||||
return 23;
|
||||
case 519:
|
||||
return 24;
|
||||
case 0:
|
||||
return 25;
|
||||
case 32:
|
||||
return 32;
|
||||
case 33:
|
||||
return 33;
|
||||
case 34:
|
||||
return 34;
|
||||
case 35:
|
||||
return 35;
|
||||
case 36:
|
||||
return 36;
|
||||
case 37:
|
||||
return 37;
|
||||
case 38:
|
||||
return 38;
|
||||
case 39:
|
||||
return 39;
|
||||
case 40:
|
||||
return 40;
|
||||
case 41:
|
||||
return 41;
|
||||
case 42:
|
||||
return 42;
|
||||
case 43:
|
||||
return 43;
|
||||
case 44:
|
||||
return 44;
|
||||
case 45:
|
||||
return 45;
|
||||
case 46:
|
||||
return 46;
|
||||
case 47:
|
||||
return 47;
|
||||
case 48:
|
||||
return 48;
|
||||
case 49:
|
||||
return 49;
|
||||
case 50:
|
||||
return 50;
|
||||
case 51:
|
||||
return 51;
|
||||
case 52:
|
||||
return 52;
|
||||
case 53:
|
||||
return 53;
|
||||
case 54:
|
||||
return 54;
|
||||
case 55:
|
||||
return 55;
|
||||
case 56:
|
||||
return 56;
|
||||
case 57:
|
||||
return 57;
|
||||
case 58:
|
||||
return 58;
|
||||
case 59:
|
||||
return 59;
|
||||
case 60:
|
||||
return 60;
|
||||
case 61:
|
||||
return 61;
|
||||
case 62:
|
||||
return 62;
|
||||
case 63:
|
||||
return 63;
|
||||
case 64:
|
||||
return 64;
|
||||
case 65:
|
||||
return 65;
|
||||
case 66:
|
||||
return 66;
|
||||
case 67:
|
||||
return 67;
|
||||
case 68:
|
||||
return 68;
|
||||
case 69:
|
||||
return 69;
|
||||
case 70:
|
||||
return 70;
|
||||
case 71:
|
||||
return 71;
|
||||
case 72:
|
||||
return 72;
|
||||
case 73:
|
||||
return 73;
|
||||
case 74:
|
||||
return 74;
|
||||
case 75:
|
||||
return 75;
|
||||
case 76:
|
||||
return 76;
|
||||
case 77:
|
||||
return 77;
|
||||
case 78:
|
||||
return 78;
|
||||
case 79:
|
||||
return 79;
|
||||
case 80:
|
||||
return 80;
|
||||
case 81:
|
||||
return 81;
|
||||
case 82:
|
||||
return 82;
|
||||
case 83:
|
||||
return 83;
|
||||
case 84:
|
||||
return 84;
|
||||
case 85:
|
||||
return 85;
|
||||
case 86:
|
||||
return 86;
|
||||
case 87:
|
||||
return 87;
|
||||
case 88:
|
||||
return 88;
|
||||
case 89:
|
||||
return 89;
|
||||
case 90:
|
||||
return 90;
|
||||
case 91:
|
||||
return 91;
|
||||
case 92:
|
||||
return 92;
|
||||
case 93:
|
||||
return 93;
|
||||
case 94:
|
||||
return 94;
|
||||
case 95:
|
||||
return 95;
|
||||
case 96:
|
||||
return 96;
|
||||
case 97:
|
||||
return 97;
|
||||
case 98:
|
||||
return 98;
|
||||
case 99:
|
||||
return 99;
|
||||
case 100:
|
||||
return 100;
|
||||
case 101:
|
||||
return 101;
|
||||
case 102:
|
||||
return 102;
|
||||
case 103:
|
||||
return 103;
|
||||
case 104:
|
||||
return 104;
|
||||
case 105:
|
||||
return 105;
|
||||
case 106:
|
||||
return 106;
|
||||
case 107:
|
||||
return 107;
|
||||
case 108:
|
||||
return 108;
|
||||
case 109:
|
||||
return 109;
|
||||
case 110:
|
||||
return 110;
|
||||
case 111:
|
||||
return 111;
|
||||
case 112:
|
||||
return 112;
|
||||
case 113:
|
||||
return 113;
|
||||
case 114:
|
||||
return 114;
|
||||
case 115:
|
||||
return 115;
|
||||
case 116:
|
||||
return 116;
|
||||
case 117:
|
||||
return 117;
|
||||
case 118:
|
||||
return 118;
|
||||
case 119:
|
||||
return 119;
|
||||
case 120:
|
||||
return 120;
|
||||
case 121:
|
||||
return 121;
|
||||
case 122:
|
||||
return 122;
|
||||
case 123:
|
||||
return 123;
|
||||
case 124:
|
||||
return 124;
|
||||
case 125:
|
||||
return 125;
|
||||
case 126:
|
||||
return 126;
|
||||
case 199:
|
||||
return 128;
|
||||
case 252:
|
||||
return 129;
|
||||
case 233:
|
||||
return 130;
|
||||
case 226:
|
||||
return 131;
|
||||
case 228:
|
||||
return 132;
|
||||
case 224:
|
||||
return 133;
|
||||
case 229:
|
||||
return 134;
|
||||
case 231:
|
||||
return 135;
|
||||
case 234:
|
||||
return 136;
|
||||
case 235:
|
||||
return 137;
|
||||
case 232:
|
||||
return 138;
|
||||
case 239:
|
||||
return 139;
|
||||
case 238:
|
||||
return 140;
|
||||
case 236:
|
||||
return 141;
|
||||
case 196:
|
||||
return 142;
|
||||
case 197:
|
||||
return 143;
|
||||
case 201:
|
||||
return 144;
|
||||
case 230:
|
||||
return 145;
|
||||
case 198:
|
||||
return 146;
|
||||
case 244:
|
||||
return 147;
|
||||
case 246:
|
||||
return 148;
|
||||
case 242:
|
||||
return 149;
|
||||
case 251:
|
||||
return 150;
|
||||
case 249:
|
||||
return 151;
|
||||
case 255:
|
||||
return 152;
|
||||
case 214:
|
||||
return 153;
|
||||
case 220:
|
||||
return 154;
|
||||
case 248:
|
||||
return 155;
|
||||
case 163:
|
||||
return 156;
|
||||
case 216:
|
||||
return 157;
|
||||
case 215:
|
||||
return 158;
|
||||
case 402:
|
||||
return 159;
|
||||
case 225:
|
||||
return 160;
|
||||
case 237:
|
||||
return 161;
|
||||
case 243:
|
||||
return 162;
|
||||
case 250:
|
||||
return 163;
|
||||
case 241:
|
||||
return 164;
|
||||
case 209:
|
||||
return 165;
|
||||
case 170:
|
||||
return 166;
|
||||
case 186:
|
||||
return 167;
|
||||
case 191:
|
||||
return 168;
|
||||
case 174:
|
||||
return 169;
|
||||
case 172:
|
||||
return 170;
|
||||
case 189:
|
||||
return 171;
|
||||
case 188:
|
||||
return 172;
|
||||
case 161:
|
||||
return 173;
|
||||
case 171:
|
||||
return 174;
|
||||
case 187:
|
||||
return 175;
|
||||
case 9617:
|
||||
return 176;
|
||||
case 9618:
|
||||
return 177;
|
||||
case 9619:
|
||||
return 178;
|
||||
case 9474:
|
||||
return 179;
|
||||
case 9508:
|
||||
return 180;
|
||||
case 9569:
|
||||
return 181;
|
||||
case 9570:
|
||||
return 182;
|
||||
case 9558:
|
||||
return 183;
|
||||
case 9557:
|
||||
return 184;
|
||||
case 9571:
|
||||
return 185;
|
||||
case 9553:
|
||||
return 186;
|
||||
case 9559:
|
||||
return 187;
|
||||
case 9565:
|
||||
return 188;
|
||||
case 9564:
|
||||
return 189;
|
||||
case 9563:
|
||||
return 190;
|
||||
case 9488:
|
||||
return 191;
|
||||
case 9492:
|
||||
return 192;
|
||||
case 9524:
|
||||
return 193;
|
||||
case 9516:
|
||||
return 194;
|
||||
case 9500:
|
||||
return 195;
|
||||
case 9472:
|
||||
return 196;
|
||||
case 9532:
|
||||
return 197;
|
||||
case 9566:
|
||||
return 198;
|
||||
case 9567:
|
||||
return 199;
|
||||
case 9562:
|
||||
return 200;
|
||||
case 9556:
|
||||
return 201;
|
||||
case 9577:
|
||||
return 202;
|
||||
case 9574:
|
||||
return 203;
|
||||
case 9568:
|
||||
return 204;
|
||||
case 9552:
|
||||
return 205;
|
||||
case 9580:
|
||||
return 206;
|
||||
case 9575:
|
||||
return 207;
|
||||
case 9576:
|
||||
return 208;
|
||||
case 9572:
|
||||
return 209;
|
||||
case 9573:
|
||||
return 210;
|
||||
case 9561:
|
||||
return 211;
|
||||
case 9560:
|
||||
return 212;
|
||||
case 9554:
|
||||
return 213;
|
||||
case 9555:
|
||||
return 214;
|
||||
case 9579:
|
||||
return 215;
|
||||
case 9578:
|
||||
return 216;
|
||||
case 9496:
|
||||
return 217;
|
||||
case 9484:
|
||||
return 218;
|
||||
case 9608:
|
||||
return 219;
|
||||
case 9604:
|
||||
return 220;
|
||||
case 9612:
|
||||
return 221;
|
||||
case 9616:
|
||||
return 222;
|
||||
case 9600:
|
||||
return 223;
|
||||
case 945:
|
||||
return 224;
|
||||
case 946:
|
||||
return 225;
|
||||
case 915:
|
||||
return 226;
|
||||
case 960:
|
||||
return 227;
|
||||
case 931:
|
||||
return 228;
|
||||
case 963:
|
||||
return 229;
|
||||
case 956:
|
||||
return 230;
|
||||
case 964:
|
||||
return 231;
|
||||
case 934:
|
||||
return 232;
|
||||
case 920:
|
||||
return 233;
|
||||
case 937:
|
||||
return 234;
|
||||
case 948:
|
||||
return 235;
|
||||
case 8734:
|
||||
return 236;
|
||||
case 8709:
|
||||
return 237;
|
||||
case 8712:
|
||||
return 238;
|
||||
case 8745:
|
||||
return 239;
|
||||
case 8801:
|
||||
return 240;
|
||||
case 177:
|
||||
return 241;
|
||||
case 8805:
|
||||
return 242;
|
||||
case 8804:
|
||||
return 243;
|
||||
case 8992:
|
||||
return 244;
|
||||
case 8993:
|
||||
return 245;
|
||||
case 247:
|
||||
return 246;
|
||||
case 8776:
|
||||
return 247;
|
||||
case 176:
|
||||
return 248;
|
||||
case 8729:
|
||||
return 249;
|
||||
case 183:
|
||||
return 250;
|
||||
case 8730:
|
||||
return 251;
|
||||
case 8319:
|
||||
return 252;
|
||||
case 178:
|
||||
return 253;
|
||||
case 9632:
|
||||
return 254;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.minecraft;
|
||||
|
||||
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.Mouse;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.EnumCursorType;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
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 GuiButtonWithStupidIcons extends GuiButton {
|
||||
|
||||
protected ResourceLocation leftIcon;
|
||||
protected float leftIconAspect;
|
||||
protected ResourceLocation rightIcon;
|
||||
protected float rightIconAspect;
|
||||
|
||||
public GuiButtonWithStupidIcons(int buttonId, int x, int y, int widthIn, int heightIn, String buttonText) {
|
||||
super(buttonId, x, y, widthIn, heightIn, buttonText);
|
||||
}
|
||||
|
||||
public GuiButtonWithStupidIcons(int buttonId, int x, int y, String buttonText) {
|
||||
super(buttonId, x, y, buttonText);
|
||||
}
|
||||
|
||||
public GuiButtonWithStupidIcons(int buttonId, int x, int y, int widthIn, int heightIn, String buttonText,
|
||||
ResourceLocation leftIcon, float leftIconAspect, ResourceLocation rightIcon, float rightIconAspect) {
|
||||
super(buttonId, x, y, widthIn, heightIn, buttonText);
|
||||
this.leftIcon = leftIcon;
|
||||
this.leftIconAspect = leftIconAspect;
|
||||
this.rightIcon = rightIcon;
|
||||
this.rightIconAspect = rightIconAspect;
|
||||
}
|
||||
|
||||
public GuiButtonWithStupidIcons(int buttonId, int x, int y, String buttonText, ResourceLocation leftIcon,
|
||||
float leftIconAspect, ResourceLocation rightIcon, float rightIconAspect) {
|
||||
super(buttonId, x, y, buttonText);
|
||||
this.leftIcon = leftIcon;
|
||||
this.leftIconAspect = leftIconAspect;
|
||||
this.rightIcon = rightIcon;
|
||||
this.rightIconAspect = rightIconAspect;
|
||||
}
|
||||
|
||||
public ResourceLocation getLeftIcon() {
|
||||
return leftIcon;
|
||||
}
|
||||
|
||||
public ResourceLocation getRightIcon() {
|
||||
return rightIcon;
|
||||
}
|
||||
|
||||
public void setLeftIcon(ResourceLocation leftIcon, float aspectRatio) {
|
||||
this.leftIcon = leftIcon;
|
||||
this.leftIconAspect = aspectRatio;
|
||||
}
|
||||
|
||||
public void setRightIcon(ResourceLocation rightIcon, float aspectRatio) {
|
||||
this.rightIcon = rightIcon;
|
||||
this.rightIconAspect = aspectRatio;
|
||||
}
|
||||
|
||||
public void drawButton(Minecraft mc, int mouseX, int mouseY) {
|
||||
if (this.visible) {
|
||||
FontRenderer fontrenderer = mc.fontRendererObj;
|
||||
mc.getTextureManager().bindTexture(buttonTextures);
|
||||
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
this.hovered = mouseX >= this.xPosition && mouseY >= this.yPosition && mouseX < this.xPosition + this.width
|
||||
&& mouseY < this.yPosition + this.height;
|
||||
if (this.enabled && this.hovered) {
|
||||
Mouse.showCursor(EnumCursorType.HAND);
|
||||
}
|
||||
int i = this.getHoverState(this.hovered);
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1, 0);
|
||||
GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
this.drawTexturedModalRect(this.xPosition, this.yPosition, 0, 46 + i * 20, this.width / 2, this.height);
|
||||
this.drawTexturedModalRect(this.xPosition + this.width / 2, this.yPosition, 200 - this.width / 2,
|
||||
46 + i * 20, this.width / 2, this.height);
|
||||
this.mouseDragged(mc, mouseX, mouseY);
|
||||
int j = 14737632;
|
||||
if (!this.enabled) {
|
||||
j = 10526880;
|
||||
} else if (this.hovered) {
|
||||
j = 16777120;
|
||||
}
|
||||
|
||||
int strWidth = fontrenderer.getStringWidth(displayString);
|
||||
int strWidthAdj = strWidth - (leftIcon != null ? (int) (16 * leftIconAspect) : 0)
|
||||
+ (rightIcon != null ? (int) (16 * rightIconAspect) : 0);
|
||||
this.drawString(fontrenderer, this.displayString, this.xPosition + (this.width - strWidthAdj) / 2,
|
||||
this.yPosition + (this.height - 8) / 2, j);
|
||||
if(leftIcon != null) {
|
||||
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
mc.getTextureManager().bindTexture(leftIcon);
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate(this.xPosition + (this.width - strWidthAdj) / 2 - 3 - 16 * leftIconAspect, this.yPosition + 2, 0.0f);
|
||||
float f = 16.0f / 256.0f;
|
||||
GlStateManager.scale(f * leftIconAspect, f, f);
|
||||
this.drawTexturedModalRect(0, 0, 0, 0, 256, 256);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
if(rightIcon != null) {
|
||||
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
mc.getTextureManager().bindTexture(rightIcon);
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate(this.xPosition + (this.width - strWidthAdj) / 2 + strWidth + 3, this.yPosition + 2, 0.0f);
|
||||
float f = 16.0f / 256.0f;
|
||||
GlStateManager.scale(f * rightIconAspect, f, f);
|
||||
this.drawTexturedModalRect(0, 0, 0, 0, 256, 256);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.minecraft;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
@ -26,8 +28,8 @@ public class GuiScreenGenericErrorMessage extends GuiScreen {
|
||||
private GuiScreen cont;
|
||||
|
||||
public GuiScreenGenericErrorMessage(String str1, String str2, GuiScreen cont) {
|
||||
this.str1 = I18n.format(str1);
|
||||
this.str2 = I18n.format(str2);
|
||||
this.str1 = StringUtils.isAllEmpty(str1) ? "" : I18n.format(str1);
|
||||
this.str2 = StringUtils.isAllEmpty(str2) ? "" : I18n.format(str2);
|
||||
this.cont = cont;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,144 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.minecraft;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.Display;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
|
||||
/**
|
||||
* 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 GuiScreenVisualViewport extends GuiScreen {
|
||||
|
||||
protected int offsetX;
|
||||
protected int offsetY;
|
||||
|
||||
@Override
|
||||
public final void setWorldAndResolution(Minecraft mc, int width, int height) {
|
||||
Display.wasVisualViewportResized(); // clear state
|
||||
offsetX = Display.getVisualViewportX() * width / mc.displayWidth;
|
||||
offsetY = Display.getVisualViewportY() * height / mc.displayHeight;
|
||||
setWorldAndResolution0(mc, Display.getVisualViewportW() * width / mc.displayWidth,
|
||||
Display.getVisualViewportH() * height / mc.displayHeight);
|
||||
}
|
||||
|
||||
protected void setWorldAndResolution0(Minecraft mc, int width, int height) {
|
||||
super.setWorldAndResolution(mc, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void updateScreen() {
|
||||
if(Display.wasVisualViewportResized()) {
|
||||
setWorldAndResolution(mc, mc.scaledResolution.getScaledWidth(), mc.scaledResolution.getScaledHeight());
|
||||
}
|
||||
updateScreen0();
|
||||
}
|
||||
|
||||
protected void updateScreen0() {
|
||||
super.updateScreen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void drawScreen(int i, int j, float var3) {
|
||||
i -= offsetX;
|
||||
j -= offsetY;
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate(offsetX, offsetY, 0.0f);
|
||||
drawScreen0(i, j, var3);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
protected void drawScreen0(int i, int j, float var3) {
|
||||
super.drawScreen(i, j, var3);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void mouseClicked(int parInt1, int parInt2, int parInt3) {
|
||||
parInt1 -= offsetX;
|
||||
parInt2 -= offsetY;
|
||||
mouseClicked0(parInt1, parInt2, parInt3);
|
||||
}
|
||||
|
||||
protected void mouseClicked0(int parInt1, int parInt2, int parInt3) {
|
||||
super.mouseClicked(parInt1, parInt2, parInt3);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void mouseReleased(int i, int j, int k) {
|
||||
i -= offsetX;
|
||||
j -= offsetY;
|
||||
mouseReleased0(i, j, k);
|
||||
}
|
||||
|
||||
protected void mouseReleased0(int i, int j, int k) {
|
||||
super.mouseReleased(i, j, k);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void mouseClickMove(int var1, int var2, int var3, long var4) {
|
||||
var1 -= offsetX;
|
||||
var2 -= offsetY;
|
||||
mouseClickMove0(var1, var2, var3, var4);
|
||||
}
|
||||
|
||||
protected void mouseClickMove0(int var1, int var2, int var3, long var4) {
|
||||
super.mouseClickMove(var1, var2, var3, var4);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void touchEndMove(int parInt1, int parInt2, int parInt3) {
|
||||
parInt1 -= offsetX;
|
||||
parInt2 -= offsetY;
|
||||
touchEndMove0(parInt1, parInt2, parInt3);
|
||||
}
|
||||
|
||||
protected void touchEndMove0(int parInt1, int parInt2, int parInt3) {
|
||||
super.touchEndMove(parInt1, parInt2, parInt3);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void touchMoved(int parInt1, int parInt2, int parInt3) {
|
||||
parInt1 -= offsetX;
|
||||
parInt2 -= offsetY;
|
||||
touchMoved0(parInt1, parInt2, parInt3);
|
||||
}
|
||||
|
||||
protected void touchMoved0(int parInt1, int parInt2, int parInt3) {
|
||||
super.touchMoved(parInt1, parInt2, parInt3);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void touchStarted(int parInt1, int parInt2, int parInt3) {
|
||||
parInt1 -= offsetX;
|
||||
parInt2 -= offsetY;
|
||||
touchStarted0(parInt1, parInt2, parInt3);
|
||||
}
|
||||
|
||||
protected void touchStarted0(int parInt1, int parInt2, int parInt3) {
|
||||
super.touchStarted(parInt1, parInt2, parInt3);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void touchTapped(int parInt1, int parInt2, int parInt3) {
|
||||
parInt1 -= offsetX;
|
||||
parInt2 -= offsetY;
|
||||
touchTapped0(parInt1, parInt2, parInt3);
|
||||
}
|
||||
|
||||
protected void touchTapped0(int parInt1, int parInt2, int parInt3) {
|
||||
super.touchTapped(parInt1, parInt2, parInt3);
|
||||
}
|
||||
|
||||
}
|
@ -54,8 +54,8 @@ public class TextureAnimationCache {
|
||||
for(int i = 0; i < cacheTextures.length; ++i) {
|
||||
cacheTextures[i] = GlStateManager.generateTexture();
|
||||
GlStateManager.bindTexture(cacheTextures[i]);
|
||||
EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
}
|
||||
@ -123,6 +123,8 @@ public class TextureAnimationCache {
|
||||
if(cacheTextures == null) {
|
||||
throw new IllegalStateException("Cannot copy from uninitialized TextureAnimationCache");
|
||||
}
|
||||
GlStateManager.disableBlend();
|
||||
GlStateManager.disableAlpha();
|
||||
GlStateManager.bindTexture(cacheTextures[level]);
|
||||
TextureCopyUtil.srcSize(width >> level, (height >> level) * frameCount);
|
||||
TextureCopyUtil.blitTextureUsingViewports(0, h * animationFrame, dx, dy, w, h);
|
||||
|
@ -0,0 +1,46 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.notifications;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.util.IChatComponent;
|
||||
|
||||
/**
|
||||
* 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 CachedNotifBadgeTexture {
|
||||
|
||||
public final int glTexture;
|
||||
public final int scaleFactor;
|
||||
public final int width;
|
||||
public final int height;
|
||||
public final List<ClickEventZone> cursorEvents;
|
||||
public final IChatComponent rootClickEvent;
|
||||
public final boolean hasClickEvents;
|
||||
public final boolean hasHoverEvents;
|
||||
|
||||
protected CachedNotifBadgeTexture(int glTexture, int scaleFactor, int width, int height,
|
||||
List<ClickEventZone> cursorEvents, IChatComponent rootClickEvent, boolean hasClickEvents,
|
||||
boolean hasHoverEvents) {
|
||||
this.glTexture = glTexture;
|
||||
this.scaleFactor = scaleFactor;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.cursorEvents = cursorEvents;
|
||||
this.rootClickEvent = rootClickEvent;
|
||||
this.hasClickEvents = hasClickEvents;
|
||||
this.hasHoverEvents = hasHoverEvents;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.notifications;
|
||||
|
||||
import net.minecraft.util.IChatComponent;
|
||||
|
||||
/**
|
||||
* 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 ClickEventZone {
|
||||
|
||||
public final int posX;
|
||||
public final int posY;
|
||||
public final int width;
|
||||
public final int height;
|
||||
public final IChatComponent chatComponent;
|
||||
public final boolean hasHoverEvent;
|
||||
public final boolean hasClickEvent;
|
||||
|
||||
public ClickEventZone(int posX, int posY, int width, int height, IChatComponent chatComponent,
|
||||
boolean hasHoverEvent, boolean hasClickEvent) {
|
||||
this.posX = posX;
|
||||
this.posY = posY;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.chatComponent = chatComponent;
|
||||
this.hasHoverEvent = hasHoverEvent;
|
||||
this.hasClickEvent = hasClickEvent;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.notifications;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.Mouse;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.EnumCursorType;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
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 GuiButtonNotifBell extends GuiButton {
|
||||
|
||||
private static final ResourceLocation eaglerTextures = new ResourceLocation("eagler:gui/eagler_gui.png");
|
||||
|
||||
private int unread = 0;
|
||||
|
||||
public GuiButtonNotifBell(int buttonID, int xPos, int yPos) {
|
||||
super(buttonID, xPos, yPos, 20, 20, "");
|
||||
}
|
||||
|
||||
public void setUnread(int num) {
|
||||
unread = num;
|
||||
}
|
||||
|
||||
public void drawButton(Minecraft minecraft, int i, int j) {
|
||||
if (this.visible) {
|
||||
minecraft.getTextureManager().bindTexture(eaglerTextures);
|
||||
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
boolean flag = i >= this.xPosition && j >= this.yPosition && i < this.xPosition + this.width
|
||||
&& j < this.yPosition + this.height;
|
||||
int k = 0;
|
||||
int c = 14737632;
|
||||
if (flag) {
|
||||
k += this.height;
|
||||
c = 16777120;
|
||||
Mouse.showCursor(EnumCursorType.HAND);
|
||||
}
|
||||
|
||||
drawTexturedModalRect(xPosition, yPosition, unread > 0 ? 116 : 136, k, width, height);
|
||||
|
||||
if(unread > 0) {
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate(xPosition + 15.5f, yPosition + 11.0f, 0.0f);
|
||||
if(unread >= 10) {
|
||||
GlStateManager.translate(0.0f, 1.0f, 0.0f);
|
||||
GlStateManager.scale(0.5f, 0.5f, 0.5f);
|
||||
}else {
|
||||
GlStateManager.scale(0.75f, 0.75f, 0.75f);
|
||||
}
|
||||
drawCenteredString(minecraft.fontRendererObj, Integer.toString(unread), 0, 0, c);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,172 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.notifications;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Collections2;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeShowV4EAG.EnumBadgePriority;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* 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 GuiScreenNotifications extends GuiScreen {
|
||||
|
||||
private static final String[] priorityLangKeys = new String[] {
|
||||
"notifications.priority.low",
|
||||
"notifications.priority.normal",
|
||||
"notifications.priority.higher",
|
||||
"notifications.priority.highest"
|
||||
};
|
||||
|
||||
private static final int[] priorityOrder = new int[] {
|
||||
0, 3, 2, 1
|
||||
};
|
||||
|
||||
GuiScreen parent;
|
||||
int selected;
|
||||
GuiSlotNotifications slots;
|
||||
GuiButton clearAllButton;
|
||||
GuiButton priorityButton;
|
||||
int showPriority = 0;
|
||||
EnumBadgePriority selectedMaxPriority = EnumBadgePriority.LOW;
|
||||
int lastUpdate = -1;
|
||||
|
||||
public GuiScreenNotifications(GuiScreen parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
selected = -1;
|
||||
buttonList.clear();
|
||||
buttonList.add(new GuiButton(0, this.width / 2 + 54, this.height - 32, 100, 20, I18n.format("gui.done")));
|
||||
buttonList.add(clearAllButton = new GuiButton(1, this.width / 2 - 154, this.height - 32, 100, 20,
|
||||
I18n.format("notifications.clearAll")));
|
||||
int i = priorityOrder[showPriority];
|
||||
buttonList.add(priorityButton = new GuiButton(2, this.width / 2 - 50, this.height - 32, 100, 20,
|
||||
I18n.format("notifications.priority", I18n.format(priorityLangKeys[i]))));
|
||||
selectedMaxPriority = EnumBadgePriority.getByID(i);
|
||||
slots = new GuiSlotNotifications(this);
|
||||
lastUpdate = -69420;
|
||||
updateList();
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
void updateButtons() {
|
||||
clearAllButton.enabled = !slots.currentDisplayNotifs.isEmpty();
|
||||
}
|
||||
|
||||
void updateList() {
|
||||
if(mc.thePlayer == null) return;
|
||||
ServerNotificationManager mgr = mc.thePlayer.sendQueue.getNotifManager();
|
||||
int verHash = showPriority | (mgr.getNotifListUpdateCount() << 2);
|
||||
if(verHash != lastUpdate) {
|
||||
lastUpdate = verHash;
|
||||
EaglercraftUUID selectedUUID = null;
|
||||
List<GuiSlotNotifications.NotifBadgeSlot> lst = slots.currentDisplayNotifs;
|
||||
int oldSelectedId = selected;
|
||||
if(oldSelectedId >= 0 && oldSelectedId < lst.size()) {
|
||||
selectedUUID = lst.get(oldSelectedId).badge.badgeUUID;
|
||||
}
|
||||
lst.clear();
|
||||
lst.addAll(Collections2.transform(Collections2.filter(mgr.getNotifLongHistory(), new Predicate<NotificationBadge>() {
|
||||
@Override
|
||||
public boolean apply(NotificationBadge input) {
|
||||
return input.priority.priority >= priorityOrder[showPriority];
|
||||
}
|
||||
}), GuiSlotNotifications.NotifBadgeSlot::new));
|
||||
selected = -1;
|
||||
if(selectedUUID != null) {
|
||||
for(int i = 0, l = lst.size(); i < l; ++i) {
|
||||
if(selectedUUID.equals(lst.get(i).badge.badgeUUID)) {
|
||||
selected = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(selected != -1) {
|
||||
if(oldSelectedId != selected) {
|
||||
slots.scrollBy((selected - oldSelectedId) * slots.getSlotHeight());
|
||||
}
|
||||
}
|
||||
updateButtons();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateScreen() {
|
||||
if(mc.thePlayer == null) {
|
||||
mc.displayGuiScreen(parent);
|
||||
return;
|
||||
}
|
||||
updateList();
|
||||
}
|
||||
|
||||
static Minecraft getMinecraft(GuiScreenNotifications screen) {
|
||||
return screen.mc;
|
||||
}
|
||||
|
||||
public void actionPerformed(GuiButton btn) {
|
||||
switch(btn.id) {
|
||||
case 0:
|
||||
mc.displayGuiScreen(parent);
|
||||
break;
|
||||
case 1:
|
||||
if(mc.thePlayer != null) {
|
||||
ServerNotificationManager mgr = mc.thePlayer.sendQueue.getNotifManager();
|
||||
mgr.removeAllNotifFromActiveList(mgr.getNotifLongHistory());
|
||||
clearAllButton.enabled = false;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
showPriority = (showPriority + 1) & 3;
|
||||
int i = priorityOrder[showPriority];
|
||||
priorityButton.displayString = I18n.format("notifications.priority", I18n.format(priorityLangKeys[i]));
|
||||
selectedMaxPriority = EnumBadgePriority.getByID(i);
|
||||
updateList();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
if(mc.thePlayer == null) return;
|
||||
slots.drawScreen(par1, par2, par3);
|
||||
this.drawCenteredString(fontRendererObj, I18n.format("notifications.title"), this.width / 2, 16, 16777215);
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
public void handleMouseInput() throws IOException {
|
||||
super.handleMouseInput();
|
||||
slots.handleMouseInput();
|
||||
}
|
||||
|
||||
public void handleTouchInput() throws IOException {
|
||||
super.handleTouchInput();
|
||||
slots.handleTouchInput();
|
||||
}
|
||||
|
||||
public void onGuiClosed() {
|
||||
if(mc.thePlayer != null) {
|
||||
mc.thePlayer.sendQueue.getNotifManager().commitUnreadFlag();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,338 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.notifications;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeShowV4EAG.EnumBadgePriority;
|
||||
import net.minecraft.client.audio.PositionedSoundRecord;
|
||||
import net.minecraft.client.gui.GuiSlot;
|
||||
import net.minecraft.client.gui.GuiUtilRenderComponents;
|
||||
import net.minecraft.event.ClickEvent;
|
||||
import net.minecraft.event.HoverEvent;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
import net.minecraft.util.MathHelper;
|
||||
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 GuiSlotNotifications extends GuiSlot {
|
||||
|
||||
private static final ResourceLocation eaglerGui = new ResourceLocation("eagler:gui/eagler_gui.png");
|
||||
private static final ResourceLocation largeNotifBk = new ResourceLocation("eagler:gui/notif_bk_large.png");
|
||||
|
||||
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm a");
|
||||
|
||||
final GuiScreenNotifications parent;
|
||||
final List<NotifBadgeSlot> currentDisplayNotifs;
|
||||
|
||||
int mouseX;
|
||||
int mouseY;
|
||||
|
||||
protected static class NotifBadgeSlot {
|
||||
|
||||
protected final NotificationBadge badge;
|
||||
protected final List<ClickEventZone> cursorEvents = new ArrayList<>();
|
||||
protected int currentScreenX = -69420;
|
||||
protected int currentScreenY = -69420;
|
||||
|
||||
protected NotifBadgeSlot(NotificationBadge badge) {
|
||||
this.badge = badge;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public GuiSlotNotifications(GuiScreenNotifications parent) {
|
||||
super(GuiScreenNotifications.getMinecraft(parent), parent.width, parent.height, 32, parent.height - 44, 68);
|
||||
this.parent = parent;
|
||||
this.currentDisplayNotifs = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSize() {
|
||||
return currentDisplayNotifs.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void elementClicked(int id, boolean doubleClk, int xx, int yy) {
|
||||
if(selectedElement != id) return; //workaround for vanilla bs
|
||||
if(id < currentDisplayNotifs.size()) {
|
||||
NotifBadgeSlot slot = currentDisplayNotifs.get(id);
|
||||
if(slot.currentScreenY != -69420) {
|
||||
int w = getListWidth();
|
||||
int localX = xx - slot.currentScreenX;
|
||||
int localY = yy - slot.currentScreenY;
|
||||
if(localX >= w - 22 && localX < w - 5 && localY >= 5 && localY < 21) {
|
||||
slot.badge.removeNotif();
|
||||
mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
|
||||
return;
|
||||
}
|
||||
IChatComponent cmp = slot.badge.bodyComponent;
|
||||
if(cmp != null) {
|
||||
if(doubleClk) {
|
||||
if (cmp.getChatStyle().getChatClickEvent() != null
|
||||
&& cmp.getChatStyle().getChatClickEvent().getAction().shouldAllowInChat()) {
|
||||
if(parent.handleComponentClick(cmp)) {
|
||||
mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}else {
|
||||
if(parent.selected != id) {
|
||||
parent.selected = id;
|
||||
}else {
|
||||
List<ClickEventZone> cursorEvents = slot.cursorEvents;
|
||||
if(cursorEvents != null && !cursorEvents.isEmpty()) {
|
||||
for(int j = 0, m = cursorEvents.size(); j < m; ++j) {
|
||||
ClickEventZone evt = cursorEvents.get(j);
|
||||
if(evt.hasClickEvent) {
|
||||
int offsetPosX = slot.currentScreenX + evt.posX;
|
||||
int offsetPosY = slot.currentScreenY + evt.posY;
|
||||
if(xx >= offsetPosX && yy >= offsetPosY && xx < offsetPosX + evt.width && yy < offsetPosY + evt.height) {
|
||||
if(parent.handleComponentClick(evt.chatComponent)) {
|
||||
mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSelected(int var1) {
|
||||
return var1 == parent.selected;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawBackground() {
|
||||
parent.drawBackground(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawSlot(int id, int xx, int yy, int width, int height, int ii) {
|
||||
if(id < currentDisplayNotifs.size()) {
|
||||
NotifBadgeSlot slot = currentDisplayNotifs.get(id);
|
||||
slot.currentScreenX = xx;
|
||||
slot.currentScreenY = yy;
|
||||
NotificationBadge bd = slot.badge;
|
||||
if(yy + 32 > this.top && yy + 32 < this.bottom) {
|
||||
bd.markRead();
|
||||
}
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate(xx, yy, 0.0f);
|
||||
mc.getTextureManager().bindTexture(largeNotifBk);
|
||||
int badgeWidth = getListWidth() - 4;
|
||||
int badgeHeight = getSlotHeight() - 4;
|
||||
float r = ((bd.backgroundColor >> 16) & 0xFF) * 0.00392156f;
|
||||
float g = ((bd.backgroundColor >> 8) & 0xFF) * 0.00392156f;
|
||||
float b = (bd.backgroundColor & 0xFF) * 0.00392156f;
|
||||
if(parent.selected != id) {
|
||||
r *= 0.85f;
|
||||
g *= 0.85f;
|
||||
b *= 0.85f;
|
||||
}
|
||||
GlStateManager.color(r, g, b, 1.0f);
|
||||
parent.drawTexturedModalRect(0, 0, 0, bd.unreadFlagRender ? 64 : 0, badgeWidth - 32, 64);
|
||||
parent.drawTexturedModalRect(badgeWidth - 32, 0, 224, bd.unreadFlagRender ? 64 : 0, 32, 64);
|
||||
mc.getTextureManager().bindTexture(eaglerGui);
|
||||
if(bd.priority == EnumBadgePriority.LOW) {
|
||||
parent.drawTexturedModalRect(badgeWidth - 21, badgeHeight - 21, 192, 176, 16, 16);
|
||||
}
|
||||
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
switch(bd.priority) {
|
||||
default:
|
||||
break;
|
||||
case NORMAL:
|
||||
parent.drawTexturedModalRect(badgeWidth - 21, badgeHeight - 21, 208, 176, 16, 16);
|
||||
break;
|
||||
case HIGHER:
|
||||
parent.drawTexturedModalRect(badgeWidth - 21, badgeHeight - 21, 224, 176, 16, 16);
|
||||
break;
|
||||
case HIGHEST:
|
||||
parent.drawTexturedModalRect(badgeWidth - 21, badgeHeight - 21, 240, 176, 16, 16);
|
||||
break;
|
||||
}
|
||||
|
||||
int bodyYOffset = 16;
|
||||
|
||||
int leftPadding = 6;
|
||||
int rightPadding = 26;
|
||||
|
||||
int mainIconSW = 32;
|
||||
boolean mainIconEn = bd.mainIcon != null && bd.mainIcon.isValid();
|
||||
if(mainIconEn) {
|
||||
int iw = bd.mainIcon.texture.getWidth();
|
||||
int ih = bd.mainIcon.texture.getHeight();
|
||||
float iaspect = (float)iw / (float)ih;
|
||||
mainIconSW = (int)(32 * iaspect);
|
||||
leftPadding += Math.min(mainIconSW, 64) + 3;
|
||||
}
|
||||
|
||||
int textZoneWidth = badgeWidth - leftPadding - rightPadding;
|
||||
|
||||
if(mainIconEn) {
|
||||
mc.getTextureManager().bindTexture(bd.mainIcon.resource);
|
||||
ServerNotificationRenderer.drawTexturedRect(6, bodyYOffset, mainIconSW, 32);
|
||||
}
|
||||
|
||||
boolean titleIconEn = bd.titleIcon != null && bd.titleIcon.isValid();
|
||||
if(titleIconEn) {
|
||||
mc.getTextureManager().bindTexture(bd.titleIcon.resource);
|
||||
ServerNotificationRenderer.drawTexturedRect(6, 5, 8, 8);
|
||||
}
|
||||
|
||||
String titleText = "";
|
||||
IChatComponent titleComponent = bd.getTitleProfanityFilter();
|
||||
if(titleComponent != null) {
|
||||
titleText = titleComponent.getFormattedText();
|
||||
}
|
||||
|
||||
titleText += EnumChatFormatting.GRAY + (titleText.length() > 0 ? " @ " : "@ ")
|
||||
+ (bd.unreadFlagRender ? EnumChatFormatting.YELLOW : EnumChatFormatting.GRAY)
|
||||
+ formatAge(bd.serverTimestamp);
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate(6 + (titleIconEn ? 10 : 0), 6, 0.0f);
|
||||
GlStateManager.scale(0.75f, 0.75f, 0.75f);
|
||||
mc.fontRendererObj.drawStringWithShadow(titleText, 0, 0, bd.titleTxtColor);
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
String sourceText = null;
|
||||
IChatComponent sourceComponent = bd.getSourceProfanityFilter();
|
||||
if(sourceComponent != null) {
|
||||
sourceText = sourceComponent.getFormattedText();
|
||||
if(sourceText.length() == 0) {
|
||||
sourceText = null;
|
||||
}
|
||||
}
|
||||
|
||||
List<IChatComponent> bodyLines = null;
|
||||
float bodyFontSize = (sourceText != null || titleIconEn) ? 0.75f : 1.0f;
|
||||
IChatComponent bodyComponent = bd.getBodyProfanityFilter();
|
||||
if(bodyComponent != null) {
|
||||
bodyLines = GuiUtilRenderComponents.func_178908_a(bodyComponent, (int) (textZoneWidth / bodyFontSize),
|
||||
mc.fontRendererObj, true, true);
|
||||
|
||||
int maxHeight = badgeHeight - (sourceText != null ? 32 : 22);
|
||||
int maxLines = MathHelper.floor_float(maxHeight / (9 * bodyFontSize));
|
||||
if(bodyLines.size() > maxLines) {
|
||||
bodyLines = bodyLines.subList(0, maxLines);
|
||||
IChatComponent cmp = bodyLines.get(maxLines - 1);
|
||||
List<IChatComponent> siblings = cmp.getSiblings();
|
||||
IChatComponent dots = new ChatComponentText("...");
|
||||
if(siblings != null && siblings.size() > 0) {
|
||||
dots.setChatStyle(siblings.get(siblings.size() - 1).getChatStyle());
|
||||
}
|
||||
cmp.appendSibling(dots);
|
||||
}
|
||||
}
|
||||
|
||||
slot.cursorEvents.clear();
|
||||
if(bodyLines != null && !bodyLines.isEmpty()) {
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate(leftPadding, bodyYOffset, 0.0f);
|
||||
int l = bodyLines.size();
|
||||
GlStateManager.scale(bodyFontSize, bodyFontSize, bodyFontSize);
|
||||
IChatComponent toolTip = null;
|
||||
for(int i = 0; i < l; ++i) {
|
||||
int startXLocal = 0;
|
||||
int startXReal = leftPadding;
|
||||
for(IChatComponent comp : bodyLines.get(i)) {
|
||||
int w = mc.fontRendererObj.drawStringWithShadow(
|
||||
comp.getChatStyle().getFormattingCode() + comp.getUnformattedTextForChat(), startXLocal,
|
||||
i * 9, bd.bodyTxtColor) - startXLocal;
|
||||
ClickEvent clickEvent = comp.getChatStyle().getChatClickEvent();
|
||||
HoverEvent hoverEvent = toolTip == null ? comp.getChatStyle().getChatHoverEvent() : null;
|
||||
if(clickEvent != null && !clickEvent.getAction().shouldAllowInChat()) {
|
||||
clickEvent = null;
|
||||
}
|
||||
if(hoverEvent != null && !hoverEvent.getAction().shouldAllowInChat()) {
|
||||
hoverEvent = null;
|
||||
}
|
||||
if(clickEvent != null) {
|
||||
slot.cursorEvents.add(new ClickEventZone(startXReal + (int) (startXLocal * bodyFontSize),
|
||||
bodyYOffset + (int) (i * 9 * bodyFontSize), (int) (w * bodyFontSize),
|
||||
(int) (9 * bodyFontSize), comp, clickEvent != null, hoverEvent != null));
|
||||
}
|
||||
if(hoverEvent != null) {
|
||||
int px = xx + startXReal + (int) (startXLocal * bodyFontSize);
|
||||
int py = yy + bodyYOffset + (int) (i * 9 * bodyFontSize);
|
||||
if (mouseX >= px && mouseX < px + (int) (w * bodyFontSize) && mouseY >= py
|
||||
&& mouseY < py + (int) (9 * bodyFontSize)) {
|
||||
toolTip = comp;
|
||||
}
|
||||
}
|
||||
startXLocal += w;
|
||||
}
|
||||
}
|
||||
GlStateManager.popMatrix();
|
||||
if(toolTip != null) {
|
||||
parent.handleComponentHover(toolTip, mouseX - xx, mouseY - yy);
|
||||
}
|
||||
}
|
||||
|
||||
if(sourceText != null) {
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate(badgeWidth - 21, badgeHeight - 5, 0.0f);
|
||||
GlStateManager.scale(0.75f, 0.75f, 0.75f);
|
||||
mc.fontRendererObj.drawStringWithShadow(sourceText, -mc.fontRendererObj.getStringWidth(sourceText) - 4, -10, bd.sourceTxtColor);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
private String formatAge(long serverTimestamp) {
|
||||
long cur = System.currentTimeMillis();
|
||||
long daysAgo = Math.round((cur - serverTimestamp) / 86400000.0);
|
||||
String ret = dateFormat.format(new Date(serverTimestamp));
|
||||
if(daysAgo > 0l) {
|
||||
ret += " (" + daysAgo + (daysAgo == 1l ? " day" : " days") + " ago)";
|
||||
}else if(daysAgo < 0l) {
|
||||
ret += " (in " + -daysAgo + (daysAgo == -1l ? " day" : " days") + ")";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getListWidth() {
|
||||
return 224;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(int mouseXIn, int mouseYIn, float parFloat1) {
|
||||
mouseX = mouseXIn;
|
||||
mouseY = mouseYIn;
|
||||
for(int i = 0, l = currentDisplayNotifs.size(); i < l; ++i) {
|
||||
NotifBadgeSlot slot = currentDisplayNotifs.get(i);
|
||||
slot.currentScreenX = -69420;
|
||||
slot.currentScreenY = -69420;
|
||||
}
|
||||
super.drawScreen(mouseXIn, mouseYIn, parFloat1);
|
||||
}
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.notifications;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.profanity_filter.ProfanityFilter;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeShowV4EAG.EnumBadgePriority;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
|
||||
/**
|
||||
* 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 NotificationBadge {
|
||||
|
||||
public final ServerNotificationManager mgr;
|
||||
public final EaglercraftUUID badgeUUID;
|
||||
public final IChatComponent bodyComponent;
|
||||
protected IChatComponent bodyComponentProfanityFilter;
|
||||
public final IChatComponent titleComponent;
|
||||
protected IChatComponent titleComponentProfanityFilter;
|
||||
public final IChatComponent sourceComponent;
|
||||
protected IChatComponent sourceComponentProfanityFilter;
|
||||
public final long clientTimestamp;
|
||||
public final long serverTimestamp;
|
||||
public final boolean silent;
|
||||
public final EnumBadgePriority priority;
|
||||
public final NotificationIcon mainIcon;
|
||||
public final NotificationIcon titleIcon;
|
||||
public final int hideAfterSec;
|
||||
public final int expireAfterSec;
|
||||
public final int backgroundColor;
|
||||
public final int bodyTxtColor;
|
||||
public final int titleTxtColor;
|
||||
public final int sourceTxtColor;
|
||||
|
||||
protected CachedNotifBadgeTexture currentCacheGLTexture = null;
|
||||
protected int currentCacheScaleFac = -1;
|
||||
protected boolean currentCacheXButton = false;
|
||||
protected boolean currentCacheProfanityFilter = false;
|
||||
protected long hideAtMillis = -1l;
|
||||
protected boolean unreadFlag = true;
|
||||
protected boolean unreadFlagRender = true;
|
||||
|
||||
protected NotificationBadge(ServerNotificationManager mgr, EaglercraftUUID badgeUUID, IChatComponent bodyComponent,
|
||||
IChatComponent titleComponent, IChatComponent sourceComponent, long clientTimestamp, long serverTimestamp,
|
||||
boolean silent, EnumBadgePriority priority, NotificationIcon mainIcon, NotificationIcon titleIcon,
|
||||
int hideAfterSec, int expireAfterSec, int backgroundColor, int bodyTxtColor, int titleTxtColor,
|
||||
int sourceTxtColor) {
|
||||
this.mgr = mgr;
|
||||
this.badgeUUID = badgeUUID;
|
||||
this.bodyComponent = bodyComponent;
|
||||
this.titleComponent = titleComponent;
|
||||
this.sourceComponent = sourceComponent;
|
||||
this.clientTimestamp = clientTimestamp;
|
||||
this.serverTimestamp = serverTimestamp;
|
||||
this.silent = silent;
|
||||
this.priority = priority;
|
||||
this.mainIcon = mainIcon;
|
||||
this.titleIcon = titleIcon;
|
||||
this.hideAfterSec = hideAfterSec;
|
||||
this.expireAfterSec = expireAfterSec;
|
||||
this.backgroundColor = backgroundColor;
|
||||
this.bodyTxtColor = bodyTxtColor;
|
||||
this.titleTxtColor = titleTxtColor;
|
||||
this.sourceTxtColor = sourceTxtColor;
|
||||
}
|
||||
|
||||
protected void incrIconRefcounts() {
|
||||
if(mainIcon != null) {
|
||||
mainIcon.retain();
|
||||
}
|
||||
if(titleIcon != null) {
|
||||
titleIcon.retain();
|
||||
}
|
||||
}
|
||||
|
||||
protected void decrIconRefcounts() {
|
||||
deleteGLTexture();
|
||||
if(mainIcon != null) {
|
||||
mainIcon.release();
|
||||
}
|
||||
if(titleIcon != null) {
|
||||
titleIcon.release();
|
||||
}
|
||||
}
|
||||
|
||||
protected CachedNotifBadgeTexture getGLTexture(ServerNotificationRenderer renderer, int scaleFactor, boolean showXButton) {
|
||||
boolean profanityFilter = Minecraft.getMinecraft().isEnableProfanityFilter();
|
||||
if(currentCacheGLTexture == null || currentCacheScaleFac != scaleFactor || currentCacheXButton != showXButton || currentCacheProfanityFilter != profanityFilter) {
|
||||
deleteGLTexture();
|
||||
currentCacheGLTexture = renderer.renderBadge(this, scaleFactor, showXButton);
|
||||
currentCacheScaleFac = scaleFactor;
|
||||
currentCacheXButton = showXButton;
|
||||
currentCacheProfanityFilter = profanityFilter;
|
||||
}
|
||||
return currentCacheGLTexture;
|
||||
}
|
||||
|
||||
protected void deleteGLTexture() {
|
||||
if(currentCacheGLTexture != null) {
|
||||
GlStateManager.deleteTexture(currentCacheGLTexture.glTexture);
|
||||
currentCacheGLTexture = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void hideNotif() {
|
||||
if(hideAtMillis == -1l) {
|
||||
markRead();
|
||||
unreadFlagRender = false;
|
||||
hideAtMillis = EagRuntime.steadyTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeNotif() {
|
||||
mgr.removeNotifFromActiveList(badgeUUID);
|
||||
}
|
||||
|
||||
public void markRead() {
|
||||
if(unreadFlag) {
|
||||
unreadFlag = false;
|
||||
--mgr.unreadCounter;
|
||||
}
|
||||
}
|
||||
|
||||
public IChatComponent getBodyProfanityFilter() {
|
||||
if(Minecraft.getMinecraft().isEnableProfanityFilter()) {
|
||||
if(bodyComponentProfanityFilter == null && bodyComponent != null) {
|
||||
bodyComponentProfanityFilter = ProfanityFilter.getInstance().profanityFilterChatComponent(bodyComponent);
|
||||
}
|
||||
return bodyComponentProfanityFilter;
|
||||
}else {
|
||||
return bodyComponent;
|
||||
}
|
||||
}
|
||||
|
||||
public IChatComponent getTitleProfanityFilter() {
|
||||
if(Minecraft.getMinecraft().isEnableProfanityFilter()) {
|
||||
if(titleComponentProfanityFilter == null && titleComponent != null) {
|
||||
titleComponentProfanityFilter = ProfanityFilter.getInstance().profanityFilterChatComponent(titleComponent);
|
||||
}
|
||||
return titleComponentProfanityFilter;
|
||||
}else {
|
||||
return titleComponent;
|
||||
}
|
||||
}
|
||||
|
||||
public IChatComponent getSourceProfanityFilter() {
|
||||
if(Minecraft.getMinecraft().isEnableProfanityFilter()) {
|
||||
if(sourceComponentProfanityFilter == null && sourceComponent != null) {
|
||||
sourceComponentProfanityFilter = ProfanityFilter.getInstance().profanityFilterChatComponent(sourceComponent);
|
||||
}
|
||||
return sourceComponentProfanityFilter;
|
||||
}else {
|
||||
return sourceComponent;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.notifications;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
|
||||
import net.lax1dude.eaglercraft.v1_8.profile.EaglerSkinTexture;
|
||||
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 NotificationIcon {
|
||||
|
||||
private static int notifIconTmpId = 0;
|
||||
|
||||
protected int refCount = 0;
|
||||
protected boolean serverRegistered = true;
|
||||
|
||||
public final EaglercraftUUID iconUUID;
|
||||
public final EaglerSkinTexture texture;
|
||||
public final ResourceLocation resource;
|
||||
|
||||
protected NotificationIcon(EaglercraftUUID iconUUID, EaglerSkinTexture texture) {
|
||||
this.iconUUID = iconUUID;
|
||||
this.texture = texture;
|
||||
this.resource = new ResourceLocation("eagler:gui/server/notifs/tex_" + notifIconTmpId++);
|
||||
}
|
||||
|
||||
public void retain() {
|
||||
++refCount;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
--refCount;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return serverRegistered || refCount > 0;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,277 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.notifications;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
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.opengl.ImageData;
|
||||
import net.lax1dude.eaglercraft.v1_8.profile.EaglerSkinTexture;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeHideV4EAG;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeShowV4EAG;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifIconsRegisterV4EAG;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifIconsReleaseV4EAG;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.PacketImageData;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
|
||||
/**
|
||||
* 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 ServerNotificationManager {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger("ServerNotificationManager");
|
||||
|
||||
private final Map<EaglercraftUUID,NotificationIcon> activeIcons = new HashMap<>();
|
||||
private final Map<EaglercraftUUID,NotificationBadge> activeNotifications = new HashMap<>();
|
||||
private List<NotificationBadge> sortedNotifList = new ArrayList<>(0);
|
||||
private List<NotificationBadge> sortedDisplayNotifList = new ArrayList<>(0);
|
||||
private int updateCounter = 0;
|
||||
private long lastCleanup = EagRuntime.steadyTimeMillis();
|
||||
private final TextureManager textureMgr;
|
||||
protected int unreadCounter = 0;
|
||||
|
||||
public ServerNotificationManager() {
|
||||
this.textureMgr = Minecraft.getMinecraft().getTextureManager();
|
||||
}
|
||||
|
||||
public void processPacketAddIcons(SPacketNotifIconsRegisterV4EAG packet) {
|
||||
for(SPacketNotifIconsRegisterV4EAG.CreateIcon icn : packet.iconsToCreate) {
|
||||
if(icn.uuidMost == 0 && icn.uuidLeast == 0) {
|
||||
logger.error("Skipping notification icon with UUID 0!");
|
||||
continue;
|
||||
}
|
||||
EaglercraftUUID uuid = new EaglercraftUUID(icn.uuidMost, icn.uuidLeast);
|
||||
PacketImageData imageData = icn.imageData;
|
||||
NotificationIcon existing = activeIcons.get(uuid);
|
||||
if(existing != null) {
|
||||
if (existing.texture.getWidth() != imageData.width
|
||||
|| existing.texture.getHeight() != imageData.height) {
|
||||
logger.error("Error: server tried to change the dimensions of icon {}!", uuid);
|
||||
}else if(!Arrays.equals(existing.texture.getData(), imageData.rgba)) {
|
||||
existing.texture.copyPixelsIn(ImageData.swapRB(imageData.rgba));
|
||||
}
|
||||
existing.serverRegistered = true;
|
||||
continue;
|
||||
}
|
||||
NotificationIcon newIcon = new NotificationIcon(uuid,
|
||||
new EaglerSkinTexture(ImageData.swapRB(imageData.rgba), imageData.width, imageData.height));
|
||||
textureMgr.loadTexture(newIcon.resource, newIcon.texture);
|
||||
activeIcons.put(uuid, newIcon);
|
||||
}
|
||||
}
|
||||
|
||||
public void processPacketRemIcons(SPacketNotifIconsReleaseV4EAG packet) {
|
||||
for(SPacketNotifIconsReleaseV4EAG.DestroyIcon icn : packet.iconsToDestroy) {
|
||||
NotificationIcon existing = activeIcons.get(new EaglercraftUUID(icn.uuidMost, icn.uuidLeast));
|
||||
if(existing != null) {
|
||||
existing.serverRegistered = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void processPacketShowBadge(SPacketNotifBadgeShowV4EAG packet) {
|
||||
EaglercraftUUID newUuid = new EaglercraftUUID(packet.badgeUUIDMost, packet.badgeUUIDLeast);
|
||||
NotificationBadge existing = activeNotifications.get(newUuid);
|
||||
if(existing != null) {
|
||||
logger.error("Duplicate notification UUID {}, all notifications should have unique UUIDs!", newUuid);
|
||||
return;
|
||||
}
|
||||
NotificationBadge newBadge = new NotificationBadge(this, newUuid,
|
||||
!StringUtils.isAllBlank(packet.bodyComponent) ? IChatComponent.Serializer.jsonToComponent(packet.bodyComponent) : null,
|
||||
!StringUtils.isAllBlank(packet.titleComponent) ? IChatComponent.Serializer.jsonToComponent(packet.titleComponent) : null,
|
||||
!StringUtils.isAllBlank(packet.sourceComponent) ? IChatComponent.Serializer.jsonToComponent(packet.sourceComponent) : null,
|
||||
EagRuntime.steadyTimeMillis(), packet.originalTimestampSec * 1000l, packet.silent, packet.priority,
|
||||
getIcon(packet.mainIconUUIDMost, packet.mainIconUUIDLeast),
|
||||
getIcon(packet.titleIconUUIDMost, packet.titleIconUUIDLeast), packet.hideAfterSec, packet.expireAfterSec,
|
||||
packet.backgroundColor, packet.bodyTxtColor, packet.titleTxtColor, packet.sourceTxtColor);
|
||||
++unreadCounter;
|
||||
addNotifToActiveList(newBadge);
|
||||
}
|
||||
|
||||
private NotificationIcon getIcon(long uuidMost, long uuidLeast) {
|
||||
if(uuidMost == 0l && uuidLeast == 0l) {
|
||||
return null;
|
||||
}
|
||||
return activeIcons.get(new EaglercraftUUID(uuidMost, uuidLeast));
|
||||
}
|
||||
|
||||
public void processPacketHideBadge(SPacketNotifBadgeHideV4EAG packet) {
|
||||
removeNotifFromActiveList(new EaglercraftUUID(packet.badgeUUIDLeast, packet.badgeUUIDMost));
|
||||
}
|
||||
|
||||
public int getNotifListUpdateCount() {
|
||||
return updateCounter;
|
||||
}
|
||||
|
||||
public List<NotificationBadge> getNotifBadgesToDisplay() {
|
||||
return sortedDisplayNotifList;
|
||||
}
|
||||
|
||||
public List<NotificationBadge> getNotifLongHistory() {
|
||||
return sortedNotifList;
|
||||
}
|
||||
|
||||
protected void addNotifToActiveList(NotificationBadge badge) {
|
||||
NotificationBadge exists = activeNotifications.put(badge.badgeUUID, badge);
|
||||
if(exists != null) {
|
||||
exists.decrIconRefcounts();
|
||||
}
|
||||
badge.incrIconRefcounts();
|
||||
resortLists();
|
||||
}
|
||||
|
||||
protected void removeNotifFromActiveList(EaglercraftUUID badge) {
|
||||
NotificationBadge exists = activeNotifications.remove(badge);
|
||||
if(exists != null) {
|
||||
exists.decrIconRefcounts();
|
||||
resortLists();
|
||||
}
|
||||
}
|
||||
|
||||
protected void removeAllNotifFromActiveList(Collection<NotificationBadge> badges) {
|
||||
boolean resort = false;
|
||||
for(NotificationBadge badge : badges) {
|
||||
NotificationBadge exists = activeNotifications.remove(badge.badgeUUID);
|
||||
if(exists != null) {
|
||||
exists.decrIconRefcounts();
|
||||
resort = true;
|
||||
}
|
||||
}
|
||||
if(resort) {
|
||||
resortLists();
|
||||
}
|
||||
}
|
||||
|
||||
protected static final Comparator<NotificationBadge> clientAgeComparator = (a, b) -> {
|
||||
return (int)(b.clientTimestamp - a.clientTimestamp);
|
||||
};
|
||||
|
||||
private void resortLists() {
|
||||
updateCounter++;
|
||||
int ll = activeNotifications.size();
|
||||
if(!sortedNotifList.isEmpty()) sortedNotifList = new ArrayList<>(ll);
|
||||
if(!sortedDisplayNotifList.isEmpty()) sortedDisplayNotifList = new ArrayList<>(Math.min(ll, 4));
|
||||
if(ll > 0) {
|
||||
sortedNotifList.addAll(activeNotifications.values());
|
||||
Collections.sort(sortedNotifList, clientAgeComparator);
|
||||
long millis = EagRuntime.steadyTimeMillis();
|
||||
for(int i = 0, l = sortedNotifList.size(); i < l; ++i) {
|
||||
NotificationBadge bd = sortedNotifList.get(i);
|
||||
if(millis - bd.clientTimestamp < (long)(bd.hideAfterSec * 1000)) {
|
||||
sortedDisplayNotifList.add(bd);
|
||||
}else {
|
||||
bd.deleteGLTexture();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void runTick() {
|
||||
long millis = EagRuntime.steadyTimeMillis();
|
||||
if(millis - lastCleanup > 2500l) {
|
||||
lastCleanup = millis;
|
||||
int len = sortedNotifList.size();
|
||||
if(len > 128) {
|
||||
removeAllNotifFromActiveList(new ArrayList<NotificationBadge>(sortedNotifList.subList(128, len)));
|
||||
}
|
||||
Iterator<NotificationIcon> itr = activeIcons.values().iterator();
|
||||
while(itr.hasNext()) {
|
||||
NotificationIcon icn = itr.next();
|
||||
if(!icn.isValid()) {
|
||||
itr.remove();
|
||||
textureMgr.deleteTexture(icn.resource);
|
||||
}
|
||||
}
|
||||
if(!sortedDisplayNotifList.isEmpty()) {
|
||||
Iterator<NotificationBadge> itr2 = sortedDisplayNotifList.iterator();
|
||||
while(itr2.hasNext()) {
|
||||
NotificationBadge bd = itr2.next();
|
||||
if(bd.hideAtMillis != -1l) {
|
||||
if(millis - bd.hideAtMillis > 500l) {
|
||||
bd.deleteGLTexture();
|
||||
itr2.remove();
|
||||
}
|
||||
}else {
|
||||
long age = millis - bd.clientTimestamp;
|
||||
if(age > (long)(bd.hideAfterSec * 1000) || age > (long)(bd.expireAfterSec * 1000)) {
|
||||
bd.deleteGLTexture();
|
||||
itr2.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!activeNotifications.isEmpty()) {
|
||||
Iterator<NotificationBadge> itr3 = activeNotifications.values().iterator();
|
||||
List<NotificationBadge> toDelete = null;
|
||||
while(itr3.hasNext()) {
|
||||
NotificationBadge bd = itr3.next();
|
||||
long age = millis - bd.clientTimestamp;
|
||||
if(age > (long)(bd.expireAfterSec * 1000)) {
|
||||
if(toDelete == null) {
|
||||
toDelete = new ArrayList<>();
|
||||
}
|
||||
toDelete.add(bd);
|
||||
}
|
||||
}
|
||||
if(toDelete != null) {
|
||||
removeAllNotifFromActiveList(toDelete);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getUnread() {
|
||||
if(unreadCounter < 0) unreadCounter = 0;
|
||||
return unreadCounter;
|
||||
}
|
||||
|
||||
public void commitUnreadFlag() {
|
||||
for(NotificationBadge badge : activeNotifications.values()) {
|
||||
badge.unreadFlagRender = badge.unreadFlag;
|
||||
}
|
||||
}
|
||||
|
||||
public void markRead() {
|
||||
for(NotificationBadge badge : activeNotifications.values()) {
|
||||
badge.unreadFlag = false;
|
||||
badge.unreadFlagRender = false;
|
||||
}
|
||||
unreadCounter = 0;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
for(NotificationIcon icn : activeIcons.values()) {
|
||||
textureMgr.deleteTexture(icn.resource);
|
||||
}
|
||||
activeIcons.clear();
|
||||
activeNotifications.clear();
|
||||
sortedNotifList = null;
|
||||
sortedDisplayNotifList = null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,539 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.notifications;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IFramebufferGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.VertexFormat;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.audio.PositionedSoundRecord;
|
||||
import net.minecraft.client.gui.GuiChat;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiUtilRenderComponents;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.event.ClickEvent;
|
||||
import net.minecraft.event.HoverEvent;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
|
||||
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
|
||||
import static net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ExtGLEnums.*;
|
||||
|
||||
/**
|
||||
* 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 ServerNotificationRenderer {
|
||||
|
||||
protected static final Logger logger = LogManager.getLogger("ServerNotificationRenderer");
|
||||
|
||||
protected Minecraft mc;
|
||||
protected int width;
|
||||
protected int height;
|
||||
protected int scaleFactor;
|
||||
|
||||
protected IFramebufferGL rendererFramebuffer;
|
||||
|
||||
protected static final int BADGE_WIDTH = 160;
|
||||
protected static final int BADGE_HEIGHT = 64;
|
||||
|
||||
private static final ResourceLocation eaglerGui = new ResourceLocation("eagler:gui/eagler_gui.png");
|
||||
|
||||
public ServerNotificationRenderer() {
|
||||
|
||||
}
|
||||
|
||||
public void init() {
|
||||
destroy();
|
||||
rendererFramebuffer = _wglCreateFramebuffer();
|
||||
}
|
||||
|
||||
public void setResolution(Minecraft mc, int w, int h, int scaleFactor) {
|
||||
this.mc = mc;
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
this.scaleFactor = scaleFactor;
|
||||
}
|
||||
|
||||
public boolean handleClicked(GuiScreen currentScreen, int posX, int posY) {
|
||||
if(mc.thePlayer == null) return false;
|
||||
ServerNotificationManager mgr = mc.thePlayer.sendQueue.getNotifManager();
|
||||
List<NotificationBadge> lst = mgr.getNotifBadgesToDisplay();
|
||||
if(!lst.isEmpty()) {
|
||||
int baseOffset = mc.guiAchievement.getHeight();
|
||||
boolean showX = (currentScreen instanceof GuiChat);
|
||||
if(showX) {
|
||||
baseOffset += 25; // exit button in chat screen;
|
||||
}
|
||||
long millis = EagRuntime.steadyTimeMillis();
|
||||
for(int i = 0, l = lst.size(); i < l; ++i) {
|
||||
NotificationBadge badge = lst.get(i);
|
||||
CachedNotifBadgeTexture tex = badge.currentCacheGLTexture;
|
||||
if(tex != null) {
|
||||
int baseX = width - tex.width;
|
||||
float texHeight = tex.height;
|
||||
float timeRemainingSec;
|
||||
long age = millis - badge.clientTimestamp;
|
||||
if(badge.hideAtMillis != -1l) {
|
||||
timeRemainingSec = (float)((double)(500l - (millis - badge.hideAtMillis)) * 0.001);
|
||||
}else {
|
||||
timeRemainingSec = (float)((double)((long)badge.hideAfterSec * 1000l - age) * 0.001);
|
||||
}
|
||||
timeRemainingSec = Math.min((float)(age * 0.001) + 0.001f, timeRemainingSec);
|
||||
float f = MathHelper.clamp_float(timeRemainingSec * 3.0F, 0.0F, 1.0F);
|
||||
f *= f;
|
||||
texHeight *= f;
|
||||
if(badge.hideAtMillis == -1l) {
|
||||
if(posX >= baseX && posX < width && posY >= baseOffset && posY < baseOffset + texHeight) {
|
||||
if(showX) {
|
||||
int xposX = baseX + tex.width - 21;
|
||||
int xposY = baseOffset + 5;
|
||||
if(posX >= xposX && posY >= xposY && posX < xposX + 16 && posY < xposY + 16) {
|
||||
badge.hideNotif();
|
||||
mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(tex.rootClickEvent != null) {
|
||||
if(currentScreen.handleComponentClick(tex.rootClickEvent)) {
|
||||
mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
List<ClickEventZone> cursorEvents = tex.cursorEvents;
|
||||
if(tex.hasClickEvents && cursorEvents != null) {
|
||||
for(int j = 0, m = cursorEvents.size(); j < m; ++j) {
|
||||
ClickEventZone evt = cursorEvents.get(j);
|
||||
if(evt.hasClickEvent) {
|
||||
int offsetPosX = baseX + evt.posX;
|
||||
int offsetPosY = baseOffset + evt.posY;
|
||||
if(posX >= offsetPosX && posY >= offsetPosY && posX < offsetPosX + evt.width && posY < offsetPosY + evt.height) {
|
||||
if(currentScreen.handleComponentClick(evt.chatComponent)) {
|
||||
mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
baseOffset += texHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void renderOverlay(int mouseX, int mouseY) {
|
||||
if(mc.thePlayer == null) return;
|
||||
ServerNotificationManager mgr = mc.thePlayer.sendQueue.getNotifManager();
|
||||
List<NotificationBadge> lst = mgr.getNotifBadgesToDisplay();
|
||||
if(!lst.isEmpty()) {
|
||||
GlStateManager.clear(GL_DEPTH_BUFFER_BIT);
|
||||
boolean showXButtons = false;
|
||||
int baseOffset = mc.guiAchievement.getHeight();
|
||||
if(mc.currentScreen != null) {
|
||||
if(mc.currentScreen instanceof GuiChat) {
|
||||
baseOffset += 25; // exit button in chat screen;
|
||||
showXButtons = true;
|
||||
}else if(mc.currentScreen instanceof GuiScreenNotifications) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
long millis = EagRuntime.steadyTimeMillis();
|
||||
boolean isBlend = false;
|
||||
for(int i = 0, l = lst.size(); i < l; ++i) {
|
||||
NotificationBadge badge = lst.get(i);
|
||||
boolean isHiding = false;
|
||||
if(badge.hideAtMillis != -1l) {
|
||||
isHiding = true;
|
||||
if(millis - badge.hideAtMillis > 500l) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
CachedNotifBadgeTexture tex = badge.getGLTexture(this, scaleFactor, showXButtons);
|
||||
if(tex != null) {
|
||||
GlStateManager.bindTexture(tex.glTexture);
|
||||
float alphaTop = 1.0f;
|
||||
float alphaBottom = 1.0f;
|
||||
float timeRemainingSec;
|
||||
long age = millis - badge.clientTimestamp;
|
||||
if(isHiding) {
|
||||
timeRemainingSec = (float)((double)(500l - (millis - badge.hideAtMillis)) * 0.001);
|
||||
}else {
|
||||
timeRemainingSec = (float)((double)((long)badge.hideAfterSec * 1000l - age) * 0.001);
|
||||
}
|
||||
timeRemainingSec = Math.min((float)(age * 0.001) + 0.001f, timeRemainingSec);
|
||||
alphaTop *= MathHelper.clamp_float(timeRemainingSec * 3.0F, 0.0F, 1.0F);
|
||||
alphaTop *= alphaTop;
|
||||
alphaBottom *= MathHelper.clamp_float(timeRemainingSec * 2.0F, 0.0F, 1.0F);
|
||||
alphaBottom *= alphaBottom;
|
||||
if(alphaTop == 0.0F && alphaBottom == 0.0F) {
|
||||
continue;
|
||||
}
|
||||
boolean blend = alphaTop < 1.0f || alphaBottom < 1.0f;
|
||||
if(blend != isBlend) {
|
||||
if(blend) {
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1, 0);
|
||||
}else {
|
||||
GlStateManager.disableBlend();
|
||||
}
|
||||
isBlend = blend;
|
||||
}
|
||||
int px = width - tex.width;
|
||||
drawTexturedGradientFBRect(px, baseOffset, tex.width, tex.height,
|
||||
((int) (alphaTop * 255.0f) << 24) | 0xFFFFFF,
|
||||
((int) (alphaBottom * 255.0f) << 24) | 0xFFFFFF, 200.0f);
|
||||
if(showXButtons && tex.hasHoverEvents) {
|
||||
if(mouseX >= px && mouseY >= baseOffset && mouseX < px + tex.width && mouseY < baseOffset + tex.height) {
|
||||
List<ClickEventZone> cursorEvents = tex.cursorEvents;
|
||||
if(cursorEvents != null) {
|
||||
for(int j = 0, m = cursorEvents.size(); j < m; ++j) {
|
||||
ClickEventZone evt = cursorEvents.get(j);
|
||||
if(evt.hasHoverEvent) {
|
||||
int offsetPosX = px + evt.posX;
|
||||
int offsetPosY = baseOffset + evt.posY;
|
||||
if(mouseX >= offsetPosX && mouseY >= offsetPosY && mouseX < offsetPosX + evt.width
|
||||
&& mouseY < offsetPosY + evt.height) {
|
||||
if(isBlend) {
|
||||
GlStateManager.disableBlend();
|
||||
isBlend = false;
|
||||
}
|
||||
mc.currentScreen.handleComponentHover(evt.chatComponent, mouseX, mouseY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
baseOffset += tex.height * alphaTop;
|
||||
}
|
||||
}
|
||||
if(isBlend) {
|
||||
GlStateManager.disableBlend();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected CachedNotifBadgeTexture renderBadge(NotificationBadge badge, int scaleFactor, boolean showXButton) {
|
||||
int badgeWidth = BADGE_WIDTH;
|
||||
int badgeHeight = 10;
|
||||
|
||||
int leftPadding = 6;
|
||||
int rightPadding = 26;
|
||||
|
||||
int mainIconSW = 32;
|
||||
if(badge.mainIcon != null) {
|
||||
int iw = badge.mainIcon.texture.getWidth();
|
||||
int ih = badge.mainIcon.texture.getHeight();
|
||||
float iaspect = (float)iw / (float)ih;
|
||||
mainIconSW = (int)(32 * iaspect);
|
||||
leftPadding += Math.min(mainIconSW, 64) + 3;
|
||||
}
|
||||
|
||||
int textZoneWidth = badgeWidth - leftPadding - rightPadding;
|
||||
int bodyYOffset = 5;
|
||||
|
||||
String titleText = null;
|
||||
IChatComponent titleComponent = badge.getTitleProfanityFilter();
|
||||
if(titleComponent != null) {
|
||||
titleText = titleComponent.getFormattedText();
|
||||
if(titleText.length() > 0) {
|
||||
badgeHeight += 12;
|
||||
bodyYOffset += 12;
|
||||
}else {
|
||||
titleText = null;
|
||||
}
|
||||
}
|
||||
|
||||
if(badge.titleIcon != null && titleText == null) {
|
||||
badgeHeight += 12;
|
||||
bodyYOffset += 12;
|
||||
}
|
||||
|
||||
float bodyFontSize = 0.75f;
|
||||
List<IChatComponent> bodyLines = null;
|
||||
List<ClickEventZone> clickEvents = null;
|
||||
IChatComponent rootClickEvt = null;
|
||||
boolean hasClickEvents = false;
|
||||
boolean hasHoverEvents = false;
|
||||
|
||||
int bodyHeight = 0;
|
||||
|
||||
IChatComponent bodyComponent = badge.getBodyProfanityFilter();
|
||||
if(bodyComponent != null) {
|
||||
if (bodyComponent.getChatStyle().getChatClickEvent() != null
|
||||
&& bodyComponent.getChatStyle().getChatClickEvent().getAction().shouldAllowInChat()) {
|
||||
rootClickEvt = bodyComponent;
|
||||
}
|
||||
bodyLines = GuiUtilRenderComponents.func_178908_a(bodyComponent, (int) (textZoneWidth / bodyFontSize),
|
||||
mc.fontRendererObj, true, true);
|
||||
|
||||
int maxHeight = BADGE_HEIGHT - 32;
|
||||
int maxLines = MathHelper.floor_float(maxHeight / (9 * bodyFontSize));
|
||||
if(bodyLines.size() > maxLines) {
|
||||
bodyLines = bodyLines.subList(0, maxLines);
|
||||
bodyComponent = bodyLines.get(maxLines - 1);
|
||||
List<IChatComponent> siblings = bodyComponent.getSiblings();
|
||||
IChatComponent dots = new ChatComponentText("...");
|
||||
if(siblings != null && siblings.size() > 0) {
|
||||
dots.setChatStyle(siblings.get(siblings.size() - 1).getChatStyle());
|
||||
}
|
||||
bodyComponent.appendSibling(dots);
|
||||
}
|
||||
bodyHeight = MathHelper.floor_float(bodyLines.size() * (9 * bodyFontSize));
|
||||
}
|
||||
|
||||
String sourceText = null;
|
||||
IChatComponent sourceComponent = badge.getSourceProfanityFilter();
|
||||
if(sourceComponent != null) {
|
||||
sourceText = sourceComponent.getFormattedText();
|
||||
if(sourceText.length() == 0) {
|
||||
sourceText = null;
|
||||
}
|
||||
}
|
||||
|
||||
if(badge.mainIcon != null) {
|
||||
bodyHeight = Math.max(sourceText != null ? 30 : 32, bodyHeight);
|
||||
}
|
||||
|
||||
if(sourceText != null) {
|
||||
badgeHeight += 6;
|
||||
}
|
||||
|
||||
badgeHeight += bodyHeight;
|
||||
|
||||
badgeHeight = Math.max(badgeHeight, showXButton ? 42 : 26);
|
||||
|
||||
if(badgeHeight > BADGE_HEIGHT) {
|
||||
logger.info("Warning: Badge {} was {} pixels too high!", badge.badgeUUID, BADGE_HEIGHT - badgeHeight);
|
||||
badgeHeight = BADGE_HEIGHT;
|
||||
}
|
||||
|
||||
int glTex = GlStateManager.generateTexture();
|
||||
GlStateManager.bindTexture(glTex);
|
||||
EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
EaglercraftGPU.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, badgeWidth * scaleFactor, badgeHeight * scaleFactor, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, (ByteBuffer) null);
|
||||
_wglBindFramebuffer(_GL_FRAMEBUFFER, rendererFramebuffer);
|
||||
_wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(glTex), 0);
|
||||
_wglDrawBuffers(_GL_COLOR_ATTACHMENT0);
|
||||
|
||||
int[] oldViewport = new int[4];
|
||||
EaglercraftGPU.glGetInteger(GL_VIEWPORT, oldViewport);
|
||||
|
||||
GlStateManager.viewport(0, 0, badgeWidth * scaleFactor, badgeHeight * scaleFactor);
|
||||
|
||||
GlStateManager.disableDepth();
|
||||
GlStateManager.depthMask(false);
|
||||
GlStateManager.enableTexture2D();
|
||||
GlStateManager.disableLighting();
|
||||
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
GlStateManager.matrixMode(GL_PROJECTION);
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.loadIdentity();
|
||||
GlStateManager.ortho(0.0D, badgeWidth, badgeHeight, 0.0D, 1000.0D, 3000.0D);
|
||||
GlStateManager.matrixMode(GL_MODELVIEW);
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.loadIdentity();
|
||||
GlStateManager.translate(0.0F, 0.0F, -2000.0F);
|
||||
|
||||
Tessellator tess = Tessellator.getInstance();
|
||||
WorldRenderer worldRenderer = tess.getWorldRenderer();
|
||||
|
||||
worldRenderer.begin(GL_QUADS, VertexFormat.POSITION_TEX_COLOR);
|
||||
|
||||
mc.getTextureManager().bindTexture(eaglerGui);
|
||||
|
||||
drawTexturedColoredRect(worldRenderer, 0, 0, 96, 192, 160, 8, (badge.backgroundColor >>> 16) & 0xFF,
|
||||
(badge.backgroundColor >>> 8) & 0xFF, badge.backgroundColor & 0xFF, 0xFF);
|
||||
|
||||
drawTexturedColoredRect(worldRenderer, 0, 8, 96, 192 + (BADGE_HEIGHT - badgeHeight + 8), 160, (badgeHeight - 8),
|
||||
(badge.backgroundColor >>> 16) & 0xFF, (badge.backgroundColor >>> 8) & 0xFF,
|
||||
badge.backgroundColor & 0xFF, 0xFF);
|
||||
|
||||
switch(badge.priority) {
|
||||
case LOW:
|
||||
default:
|
||||
drawTexturedColoredRect(worldRenderer, badgeWidth - 21, badgeHeight - 21, 192, 176, 16, 16, (badge.backgroundColor >>> 16) & 0xFF,
|
||||
(badge.backgroundColor >>> 8) & 0xFF, badge.backgroundColor & 0xFF, 0xFF);
|
||||
break;
|
||||
case NORMAL:
|
||||
drawTexturedColoredRect(worldRenderer, badgeWidth - 21, badgeHeight - 21, 208, 176, 16, 16, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||
break;
|
||||
case HIGHER:
|
||||
drawTexturedColoredRect(worldRenderer, badgeWidth - 21, badgeHeight - 21, 224, 176, 16, 16, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||
break;
|
||||
case HIGHEST:
|
||||
drawTexturedColoredRect(worldRenderer, badgeWidth - 21, badgeHeight - 21, 240, 176, 16, 16, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||
break;
|
||||
}
|
||||
|
||||
if(showXButton) {
|
||||
drawTexturedColoredRect(worldRenderer, badgeWidth - 21, 5, 80, 208, 16, 16, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||
}
|
||||
|
||||
tess.draw();
|
||||
|
||||
if(badge.mainIcon != null) {
|
||||
mc.getTextureManager().bindTexture(badge.mainIcon.resource);
|
||||
drawTexturedRect(6, bodyYOffset, mainIconSW, 32);
|
||||
}
|
||||
|
||||
if(badge.titleIcon != null) {
|
||||
mc.getTextureManager().bindTexture(badge.titleIcon.resource);
|
||||
drawTexturedRect(6, 5, 8, 8);
|
||||
}
|
||||
|
||||
if(titleText != null) {
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate(6 + (badge.titleIcon != null ? 10 : 0), 6, 0.0f);
|
||||
GlStateManager.scale(0.75f, 0.75f, 0.75f);
|
||||
mc.fontRendererObj.drawStringWithShadow(titleText, 0, 0, badge.titleTxtColor);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
if(bodyLines != null && !bodyLines.isEmpty()) {
|
||||
GlStateManager.pushMatrix();
|
||||
if(!showXButton && badge.mainIcon == null && titleText != null) {
|
||||
bodyYOffset -= 2;
|
||||
}
|
||||
GlStateManager.translate(leftPadding, bodyYOffset, 0.0f);
|
||||
int l = bodyLines.size();
|
||||
GlStateManager.scale(bodyFontSize, bodyFontSize, bodyFontSize);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
int startXLocal = 0;
|
||||
int startXReal = leftPadding;
|
||||
for(IChatComponent comp : bodyLines.get(i)) {
|
||||
int w = mc.fontRendererObj.drawStringWithShadow(
|
||||
comp.getChatStyle().getFormattingCode() + comp.getUnformattedTextForChat(), startXLocal,
|
||||
i * 9, badge.bodyTxtColor) - startXLocal;
|
||||
ClickEvent clickEvent = comp.getChatStyle().getChatClickEvent();
|
||||
HoverEvent hoverEvent = comp.getChatStyle().getChatHoverEvent();
|
||||
if(clickEvent != null && !clickEvent.getAction().shouldAllowInChat()) {
|
||||
clickEvent = null;
|
||||
}
|
||||
if(hoverEvent != null && !hoverEvent.getAction().shouldAllowInChat()) {
|
||||
hoverEvent = null;
|
||||
}
|
||||
if(clickEvent != null || hoverEvent != null) {
|
||||
hasClickEvents |= clickEvent != null;
|
||||
hasHoverEvents |= hoverEvent != null;
|
||||
if(clickEvents == null) {
|
||||
clickEvents = new ArrayList<>();
|
||||
}
|
||||
clickEvents.add(new ClickEventZone(startXReal + (int) (startXLocal * bodyFontSize),
|
||||
bodyYOffset + (int) (i * 9 * bodyFontSize), (int) (w * bodyFontSize),
|
||||
(int) (9 * bodyFontSize), comp, clickEvent != null, hoverEvent != null));
|
||||
}
|
||||
startXLocal += w;
|
||||
}
|
||||
}
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
if(sourceText != null) {
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate(badgeWidth - 21, badgeHeight - 5, 0.0f);
|
||||
GlStateManager.scale(0.5f, 0.5f, 0.5f);
|
||||
mc.fontRendererObj.drawStringWithShadow(sourceText, -mc.fontRendererObj.getStringWidth(sourceText) - 4, -10, badge.sourceTxtColor);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
GlStateManager.matrixMode(GL_PROJECTION);
|
||||
GlStateManager.popMatrix();
|
||||
GlStateManager.matrixMode(GL_MODELVIEW);
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
GlStateManager.depthMask(true);
|
||||
GlStateManager.enableDepth();
|
||||
|
||||
_wglBindFramebuffer(_GL_FRAMEBUFFER, null);
|
||||
GlStateManager.viewport(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
|
||||
|
||||
return new CachedNotifBadgeTexture(glTex, scaleFactor, badgeWidth, badgeHeight, clickEvents, rootClickEvt, hasClickEvents, hasHoverEvents);
|
||||
}
|
||||
|
||||
static void drawTexturedColoredRect(WorldRenderer worldRenderer, float xCoord, float yCoord, int minU,
|
||||
int minV, int width, int height, int r, int g, int b, int a) {
|
||||
float f = 0.00390625F;
|
||||
float f1 = 0.00390625F;
|
||||
worldRenderer.pos((double) (xCoord + 0.0F), (double) (yCoord + (float) height), 0.0).color(r, g, b, a)
|
||||
.tex((double) ((float) (minU + 0) * f), (double) ((float) (minV + height) * f1)).endVertex();
|
||||
worldRenderer.pos((double) (xCoord + (float) width), (double) (yCoord + (float) height), 0.0).color(r, g, b, a)
|
||||
.tex((double) ((float) (minU + width) * f), (double) ((float) (minV + height) * f1)).endVertex();
|
||||
worldRenderer.pos((double) (xCoord + (float) width), (double) (yCoord + 0.0F), 0.0).color(r, g, b, a)
|
||||
.tex((double) ((float) (minU + width) * f), (double) ((float) (minV + 0) * f1)).endVertex();
|
||||
worldRenderer.pos((double) (xCoord + 0.0F), (double) (yCoord + 0.0F), 0.0).color(r, g, b, a)
|
||||
.tex((double) ((float) (minU + 0) * f), (double) ((float) (minV + 0) * f1)).endVertex();
|
||||
}
|
||||
|
||||
static void drawTexturedGradientFBRect(float xCoord, float yCoord, int width, int height, int rgbaTop, int rgbaBottom, float zIndex) {
|
||||
int topR = (rgbaTop >>> 16) & 0xFF;
|
||||
int topG = (rgbaTop >>> 8) & 0xFF;
|
||||
int topB = rgbaTop & 0xFF;
|
||||
int topA = (rgbaTop >>> 24) & 0xFF;
|
||||
int bottomR = (rgbaBottom >>> 16) & 0xFF;
|
||||
int bottomG = (rgbaBottom >>> 8) & 0xFF;
|
||||
int bottomB = rgbaBottom & 0xFF;
|
||||
int bottomA = (rgbaBottom >>> 24) & 0xFF;
|
||||
Tessellator tess = Tessellator.getInstance();
|
||||
WorldRenderer worldRenderer = tess.getWorldRenderer();
|
||||
worldRenderer.begin(GL_QUADS, VertexFormat.POSITION_TEX_COLOR);
|
||||
worldRenderer.pos((double) (xCoord + 0.0F), (double) (yCoord + (float) height), zIndex)
|
||||
.color(bottomR, bottomG, bottomB, bottomA).tex(0.0, 0.0).endVertex();
|
||||
worldRenderer.pos((double) (xCoord + (float) width), (double) (yCoord + (float) height), zIndex)
|
||||
.color(bottomR, bottomG, bottomB, bottomA).tex(1.0, 0.0).endVertex();
|
||||
worldRenderer.pos((double) (xCoord + (float) width), (double) (yCoord + 0.0F), zIndex)
|
||||
.color(topR, topG, topB, topA).tex(1.0, 1.0).endVertex();
|
||||
worldRenderer.pos((double) (xCoord + 0.0F), (double) (yCoord + 0.0F), zIndex).color(topR, topG, topB, topA)
|
||||
.tex(0.0, 1.0).endVertex();
|
||||
tess.draw();
|
||||
}
|
||||
|
||||
static void drawTexturedRect(float xCoord, float yCoord, int width, int height) {
|
||||
Tessellator tess = Tessellator.getInstance();
|
||||
WorldRenderer worldRenderer = tess.getWorldRenderer();
|
||||
worldRenderer.begin(GL_QUADS, VertexFormat.POSITION_TEX);
|
||||
worldRenderer.pos((double) (xCoord + 0.0F), (double) (yCoord + (float) height), 0.0).tex(0.0, 1.0).endVertex();
|
||||
worldRenderer.pos((double) (xCoord + (float) width), (double) (yCoord + (float) height), 0.0).tex(1.0, 1.0).endVertex();
|
||||
worldRenderer.pos((double) (xCoord + (float) width), (double) (yCoord + 0.0F), 0.0).tex(1.0, 0.0).endVertex();
|
||||
worldRenderer.pos((double) (xCoord + 0.0F), (double) (yCoord + 0.0F), 0.0).tex(0.0, 0.0).endVertex();
|
||||
tess.draw();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if(rendererFramebuffer != null) {
|
||||
_wglDeleteFramebuffer(rendererFramebuffer);
|
||||
rendererFramebuffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -3,15 +3,16 @@ package net.lax1dude.eaglercraft.v1_8.opengl;
|
||||
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
|
||||
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IBufferArrayGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2023 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
|
||||
@ -28,17 +29,19 @@ import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionCon
|
||||
public class DrawUtils {
|
||||
|
||||
public static final String vertexShaderPath = "/assets/eagler/glsl/local.vsh";
|
||||
public static final String vertexShaderPrecision = "precision highp float;\n";
|
||||
|
||||
public static IBufferArrayGL standardQuad2DVAO = null;
|
||||
public static IBufferArrayGL standardQuad3DVAO = null;
|
||||
public static IBufferGL standardQuadVBO = null;
|
||||
|
||||
public static IShaderGL vshLocal = null;
|
||||
public static List<VSHInputLayoutParser.ShaderInput> vshLocalLayout = null;
|
||||
|
||||
static void init() {
|
||||
if(standardQuad2DVAO == null) {
|
||||
standardQuad2DVAO = _wglGenVertexArrays();
|
||||
standardQuad3DVAO = _wglGenVertexArrays();
|
||||
standardQuad2DVAO = EaglercraftGPU.createGLBufferArray();
|
||||
standardQuad3DVAO = EaglercraftGPU.createGLBufferArray();
|
||||
standardQuadVBO = _wglGenBuffers();
|
||||
|
||||
FloatBuffer verts = EagRuntime.allocateFloatBuffer(18);
|
||||
@ -48,30 +51,29 @@ public class DrawUtils {
|
||||
});
|
||||
verts.flip();
|
||||
|
||||
EaglercraftGPU.bindGLArrayBuffer(standardQuadVBO);
|
||||
EaglercraftGPU.bindVAOGLArrayBufferNow(standardQuadVBO);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, verts, GL_STATIC_DRAW);
|
||||
EagRuntime.freeFloatBuffer(verts);
|
||||
|
||||
EaglercraftGPU.bindGLBufferArray(standardQuad2DVAO);
|
||||
|
||||
_wglEnableVertexAttribArray(0);
|
||||
_wglVertexAttribPointer(0, 2, GL_FLOAT, false, 12, 0);
|
||||
EaglercraftGPU.enableVertexAttribArray(0);
|
||||
EaglercraftGPU.vertexAttribPointer(0, 2, GL_FLOAT, false, 12, 0);
|
||||
|
||||
EaglercraftGPU.bindGLBufferArray(standardQuad3DVAO);
|
||||
|
||||
_wglEnableVertexAttribArray(0);
|
||||
_wglVertexAttribPointer(0, 3, GL_FLOAT, false, 12, 0);
|
||||
EaglercraftGPU.enableVertexAttribArray(0);
|
||||
EaglercraftGPU.vertexAttribPointer(0, 3, GL_FLOAT, false, 12, 0);
|
||||
}
|
||||
|
||||
if(vshLocal == null) {
|
||||
String vertexSource = EagRuntime.getResourceString(vertexShaderPath);
|
||||
if(vertexSource == null) {
|
||||
throw new RuntimeException("vertex shader \"" + vertexShaderPath + "\" is missing!");
|
||||
}
|
||||
|
||||
String vertexSource = EagRuntime.getRequiredResourceString(vertexShaderPath);
|
||||
|
||||
vshLocalLayout = VSHInputLayoutParser.getShaderInputs(vertexSource);
|
||||
|
||||
vshLocal = _wglCreateShader(GL_VERTEX_SHADER);
|
||||
|
||||
_wglShaderSource(vshLocal, FixedFunctionConstants.VERSION + "\n" + vertexSource);
|
||||
|
||||
_wglShaderSource(vshLocal, GLSLHeader.getVertexHeaderCompat(vertexSource, vertexShaderPrecision));
|
||||
_wglCompileShader(vshLocal);
|
||||
|
||||
if(_wglGetShaderi(vshLocal, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
@ -90,12 +92,32 @@ public class DrawUtils {
|
||||
|
||||
public static void drawStandardQuad2D() {
|
||||
EaglercraftGPU.bindGLBufferArray(standardQuad2DVAO);
|
||||
_wglDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
EaglercraftGPU.doDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
}
|
||||
|
||||
public static void drawStandardQuad3D() {
|
||||
EaglercraftGPU.bindGLBufferArray(standardQuad3DVAO);
|
||||
_wglDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
EaglercraftGPU.doDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
}
|
||||
|
||||
public static void destroy() {
|
||||
if(standardQuad2DVAO != null) {
|
||||
EaglercraftGPU.destroyGLBufferArray(standardQuad2DVAO);
|
||||
standardQuad2DVAO = null;
|
||||
}
|
||||
if(standardQuad3DVAO != null) {
|
||||
EaglercraftGPU.destroyGLBufferArray(standardQuad3DVAO);
|
||||
standardQuad3DVAO = null;
|
||||
}
|
||||
if(standardQuadVBO != null) {
|
||||
_wglDeleteBuffers(standardQuadVBO);
|
||||
standardQuadVBO = null;
|
||||
}
|
||||
if(vshLocal != null) {
|
||||
vshLocal.free();
|
||||
vshLocal = null;
|
||||
vshLocalLayout = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public class EaglerMeshLoader implements IResourceManagerReloadListener {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger("EaglerMeshLoader");
|
||||
|
||||
private static final Map<ResourceLocation, HighPolyMesh> meshCache = new HashMap();
|
||||
private static final Map<ResourceLocation, HighPolyMesh> meshCache = new HashMap<>();
|
||||
|
||||
public static HighPolyMesh getEaglerMesh(ResourceLocation meshLoc) {
|
||||
if(meshLoc.cachedPointerType == ResourceLocation.CACHED_POINTER_EAGLER_MESH) {
|
||||
@ -104,7 +104,7 @@ public class EaglerMeshLoader implements IResourceManagerReloadListener {
|
||||
}
|
||||
|
||||
if(meshStruct.vertexArray == null) {
|
||||
meshStruct.vertexArray = _wglGenVertexArrays();
|
||||
meshStruct.vertexArray = EaglercraftGPU.createGLBufferArray();
|
||||
}
|
||||
if(meshStruct.vertexBuffer == null) {
|
||||
meshStruct.vertexBuffer = _wglGenBuffers();
|
||||
@ -115,29 +115,29 @@ public class EaglerMeshLoader implements IResourceManagerReloadListener {
|
||||
|
||||
up1.position(0).limit(intsOfVertex);
|
||||
|
||||
EaglercraftGPU.bindGLArrayBuffer(meshStruct.vertexBuffer);
|
||||
EaglercraftGPU.bindVAOGLArrayBufferNow(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);
|
||||
EaglercraftGPU.bindVAOGLElementArrayBufferNow(meshStruct.indexBuffer);
|
||||
_wglBufferData(GL_ELEMENT_ARRAY_BUFFER, up1, GL_STATIC_DRAW);
|
||||
|
||||
_wglEnableVertexAttribArray(0);
|
||||
_wglVertexAttribPointer(0, 3, GL_FLOAT, false, stride, 0);
|
||||
EaglercraftGPU.enableVertexAttribArray(0);
|
||||
EaglercraftGPU.vertexAttribPointer(0, 3, GL_FLOAT, false, stride, 0);
|
||||
|
||||
if(meshStruct.hasTexture) {
|
||||
_wglEnableVertexAttribArray(1);
|
||||
_wglVertexAttribPointer(1, 2, GL_FLOAT, false, stride, 16);
|
||||
EaglercraftGPU.enableVertexAttribArray(1);
|
||||
EaglercraftGPU.vertexAttribPointer(1, 2, GL_FLOAT, false, stride, 16);
|
||||
}
|
||||
|
||||
_wglEnableVertexAttribArray(meshStruct.hasTexture ? 2 : 1);
|
||||
_wglVertexAttribPointer(meshStruct.hasTexture ? 2 : 1, 4, GL_BYTE, true, stride, 12);
|
||||
EaglercraftGPU.enableVertexAttribArray(meshStruct.hasTexture ? 2 : 1);
|
||||
EaglercraftGPU.vertexAttribPointer(meshStruct.hasTexture ? 2 : 1, 4, GL_BYTE, true, stride, 12);
|
||||
}catch(Throwable ex) {
|
||||
if(meshStruct.vertexArray != null) {
|
||||
_wglDeleteVertexArrays(meshStruct.vertexArray);
|
||||
EaglercraftGPU.destroyGLBufferArray(meshStruct.vertexArray);
|
||||
meshStruct.vertexArray = null;
|
||||
}
|
||||
if(meshStruct.vertexBuffer != null) {
|
||||
|
@ -5,6 +5,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
|
||||
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.util.MathHelper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -16,7 +17,6 @@ import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IQueryGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.ITextureGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformBufferFunctions;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL;
|
||||
|
||||
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
|
||||
@ -39,12 +39,15 @@ import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
|
||||
*/
|
||||
public class EaglercraftGPU {
|
||||
|
||||
static final GLObjectMap<ITextureGL> mapTexturesGL = new GLObjectMap(32767);
|
||||
static final GLObjectMap<IQueryGL> mapQueriesGL = new GLObjectMap(32767);
|
||||
static final GLObjectMap<DisplayList> mapDisplayListsGL = new GLObjectMap(32767);
|
||||
static final GLObjectMap<ITextureGL> mapTexturesGL = new GLObjectMap<>(8192);
|
||||
static final GLObjectMap<IQueryGL> mapQueriesGL = new GLObjectMap<>(8192);
|
||||
static final GLObjectMap<DisplayList> mapDisplayListsGL = new GLObjectMap<>(8192);
|
||||
|
||||
static final Logger logger = LogManager.getLogger("EaglercraftGPU");
|
||||
|
||||
static boolean emulatedVAOs = false;
|
||||
static SoftGLBufferState emulatedVAOState = new SoftGLBufferState();
|
||||
|
||||
public static final String gluErrorString(int i) {
|
||||
switch(i) {
|
||||
case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
|
||||
@ -87,16 +90,16 @@ public class EaglercraftGPU {
|
||||
EaglercraftGPU.bindGLBufferArray(dp.vertexArray);
|
||||
int c = 0;
|
||||
if((dp.attribs & ATTRIB_TEXTURE) == ATTRIB_TEXTURE) {
|
||||
_wglDisableVertexAttribArray(++c);
|
||||
EaglercraftGPU.disableVertexAttribArray(++c);
|
||||
}
|
||||
if((dp.attribs & ATTRIB_COLOR) == ATTRIB_COLOR) {
|
||||
_wglDisableVertexAttribArray(++c);
|
||||
EaglercraftGPU.disableVertexAttribArray(++c);
|
||||
}
|
||||
if((dp.attribs & ATTRIB_NORMAL) == ATTRIB_NORMAL) {
|
||||
_wglDisableVertexAttribArray(++c);
|
||||
EaglercraftGPU.disableVertexAttribArray(++c);
|
||||
}
|
||||
if((dp.attribs & ATTRIB_LIGHTMAP) == ATTRIB_LIGHTMAP) {
|
||||
_wglDisableVertexAttribArray(++c);
|
||||
EaglercraftGPU.disableVertexAttribArray(++c);
|
||||
}
|
||||
}
|
||||
dp.attribs = -1;
|
||||
@ -109,7 +112,7 @@ public class EaglercraftGPU {
|
||||
if(displayListBuffer.capacity() < wantSize) {
|
||||
int newSize = (wantSize & 0xFFFE0000) + 0x40000;
|
||||
ByteBuffer newBuffer = EagRuntime.allocateByteBuffer(newSize);
|
||||
PlatformBufferFunctions.put(newBuffer, (ByteBuffer)displayListBuffer.flip());
|
||||
newBuffer.put((ByteBuffer)displayListBuffer.flip());
|
||||
EagRuntime.freeByteBuffer(displayListBuffer);
|
||||
displayListBuffer = newBuffer;
|
||||
}
|
||||
@ -123,7 +126,7 @@ public class EaglercraftGPU {
|
||||
|
||||
if(dp.attribs == -1) {
|
||||
if(dp.vertexArray != null) {
|
||||
_wglDeleteVertexArrays(dp.vertexArray);
|
||||
EaglercraftGPU.destroyGLBufferArray(dp.vertexArray);
|
||||
dp.vertexArray = null;
|
||||
}
|
||||
if(dp.vertexBuffer != null) {
|
||||
@ -135,7 +138,7 @@ public class EaglercraftGPU {
|
||||
}
|
||||
|
||||
if(dp.vertexArray == null) {
|
||||
dp.vertexArray = _wglGenVertexArrays();
|
||||
dp.vertexArray = createGLBufferArray();
|
||||
dp.bindQuad16 = false;
|
||||
dp.bindQuad32 = false;
|
||||
}
|
||||
@ -143,7 +146,7 @@ public class EaglercraftGPU {
|
||||
dp.vertexBuffer = _wglGenBuffers();
|
||||
}
|
||||
|
||||
bindGLArrayBuffer(dp.vertexBuffer);
|
||||
bindVAOGLArrayBufferNow(dp.vertexBuffer);
|
||||
displayListBuffer.flip();
|
||||
_wglBufferData(GL_ARRAY_BUFFER, displayListBuffer, GL_STATIC_DRAW);
|
||||
displayListBuffer.clear();
|
||||
@ -194,7 +197,7 @@ public class EaglercraftGPU {
|
||||
}
|
||||
dp.attribs = -1;
|
||||
if(dp.vertexArray != null) {
|
||||
_wglDeleteVertexArrays(dp.vertexArray);
|
||||
EaglercraftGPU.destroyGLBufferArray(dp.vertexArray);
|
||||
dp.vertexArray = null;
|
||||
}
|
||||
if(dp.vertexBuffer != null) {
|
||||
@ -210,7 +213,7 @@ public class EaglercraftGPU {
|
||||
++GlStateManager.stateNormalSerial;
|
||||
}
|
||||
|
||||
private static final Map<Integer,String> stringCache = new HashMap();
|
||||
private static final Map<Integer,String> stringCache = new HashMap<>();
|
||||
|
||||
public static final String glGetString(int param) {
|
||||
String str = stringCache.get(param);
|
||||
@ -238,9 +241,24 @@ public class EaglercraftGPU {
|
||||
return _wglGetInteger(param);
|
||||
}
|
||||
|
||||
public static final void glTexImage2D(int target, int level, int internalFormat, int w, int h, int unused,
|
||||
int format, int type, ByteBuffer pixels) {
|
||||
if(glesVers >= 300) {
|
||||
_wglTexImage2D(target, level, internalFormat, w, h, unused, format, type, pixels);
|
||||
}else {
|
||||
int tv = TextureFormatHelper.trivializeInternalFormatToGLES20(internalFormat);
|
||||
_wglTexImage2D(target, level, tv, w, h, unused, tv, type, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
public static final void glTexImage2D(int target, int level, int internalFormat, int w, int h, int unused,
|
||||
int format, int type, IntBuffer pixels) {
|
||||
_wglTexImage2D(target, level, internalFormat, w, h, unused, format, type, pixels);
|
||||
if(glesVers >= 300) {
|
||||
_wglTexImage2D(target, level, internalFormat, w, h, unused, format, type, pixels);
|
||||
}else {
|
||||
int tv = TextureFormatHelper.trivializeInternalFormatToGLES20(internalFormat);
|
||||
_wglTexImage2D(target, level, tv, w, h, unused, tv, type, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
public static final void glTexSubImage2D(int target, int level, int x, int y, int w, int h, int format,
|
||||
@ -249,9 +267,32 @@ public class EaglercraftGPU {
|
||||
}
|
||||
|
||||
public static final void glTexStorage2D(int target, int levels, int internalFormat, int w, int h) {
|
||||
_wglTexStorage2D(target, levels, internalFormat, w, h);
|
||||
if(texStorageCapable && (glesVers >= 300 || levels == 1 || (MathHelper.calculateLogBaseTwo(Math.max(w, h)) + 1) == levels)) {
|
||||
_wglTexStorage2D(target, levels, internalFormat, w, h);
|
||||
}else {
|
||||
int tv = TextureFormatHelper.trivializeInternalFormatToGLES20(internalFormat);
|
||||
int type = TextureFormatHelper.getTypeFromInternal(internalFormat);
|
||||
for(int i = 0; i < levels; ++i) {
|
||||
_wglTexImage2D(target, i, tv, Math.max(w >> i, 1), Math.max(h >> i, 1), 0, tv, type, (ByteBuffer)null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static final void glReadPixels(int x, int y, int width, int height, int format, int type, ByteBuffer buffer) {
|
||||
switch(type) {
|
||||
case GL_FLOAT:
|
||||
_wglReadPixels(x, y, width, height, format, GL_FLOAT, buffer.asFloatBuffer());
|
||||
break;
|
||||
case 0x140B: // GL_HALF_FLOAT
|
||||
_wglReadPixels_u16(x, y, width, height, format, glesVers == 200 ? 0x8D61 : 0x140B, buffer);
|
||||
break;
|
||||
case GL_UNSIGNED_BYTE:
|
||||
default:
|
||||
_wglReadPixels(x, y, width, height, format, type, buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static final void glLineWidth(float f) {
|
||||
_wglLineWidth(f);
|
||||
}
|
||||
@ -284,7 +325,7 @@ public class EaglercraftGPU {
|
||||
DisplayList d = mapDisplayListsGL.free(id);
|
||||
if(d != null) {
|
||||
if(d.vertexArray != null) {
|
||||
_wglDeleteVertexArrays(d.vertexArray);
|
||||
EaglercraftGPU.destroyGLBufferArray(d.vertexArray);
|
||||
}
|
||||
if(d.vertexBuffer != null) {
|
||||
_wglDeleteBuffers(d.vertexBuffer);
|
||||
@ -302,18 +343,197 @@ public class EaglercraftGPU {
|
||||
GlStateManager.stateBlendEquation = equation;
|
||||
}
|
||||
}
|
||||
|
||||
private static IBufferArrayGL currentBufferArray = null;
|
||||
|
||||
public static final void bindGLBufferArray(IBufferArrayGL buffer) {
|
||||
if(currentBufferArray != buffer) {
|
||||
_wglBindVertexArray(buffer);
|
||||
currentBufferArray = buffer;
|
||||
|
||||
public static final boolean areVAOsEmulated() {
|
||||
return emulatedVAOs;
|
||||
}
|
||||
|
||||
public static final IBufferArrayGL createGLBufferArray() {
|
||||
if(emulatedVAOs) {
|
||||
return new SoftGLBufferArray();
|
||||
}else {
|
||||
return _wglGenVertexArrays();
|
||||
}
|
||||
}
|
||||
|
||||
public static final void destroyGLBufferArray(IBufferArrayGL buffer) {
|
||||
if(!emulatedVAOs) {
|
||||
_wglDeleteVertexArrays(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static final void enableVertexAttribArray(int index) {
|
||||
if(emulatedVAOs) {
|
||||
if(currentBufferArray == null) {
|
||||
logger.warn("Skipping enable attrib with emulated VAO because no known VAO is bound!");
|
||||
return;
|
||||
}
|
||||
((SoftGLBufferArray)currentBufferArray).enableAttrib(index, true);
|
||||
}else {
|
||||
_wglEnableVertexAttribArray(index);
|
||||
}
|
||||
}
|
||||
|
||||
public static final void disableVertexAttribArray(int index) {
|
||||
if(emulatedVAOs) {
|
||||
if(currentBufferArray == null) {
|
||||
logger.warn("Skipping disable attrib with emulated VAO because no known VAO is bound!");
|
||||
return;
|
||||
}
|
||||
((SoftGLBufferArray)currentBufferArray).enableAttrib(index, false);
|
||||
}else {
|
||||
_wglDisableVertexAttribArray(index);
|
||||
}
|
||||
}
|
||||
|
||||
public static final void vertexAttribPointer(int index, int size, int format, boolean normalized, int stride, int offset) {
|
||||
if(emulatedVAOs) {
|
||||
if(currentBufferArray == null) {
|
||||
logger.warn("Skipping vertexAttribPointer with emulated VAO because no known VAO is bound!");
|
||||
return;
|
||||
}
|
||||
if(currentVAOArrayBuffer == null) {
|
||||
logger.warn("Skipping vertexAttribPointer with emulated VAO because no VAO array buffer is bound!");
|
||||
return;
|
||||
}
|
||||
((SoftGLBufferArray)currentBufferArray).setAttrib(currentVAOArrayBuffer, index, size, format, normalized, stride, offset);
|
||||
}else {
|
||||
_wglVertexAttribPointer(index, size, format, normalized, stride, offset);
|
||||
}
|
||||
}
|
||||
|
||||
public static final void vertexAttribDivisor(int index, int divisor) {
|
||||
if(emulatedVAOs) {
|
||||
if(currentBufferArray == null) {
|
||||
logger.warn("Skipping vertexAttribPointer with emulated VAO because no known VAO is bound!");
|
||||
return;
|
||||
}
|
||||
((SoftGLBufferArray)currentBufferArray).setAttribDivisor(index, divisor);
|
||||
}else {
|
||||
_wglVertexAttribDivisor(index, divisor);
|
||||
}
|
||||
}
|
||||
|
||||
public static final void doDrawArrays(int mode, int first, int count) {
|
||||
if(emulatedVAOs) {
|
||||
if(currentBufferArray == null) {
|
||||
logger.warn("Skipping draw call with emulated VAO because no known VAO is bound!");
|
||||
return;
|
||||
}
|
||||
((SoftGLBufferArray)currentBufferArray).transitionToState(emulatedVAOState, false);
|
||||
}
|
||||
_wglDrawArrays(mode, first, count);
|
||||
}
|
||||
|
||||
public static final void doDrawElements(int mode, int count, int type, int offset) {
|
||||
if(emulatedVAOs) {
|
||||
if(currentBufferArray == null) {
|
||||
logger.warn("Skipping draw call with emulated VAO because no known VAO is bound!");
|
||||
return;
|
||||
}
|
||||
((SoftGLBufferArray)currentBufferArray).transitionToState(emulatedVAOState, true);
|
||||
}
|
||||
_wglDrawElements(mode, count, type, offset);
|
||||
}
|
||||
|
||||
public static final void doDrawArraysInstanced(int mode, int first, int count, int instances) {
|
||||
if(emulatedVAOs) {
|
||||
if(currentBufferArray == null) {
|
||||
logger.warn("Skipping instanced draw call with emulated VAO because no known VAO is bound!");
|
||||
return;
|
||||
}
|
||||
((SoftGLBufferArray)currentBufferArray).transitionToState(emulatedVAOState, false);
|
||||
}
|
||||
_wglDrawArraysInstanced(mode, first, count, instances);
|
||||
}
|
||||
|
||||
public static final void doDrawElementsInstanced(int mode, int count, int type, int offset, int instances) {
|
||||
if(emulatedVAOs) {
|
||||
if(currentBufferArray == null) {
|
||||
logger.warn("Skipping instanced draw call with emulated VAO because no known VAO is bound!");
|
||||
return;
|
||||
}
|
||||
((SoftGLBufferArray)currentBufferArray).transitionToState(emulatedVAOState, true);
|
||||
}
|
||||
_wglDrawElementsInstanced(mode, count, type, offset, instances);
|
||||
}
|
||||
|
||||
static IBufferArrayGL currentBufferArray = null;
|
||||
|
||||
private static IBufferGL currentArrayBuffer = null;
|
||||
|
||||
public static final void bindGLBufferArray(IBufferArrayGL buffer) {
|
||||
if(emulatedVAOs) {
|
||||
currentBufferArray = buffer;
|
||||
}else {
|
||||
if(currentBufferArray != buffer) {
|
||||
_wglBindVertexArray(buffer);
|
||||
currentBufferArray = buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static IBufferGL currentArrayBuffer = null;
|
||||
|
||||
// only used when VAOs are emulated
|
||||
static IBufferGL currentVAOArrayBuffer = null;
|
||||
|
||||
public static final void bindVAOGLArrayBuffer(IBufferGL buffer) {
|
||||
if(emulatedVAOs) {
|
||||
currentVAOArrayBuffer = buffer;
|
||||
}else {
|
||||
if(currentArrayBuffer != buffer) {
|
||||
_wglBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
currentArrayBuffer = buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final void bindVAOGLArrayBufferNow(IBufferGL buffer) {
|
||||
if(emulatedVAOs) {
|
||||
currentVAOArrayBuffer = buffer;
|
||||
}
|
||||
if(currentArrayBuffer != buffer) {
|
||||
_wglBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
currentArrayBuffer = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
public static final void bindVAOGLElementArrayBuffer(IBufferGL buffer) {
|
||||
if(emulatedVAOs) {
|
||||
if(currentBufferArray == null) {
|
||||
logger.warn("Skipping set element array buffer with emulated VAO because no known VAO is bound!");
|
||||
return;
|
||||
}
|
||||
((SoftGLBufferArray)currentBufferArray).setIndexBuffer(buffer);
|
||||
}else {
|
||||
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static final void bindVAOGLElementArrayBufferNow(IBufferGL buffer) {
|
||||
if(emulatedVAOs) {
|
||||
if(currentBufferArray == null) {
|
||||
logger.warn("Skipping set element array buffer with emulated VAO because no known VAO is bound!");
|
||||
return;
|
||||
}
|
||||
((SoftGLBufferArray)currentBufferArray).setIndexBuffer(buffer);
|
||||
if(currentEmulatedVAOIndexBuffer != buffer) {
|
||||
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
|
||||
currentEmulatedVAOIndexBuffer = buffer;
|
||||
}
|
||||
}else {
|
||||
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static IBufferGL currentEmulatedVAOIndexBuffer = null;
|
||||
|
||||
static final void bindEmulatedVAOIndexBuffer(IBufferGL buffer) {
|
||||
if(currentEmulatedVAOIndexBuffer != buffer) {
|
||||
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
|
||||
currentEmulatedVAOIndexBuffer = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
public static final void bindGLArrayBuffer(IBufferGL buffer) {
|
||||
if(currentArrayBuffer != buffer) {
|
||||
_wglBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
@ -321,7 +541,7 @@ public class EaglercraftGPU {
|
||||
}
|
||||
}
|
||||
|
||||
private static IBufferGL currentUniformBuffer = null;
|
||||
static IBufferGL currentUniformBuffer = null;
|
||||
|
||||
public static final void bindGLUniformBuffer(IBufferGL buffer) {
|
||||
if(currentUniformBuffer != buffer) {
|
||||
@ -330,7 +550,7 @@ public class EaglercraftGPU {
|
||||
}
|
||||
}
|
||||
|
||||
private static IProgramGL currentShaderProgram = null;
|
||||
static IProgramGL currentShaderProgram = null;
|
||||
|
||||
public static final void bindGLShaderProgram(IProgramGL prog) {
|
||||
if(currentShaderProgram != prog) {
|
||||
@ -352,6 +572,38 @@ public class EaglercraftGPU {
|
||||
currentUniformBlockBindingSize[index] = size;
|
||||
}
|
||||
}
|
||||
|
||||
public static final int CLEAR_BINDING_TEXTURE = 1;
|
||||
public static final int CLEAR_BINDING_TEXTURE0 = 2;
|
||||
public static final int CLEAR_BINDING_ACTIVE_TEXTURE = 4;
|
||||
public static final int CLEAR_BINDING_BUFFER_ARRAY = 8;
|
||||
public static final int CLEAR_BINDING_ARRAY_BUFFER = 16;
|
||||
public static final int CLEAR_BINDING_SHADER_PROGRAM = 32;
|
||||
|
||||
public static final void clearCurrentBinding(int mask) {
|
||||
if((mask & CLEAR_BINDING_TEXTURE) != 0) {
|
||||
int[] i = GlStateManager.boundTexture;
|
||||
for(int j = 0; j < i.length; ++j) {
|
||||
i[j] = -1;
|
||||
}
|
||||
}
|
||||
if((mask & CLEAR_BINDING_TEXTURE0) != 0) {
|
||||
GlStateManager.boundTexture[0] = -1;
|
||||
}
|
||||
if((mask & CLEAR_BINDING_ACTIVE_TEXTURE) != 0) {
|
||||
GlStateManager.activeTexture = 0;
|
||||
_wglActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
if((mask & CLEAR_BINDING_BUFFER_ARRAY) != 0) {
|
||||
currentBufferArray = null;
|
||||
}
|
||||
if((mask & CLEAR_BINDING_ARRAY_BUFFER) != 0) {
|
||||
currentArrayBuffer = currentVAOArrayBuffer = null;
|
||||
}
|
||||
if((mask & CLEAR_BINDING_SHADER_PROGRAM) != 0) {
|
||||
currentShaderProgram = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static final int ATTRIB_TEXTURE = 1;
|
||||
public static final int ATTRIB_COLOR = 2;
|
||||
@ -414,7 +666,7 @@ public class EaglercraftGPU {
|
||||
if(newSize > 0xFFFF) {
|
||||
newSize = 0xFFFF;
|
||||
}
|
||||
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
|
||||
EaglercraftGPU.bindVAOGLElementArrayBufferNow(buf);
|
||||
resizeQuad16EmulationBuffer(newSize >> 2);
|
||||
}else {
|
||||
int cnt = quad16EmulationBufferSize;
|
||||
@ -423,10 +675,10 @@ public class EaglercraftGPU {
|
||||
if(newSize > 0xFFFF) {
|
||||
newSize = 0xFFFF;
|
||||
}
|
||||
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
|
||||
EaglercraftGPU.bindVAOGLElementArrayBufferNow(buf);
|
||||
resizeQuad16EmulationBuffer(newSize >> 2);
|
||||
}else if(bind) {
|
||||
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
|
||||
EaglercraftGPU.bindVAOGLElementArrayBuffer(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -436,16 +688,16 @@ public class EaglercraftGPU {
|
||||
if(buf == null) {
|
||||
quad32EmulationBuffer = buf = _wglGenBuffers();
|
||||
int newSize = quad32EmulationBufferSize = (vertexCount & 0xFFFFC000) + 0x8000;
|
||||
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
|
||||
EaglercraftGPU.bindVAOGLElementArrayBufferNow(buf);
|
||||
resizeQuad32EmulationBuffer(newSize >> 2);
|
||||
}else {
|
||||
int cnt = quad32EmulationBufferSize;
|
||||
if(cnt < vertexCount) {
|
||||
int newSize = quad32EmulationBufferSize = (vertexCount & 0xFFFFC000) + 0x8000;
|
||||
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
|
||||
EaglercraftGPU.bindVAOGLElementArrayBufferNow(buf);
|
||||
resizeQuad32EmulationBuffer(newSize >> 2);
|
||||
}else if(bind) {
|
||||
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
|
||||
EaglercraftGPU.bindVAOGLElementArrayBuffer(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -508,9 +760,19 @@ public class EaglercraftGPU {
|
||||
p.drawElements(GL_TRIANGLES, mesh.indexCount, GL_UNSIGNED_SHORT, 0);
|
||||
}
|
||||
|
||||
static int glesVers = -1;
|
||||
static boolean hasFramebufferHDR16FSupport = false;
|
||||
static boolean hasFramebufferHDR32FSupport = false;
|
||||
static boolean hasLinearHDR16FSupport = false;
|
||||
static boolean hasLinearHDR32FSupport = false;
|
||||
static boolean fboRenderMipmapCapable = false;
|
||||
static boolean vertexArrayCapable = false;
|
||||
static boolean instancingCapable = false;
|
||||
static boolean texStorageCapable = false;
|
||||
static boolean textureLODCapable = false;
|
||||
static boolean shader5Capable = false;
|
||||
static boolean npotCapable = false;
|
||||
static int uniformBufferOffsetAlignment = -1;
|
||||
|
||||
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);
|
||||
@ -525,19 +787,24 @@ public class EaglercraftGPU {
|
||||
int internalFormat;
|
||||
switch(format) {
|
||||
case GL_RED:
|
||||
internalFormat = 0x822D; // GL_R16F
|
||||
if(glesVers == 200) {
|
||||
format = GL_LUMINANCE;
|
||||
internalFormat = GL_LUMINANCE;
|
||||
}else {
|
||||
internalFormat = glesVers == 200 ? GL_LUMINANCE : 0x822D; // GL_R16F
|
||||
}
|
||||
break;
|
||||
case 0x8227: // GL_RG
|
||||
internalFormat = 0x822F; // GL_RG16F
|
||||
internalFormat = glesVers == 200 ? 0x8227 : 0x822F; // GL_RG16F
|
||||
case GL_RGB:
|
||||
throw new UnsupportedOperationException("GL_RGB16F isn't supported specifically in WebGL 2.0 for some goddamn reason");
|
||||
case GL_RGBA:
|
||||
internalFormat = 0x881A; // GL_RGBA16F
|
||||
internalFormat = glesVers == 200 ? GL_RGBA : 0x881A; // GL_RGBA16F
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown format: " + format);
|
||||
}
|
||||
_wglTexImage2Du16(target, level, internalFormat, w, h, 0, format, 0x140B, pixelData);
|
||||
_wglTexImage2Du16(target, level, internalFormat, w, h, 0, format, glesVers == 200 ? 0x8D61 : 0x140B, pixelData);
|
||||
}else {
|
||||
if(allow32bitFallback) {
|
||||
if(hasFramebufferHDR32FSupport) {
|
||||
@ -567,7 +834,7 @@ public class EaglercraftGPU {
|
||||
internalFormat = 0x822E; // GL_R32F
|
||||
break;
|
||||
case 0x8227: // GL_RG
|
||||
internalFormat = 0x822F; // GL_RG32F
|
||||
internalFormat = 0x8230; // GL_RG32F
|
||||
case GL_RGB:
|
||||
throw new UnsupportedOperationException("GL_RGB32F isn't supported specifically in WebGL 2.0 for some goddamn reason");
|
||||
case GL_RGBA:
|
||||
@ -594,19 +861,38 @@ public class EaglercraftGPU {
|
||||
EaglercraftGPU.glGetString(7936);
|
||||
EaglercraftGPU.glGetString(7937);
|
||||
EaglercraftGPU.glGetString(7938);
|
||||
glesVers = PlatformOpenGL.checkOpenGLESVersion();
|
||||
vertexArrayCapable = PlatformOpenGL.checkVAOCapable();
|
||||
emulatedVAOs = !vertexArrayCapable;
|
||||
fboRenderMipmapCapable = PlatformOpenGL.checkFBORenderMipmapCapable();
|
||||
instancingCapable = PlatformOpenGL.checkInstancingCapable();
|
||||
texStorageCapable = PlatformOpenGL.checkTexStorageCapable();
|
||||
textureLODCapable = PlatformOpenGL.checkTextureLODCapable();
|
||||
shader5Capable = PlatformOpenGL.checkOESGPUShader5Capable() || PlatformOpenGL.checkEXTGPUShader5Capable();
|
||||
npotCapable = PlatformOpenGL.checkNPOTCapable();
|
||||
uniformBufferOffsetAlignment = glesVers >= 300 ? _wglGetInteger(0x8A34) : -1;
|
||||
if(!npotCapable) {
|
||||
logger.warn("NPOT texture support detected as false, texture wrapping must be set to GL_CLAMP_TO_EDGE if the texture's width or height is not a power of 2");
|
||||
}
|
||||
hasFramebufferHDR16FSupport = PlatformOpenGL.checkHDRFramebufferSupport(16);
|
||||
if(hasFramebufferHDR16FSupport) {
|
||||
logger.info("16-bit HDR render target support: true");
|
||||
}else {
|
||||
logger.error("16-bit HDR render target support: false");
|
||||
}
|
||||
hasLinearHDR16FSupport = PlatformOpenGL.checkLinearHDRFilteringSupport(16);
|
||||
if(hasLinearHDR16FSupport) {
|
||||
logger.info("16-bit HDR linear filter support: true");
|
||||
}else {
|
||||
logger.error("16-bit HDR linear filter support: false");
|
||||
}
|
||||
hasFramebufferHDR32FSupport = PlatformOpenGL.checkHDRFramebufferSupport(32);
|
||||
if(hasFramebufferHDR32FSupport) {
|
||||
logger.info("32-bit HDR render target support: true");
|
||||
}else {
|
||||
logger.error("32-bit HDR render target support: false");
|
||||
}
|
||||
hasLinearHDR32FSupport = PlatformOpenGL.checkLinearHDR32FSupport();
|
||||
hasLinearHDR32FSupport = PlatformOpenGL.checkLinearHDRFilteringSupport(32);
|
||||
if(hasLinearHDR32FSupport) {
|
||||
logger.info("32-bit HDR linear filter support: true");
|
||||
}else {
|
||||
@ -615,16 +901,86 @@ public class EaglercraftGPU {
|
||||
if(!checkHasHDRFramebufferSupportWithFilter()) {
|
||||
logger.error("No HDR render target support was detected! Shaders will be disabled.");
|
||||
}
|
||||
if(emulatedVAOs) {
|
||||
logger.info("Note: Could not unlock VAOs via OpenGL extensions, emulating them instead");
|
||||
}
|
||||
if(!instancingCapable) {
|
||||
logger.info("Note: Could not unlock instancing via OpenGL extensions, using slow vanilla font and particle rendering");
|
||||
}
|
||||
emulatedVAOState = emulatedVAOs ? new SoftGLBufferState() : null;
|
||||
PlatformOpenGL.enterVAOEmulationHook();
|
||||
GLSLHeader.init();
|
||||
DrawUtils.init();
|
||||
SpriteLevelMixer.initialize();
|
||||
InstancedFontRenderer.initialize();
|
||||
InstancedParticleRenderer.initialize();
|
||||
if(instancingCapable) {
|
||||
InstancedFontRenderer.initialize();
|
||||
InstancedParticleRenderer.initialize();
|
||||
}
|
||||
EffectPipelineFXAA.initialize();
|
||||
TextureCopyUtil.initialize();
|
||||
DrawUtils.vshLocal.free();
|
||||
DrawUtils.vshLocal = null;
|
||||
}
|
||||
|
||||
public static final void destroyCache() {
|
||||
stringCache.clear();
|
||||
mapTexturesGL.clear();
|
||||
mapQueriesGL.clear();
|
||||
mapDisplayListsGL.clear();
|
||||
emulatedVAOs = false;
|
||||
emulatedVAOState = null;
|
||||
glesVers = -1;
|
||||
fboRenderMipmapCapable = false;
|
||||
vertexArrayCapable = false;
|
||||
instancingCapable = false;
|
||||
hasFramebufferHDR16FSupport = false;
|
||||
hasFramebufferHDR32FSupport = false;
|
||||
hasLinearHDR32FSupport = false;
|
||||
GLSLHeader.destroy();
|
||||
DrawUtils.destroy();
|
||||
SpriteLevelMixer.destroy();
|
||||
InstancedFontRenderer.destroy();
|
||||
InstancedParticleRenderer.destroy();
|
||||
EffectPipelineFXAA.destroy();
|
||||
TextureCopyUtil.destroy();
|
||||
}
|
||||
|
||||
public static final int checkOpenGLESVersion() {
|
||||
return glesVers;
|
||||
}
|
||||
|
||||
public static final boolean checkFBORenderMipmapCapable() {
|
||||
return fboRenderMipmapCapable;
|
||||
}
|
||||
|
||||
public static final boolean checkVAOCapable() {
|
||||
return vertexArrayCapable;
|
||||
}
|
||||
|
||||
public static final boolean checkInstancingCapable() {
|
||||
return instancingCapable;
|
||||
}
|
||||
|
||||
public static final boolean checkTexStorageCapable() {
|
||||
return texStorageCapable;
|
||||
}
|
||||
|
||||
public static final boolean checkTextureLODCapable() {
|
||||
return textureLODCapable;
|
||||
}
|
||||
|
||||
public static final boolean checkShader5Capable() {
|
||||
return shader5Capable;
|
||||
}
|
||||
|
||||
public static final boolean checkNPOTCapable() {
|
||||
return npotCapable;
|
||||
}
|
||||
|
||||
public static final int getUniformBufferOffsetAlignment() {
|
||||
return uniformBufferOffsetAlignment;
|
||||
}
|
||||
|
||||
public static final boolean checkHDRFramebufferSupport(int bits) {
|
||||
switch(bits) {
|
||||
case 16:
|
||||
@ -636,15 +992,28 @@ public class EaglercraftGPU {
|
||||
}
|
||||
}
|
||||
|
||||
public static final boolean checkLinearHDRFilteringSupport(int bits) {
|
||||
switch(bits) {
|
||||
case 16:
|
||||
return hasLinearHDR16FSupport;
|
||||
case 32:
|
||||
return hasLinearHDR32FSupport;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static final boolean checkHasHDRFramebufferSupport() {
|
||||
return hasFramebufferHDR16FSupport || hasFramebufferHDR32FSupport;
|
||||
}
|
||||
|
||||
public static final boolean checkHasHDRFramebufferSupportWithFilter() {
|
||||
return hasFramebufferHDR16FSupport || (hasFramebufferHDR32FSupport && hasLinearHDR32FSupport);
|
||||
return (hasFramebufferHDR16FSupport && hasLinearHDR16FSupport) || (hasFramebufferHDR32FSupport && hasLinearHDR32FSupport);
|
||||
}
|
||||
|
||||
//legacy
|
||||
public static final boolean checkLinearHDR32FSupport() {
|
||||
return hasLinearHDR32FSupport;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants;
|
||||
|
||||
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
|
||||
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
|
||||
@ -35,11 +34,13 @@ public class EffectPipelineFXAA {
|
||||
private static final Logger logger = LogManager.getLogger("EffectPipelineFXAA");
|
||||
|
||||
public static final String fragmentShaderPath = "/assets/eagler/glsl/post_fxaa.fsh";
|
||||
public static final String fragmentShaderPrecision = "precision lowp int;\nprecision mediump float;\nprecision mediump sampler2D;\n";
|
||||
|
||||
private static final int _GL_FRAMEBUFFER = 0x8D40;
|
||||
private static final int _GL_RENDERBUFFER = 0x8D41;
|
||||
private static final int _GL_COLOR_ATTACHMENT0 = 0x8CE0;
|
||||
private static final int _GL_DEPTH_ATTACHMENT = 0x8D00;
|
||||
private static final int _GL_DEPTH_COMPONENT16 = 0x81A5;
|
||||
private static final int _GL_DEPTH_COMPONENT32F = 0x8CAC;
|
||||
|
||||
private static IProgramGL shaderProgram = null;
|
||||
@ -53,14 +54,11 @@ public class EffectPipelineFXAA {
|
||||
private static int currentHeight = -1;
|
||||
|
||||
static void initialize() {
|
||||
String fragmentSource = EagRuntime.getResourceString(fragmentShaderPath);
|
||||
if(fragmentSource == null) {
|
||||
throw new RuntimeException("EffectPipelineFXAA shader \"" + fragmentShaderPath + "\" is missing!");
|
||||
}
|
||||
String fragmentSource = EagRuntime.getRequiredResourceString(fragmentShaderPath);
|
||||
|
||||
IShaderGL frag = _wglCreateShader(GL_FRAGMENT_SHADER);
|
||||
|
||||
_wglShaderSource(frag, FixedFunctionConstants.VERSION + "\n" + fragmentSource);
|
||||
_wglShaderSource(frag, GLSLHeader.getFragmentHeaderCompat(fragmentSource, fragmentShaderPrecision));
|
||||
_wglCompileShader(frag);
|
||||
|
||||
if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
@ -80,6 +78,10 @@ public class EffectPipelineFXAA {
|
||||
_wglAttachShader(shaderProgram, DrawUtils.vshLocal);
|
||||
_wglAttachShader(shaderProgram, frag);
|
||||
|
||||
if(EaglercraftGPU.checkOpenGLESVersion() == 200) {
|
||||
VSHInputLayoutParser.applyLayout(shaderProgram, DrawUtils.vshLocalLayout);
|
||||
}
|
||||
|
||||
_wglLinkProgram(shaderProgram);
|
||||
|
||||
_wglDetachShader(shaderProgram, DrawUtils.vshLocal);
|
||||
@ -130,10 +132,10 @@ public class EffectPipelineFXAA {
|
||||
currentHeight = height;
|
||||
|
||||
GlStateManager.bindTexture(framebufferColor);
|
||||
_wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null);
|
||||
EaglercraftGPU.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null);
|
||||
|
||||
_wglBindRenderbuffer(_GL_RENDERBUFFER, framebufferDepth);
|
||||
_wglRenderbufferStorage(_GL_RENDERBUFFER, _GL_DEPTH_COMPONENT32F, width, height);
|
||||
_wglRenderbufferStorage(_GL_RENDERBUFFER, EaglercraftGPU.checkOpenGLESVersion() == 200 ? _GL_DEPTH_COMPONENT16 : _GL_DEPTH_COMPONENT32F, width, height);
|
||||
}
|
||||
|
||||
_wglBindFramebuffer(_GL_FRAMEBUFFER, framebuffer);
|
||||
@ -155,4 +157,24 @@ public class EffectPipelineFXAA {
|
||||
DrawUtils.drawStandardQuad2D();
|
||||
}
|
||||
|
||||
public static void destroy() {
|
||||
if(shaderProgram != null) {
|
||||
_wglDeleteProgram(shaderProgram);
|
||||
shaderProgram = null;
|
||||
}
|
||||
u_screenSize2f = null;
|
||||
if(framebuffer != null) {
|
||||
_wglDeleteFramebuffer(framebuffer);
|
||||
framebuffer = null;
|
||||
}
|
||||
if(framebufferColor != -1) {
|
||||
GlStateManager.deleteTexture(framebufferColor);
|
||||
framebufferColor = -2;
|
||||
}
|
||||
if(framebufferDepth != null) {
|
||||
_wglDeleteRenderbuffer(framebufferDepth);
|
||||
framebufferDepth = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -98,33 +98,33 @@ public class FixedFunctionPipeline {
|
||||
}
|
||||
|
||||
EaglercraftGPU.bindGLBufferArray(list.vertexArray);
|
||||
EaglercraftGPU.bindGLArrayBuffer(list.vertexBuffer);
|
||||
EaglercraftGPU.bindVAOGLArrayBuffer(list.vertexBuffer);
|
||||
|
||||
_wglEnableVertexAttribArray(0);
|
||||
_wglVertexAttribPointer(0, VertexFormat.COMPONENT_POSITION_SIZE,
|
||||
EaglercraftGPU.enableVertexAttribArray(0);
|
||||
EaglercraftGPU.vertexAttribPointer(0, VertexFormat.COMPONENT_POSITION_SIZE,
|
||||
VertexFormat.COMPONENT_POSITION_FORMAT, false, self.attribStride, 0);
|
||||
|
||||
if(self.attribTextureIndex != -1) {
|
||||
_wglEnableVertexAttribArray(self.attribTextureIndex);
|
||||
_wglVertexAttribPointer(self.attribTextureIndex, VertexFormat.COMPONENT_TEX_SIZE,
|
||||
EaglercraftGPU.enableVertexAttribArray(self.attribTextureIndex);
|
||||
EaglercraftGPU.vertexAttribPointer(self.attribTextureIndex, VertexFormat.COMPONENT_TEX_SIZE,
|
||||
VertexFormat.COMPONENT_TEX_FORMAT, false, self.attribStride, self.attribTextureOffset);
|
||||
}
|
||||
|
||||
if(self.attribColorIndex != -1) {
|
||||
_wglEnableVertexAttribArray(self.attribColorIndex);
|
||||
_wglVertexAttribPointer(self.attribColorIndex, VertexFormat.COMPONENT_COLOR_SIZE,
|
||||
EaglercraftGPU.enableVertexAttribArray(self.attribColorIndex);
|
||||
EaglercraftGPU.vertexAttribPointer(self.attribColorIndex, VertexFormat.COMPONENT_COLOR_SIZE,
|
||||
VertexFormat.COMPONENT_COLOR_FORMAT, true, self.attribStride, self.attribColorOffset);
|
||||
}
|
||||
|
||||
if(self.attribNormalIndex != -1) {
|
||||
_wglEnableVertexAttribArray(self.attribNormalIndex);
|
||||
_wglVertexAttribPointer(self.attribNormalIndex, VertexFormat.COMPONENT_NORMAL_SIZE,
|
||||
EaglercraftGPU.enableVertexAttribArray(self.attribNormalIndex);
|
||||
EaglercraftGPU.vertexAttribPointer(self.attribNormalIndex, VertexFormat.COMPONENT_NORMAL_SIZE,
|
||||
VertexFormat.COMPONENT_NORMAL_FORMAT, true, self.attribStride, self.attribNormalOffset);
|
||||
}
|
||||
|
||||
if(self.attribLightmapIndex != -1) {
|
||||
_wglEnableVertexAttribArray(self.attribLightmapIndex);
|
||||
_wglVertexAttribPointer(self.attribLightmapIndex, VertexFormat.COMPONENT_LIGHTMAP_SIZE,
|
||||
EaglercraftGPU.enableVertexAttribArray(self.attribLightmapIndex);
|
||||
EaglercraftGPU.vertexAttribPointer(self.attribLightmapIndex, VertexFormat.COMPONENT_LIGHTMAP_SIZE,
|
||||
VertexFormat.COMPONENT_LIGHTMAP_FORMAT, false, self.attribStride, self.attribLightmapOffset);
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@ public class FixedFunctionPipeline {
|
||||
|
||||
void drawArrays(int mode, int offset, int count) {
|
||||
EaglercraftGPU.bindGLShaderProgram(shaderProgram);
|
||||
PlatformOpenGL._wglDrawArrays(mode, offset, count);
|
||||
EaglercraftGPU.doDrawArrays(mode, offset, count);
|
||||
}
|
||||
|
||||
void drawDirectArrays(int mode, int offset, int count) {
|
||||
@ -160,7 +160,7 @@ public class FixedFunctionPipeline {
|
||||
}else {
|
||||
EaglercraftGPU.attachQuad32EmulationBuffer(count, false);
|
||||
}
|
||||
PlatformOpenGL._wglDrawElements(GL_TRIANGLES, count + (count >> 1),
|
||||
EaglercraftGPU.doDrawElements(GL_TRIANGLES, count + (count >> 1),
|
||||
GL_UNSIGNED_INT, 0);
|
||||
}else {
|
||||
if(!sb.bindQuad16) {
|
||||
@ -170,17 +170,17 @@ public class FixedFunctionPipeline {
|
||||
}else {
|
||||
EaglercraftGPU.attachQuad16EmulationBuffer(count, false);
|
||||
}
|
||||
PlatformOpenGL._wglDrawElements(GL_TRIANGLES, count + (count >> 1),
|
||||
EaglercraftGPU.doDrawElements(GL_TRIANGLES, count + (count >> 1),
|
||||
GL_UNSIGNED_SHORT, 0);
|
||||
}
|
||||
}else {
|
||||
PlatformOpenGL._wglDrawArrays(mode, offset, count);
|
||||
EaglercraftGPU.doDrawArrays(mode, offset, count);
|
||||
}
|
||||
}
|
||||
|
||||
void drawElements(int mode, int count, int type, int offset) {
|
||||
EaglercraftGPU.bindGLShaderProgram(shaderProgram);
|
||||
PlatformOpenGL._wglDrawElements(mode, count, type, offset);
|
||||
EaglercraftGPU.doDrawElements(mode, count, type, offset);
|
||||
}
|
||||
|
||||
private static IExtPipelineCompiler extensionProvider;
|
||||
@ -192,7 +192,7 @@ public class FixedFunctionPipeline {
|
||||
|
||||
private static final FixedFunctionPipeline[] pipelineStateCache = new FixedFunctionPipeline[fixedFunctionStatesBits + 1];
|
||||
private static final FixedFunctionPipeline[][] pipelineExtStateCache = new FixedFunctionPipeline[fixedFunctionStatesBits + 1][];
|
||||
private static final List<FixedFunctionPipeline> pipelineListTracker = new ArrayList(1024);
|
||||
private static final List<FixedFunctionPipeline> pipelineListTracker = new ArrayList<>(1024);
|
||||
|
||||
private static String shaderSourceCacheVSH = null;
|
||||
private static String shaderSourceCacheFSH = null;
|
||||
@ -232,22 +232,16 @@ public class FixedFunctionPipeline {
|
||||
fshSource = extSource[1];
|
||||
}else {
|
||||
if(shaderSourceCacheVSH == null) {
|
||||
shaderSourceCacheVSH = EagRuntime.getResourceString(FILENAME_VSH);
|
||||
if(shaderSourceCacheVSH == null) {
|
||||
throw new RuntimeException("Could not load: " + FILENAME_VSH);
|
||||
}
|
||||
shaderSourceCacheVSH = EagRuntime.getRequiredResourceString(FILENAME_VSH);
|
||||
}
|
||||
vshSource = shaderSourceCacheVSH;
|
||||
if(shaderSourceCacheFSH == null) {
|
||||
shaderSourceCacheFSH = EagRuntime.getResourceString(FILENAME_FSH);
|
||||
if(shaderSourceCacheFSH == null) {
|
||||
throw new RuntimeException("Could not load: " + FILENAME_FSH);
|
||||
}
|
||||
shaderSourceCacheFSH = EagRuntime.getRequiredResourceString(FILENAME_FSH);
|
||||
}
|
||||
fshSource = shaderSourceCacheFSH;
|
||||
}
|
||||
|
||||
StringBuilder macros = new StringBuilder(VERSION + "\n");
|
||||
StringBuilder macros = new StringBuilder();
|
||||
if((coreBits & STATE_HAS_ATTRIB_TEXTURE) != 0) {
|
||||
macros.append("#define " + MACRO_ATTRIB_TEXTURE + "\n");
|
||||
}
|
||||
@ -291,7 +285,8 @@ public class FixedFunctionPipeline {
|
||||
|
||||
IShaderGL vsh = _wglCreateShader(GL_VERTEX_SHADER);
|
||||
|
||||
_wglShaderSource(vsh, macros.toString() + vshSource);
|
||||
String macrosStr = macros.toString();
|
||||
_wglShaderSource(vsh, GLSLHeader.getVertexHeaderCompat(vshSource, macrosStr));
|
||||
_wglCompileShader(vsh);
|
||||
|
||||
if(_wglGetShaderi(vsh, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
@ -309,7 +304,7 @@ public class FixedFunctionPipeline {
|
||||
|
||||
IShaderGL fsh = _wglCreateShader(GL_FRAGMENT_SHADER);
|
||||
|
||||
_wglShaderSource(fsh, macros.toString() + fshSource);
|
||||
_wglShaderSource(fsh, GLSLHeader.getFragmentHeaderCompat(fshSource, macrosStr));
|
||||
_wglCompileShader(fsh);
|
||||
|
||||
if(_wglGetShaderi(fsh, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
@ -581,45 +576,45 @@ public class FixedFunctionPipeline {
|
||||
streamBuffer = new StreamBuffer(FixedFunctionShader.initialSize, FixedFunctionShader.initialCount,
|
||||
FixedFunctionShader.maxCount, (vertexArray, vertexBuffer) -> {
|
||||
EaglercraftGPU.bindGLBufferArray(vertexArray);
|
||||
EaglercraftGPU.bindGLArrayBuffer(vertexBuffer);
|
||||
EaglercraftGPU.bindVAOGLArrayBuffer(vertexBuffer);
|
||||
|
||||
_wglEnableVertexAttribArray(0);
|
||||
_wglVertexAttribPointer(0, VertexFormat.COMPONENT_POSITION_SIZE,
|
||||
EaglercraftGPU.enableVertexAttribArray(0);
|
||||
EaglercraftGPU.vertexAttribPointer(0, VertexFormat.COMPONENT_POSITION_SIZE,
|
||||
VertexFormat.COMPONENT_POSITION_FORMAT, false, attribStride, 0);
|
||||
|
||||
if(attribTextureIndex != -1) {
|
||||
_wglEnableVertexAttribArray(attribTextureIndex);
|
||||
_wglVertexAttribPointer(attribTextureIndex, VertexFormat.COMPONENT_TEX_SIZE,
|
||||
EaglercraftGPU.enableVertexAttribArray(attribTextureIndex);
|
||||
EaglercraftGPU.vertexAttribPointer(attribTextureIndex, VertexFormat.COMPONENT_TEX_SIZE,
|
||||
VertexFormat.COMPONENT_TEX_FORMAT, false, attribStride, attribTextureOffset);
|
||||
}
|
||||
|
||||
if(attribColorIndex != -1) {
|
||||
_wglEnableVertexAttribArray(attribColorIndex);
|
||||
_wglVertexAttribPointer(attribColorIndex, VertexFormat.COMPONENT_COLOR_SIZE,
|
||||
EaglercraftGPU.enableVertexAttribArray(attribColorIndex);
|
||||
EaglercraftGPU.vertexAttribPointer(attribColorIndex, VertexFormat.COMPONENT_COLOR_SIZE,
|
||||
VertexFormat.COMPONENT_COLOR_FORMAT, true, attribStride, attribColorOffset);
|
||||
}
|
||||
|
||||
if(attribNormalIndex != -1) {
|
||||
_wglEnableVertexAttribArray(attribNormalIndex);
|
||||
_wglVertexAttribPointer(attribNormalIndex, VertexFormat.COMPONENT_NORMAL_SIZE,
|
||||
EaglercraftGPU.enableVertexAttribArray(attribNormalIndex);
|
||||
EaglercraftGPU.vertexAttribPointer(attribNormalIndex, VertexFormat.COMPONENT_NORMAL_SIZE,
|
||||
VertexFormat.COMPONENT_NORMAL_FORMAT, true, attribStride, attribNormalOffset);
|
||||
}
|
||||
|
||||
if(attribLightmapIndex != -1) {
|
||||
_wglEnableVertexAttribArray(attribLightmapIndex);
|
||||
_wglVertexAttribPointer(attribLightmapIndex, VertexFormat.COMPONENT_LIGHTMAP_SIZE,
|
||||
EaglercraftGPU.enableVertexAttribArray(attribLightmapIndex);
|
||||
EaglercraftGPU.vertexAttribPointer(attribLightmapIndex, VertexFormat.COMPONENT_LIGHTMAP_SIZE,
|
||||
VertexFormat.COMPONENT_LIGHTMAP_FORMAT, false, attribStride, attribLightmapOffset);
|
||||
}
|
||||
});
|
||||
|
||||
stateEnableTexture2D = (bits & STATE_ENABLE_TEXTURE2D) == STATE_ENABLE_TEXTURE2D;
|
||||
stateEnableLightmap = (bits & STATE_ENABLE_LIGHTMAP) == STATE_ENABLE_LIGHTMAP;
|
||||
stateEnableAlphaTest = (bits & STATE_ENABLE_ALPHA_TEST) == STATE_ENABLE_ALPHA_TEST;
|
||||
stateEnableMCLighting = (bits & STATE_ENABLE_MC_LIGHTING) == STATE_ENABLE_MC_LIGHTING;
|
||||
stateEnableEndPortal = (bits & STATE_ENABLE_END_PORTAL) == STATE_ENABLE_END_PORTAL;
|
||||
stateEnableAnisotropicFix = (bits & STATE_ENABLE_ANISOTROPIC_FIX) == STATE_ENABLE_ANISOTROPIC_FIX;
|
||||
stateEnableFog = (bits & STATE_ENABLE_FOG) == STATE_ENABLE_FOG;
|
||||
stateEnableBlendAdd = (bits & STATE_ENABLE_BLEND_ADD) == STATE_ENABLE_BLEND_ADD;
|
||||
stateEnableTexture2D = (bits & STATE_ENABLE_TEXTURE2D) != 0;
|
||||
stateEnableLightmap = (bits & STATE_ENABLE_LIGHTMAP) != 0;
|
||||
stateEnableAlphaTest = (bits & STATE_ENABLE_ALPHA_TEST) != 0;
|
||||
stateEnableMCLighting = (bits & STATE_ENABLE_MC_LIGHTING) != 0;
|
||||
stateEnableEndPortal = (bits & STATE_ENABLE_END_PORTAL) != 0;
|
||||
stateEnableAnisotropicFix = (bits & STATE_ENABLE_ANISOTROPIC_FIX) != 0;
|
||||
stateEnableFog = (bits & STATE_ENABLE_FOG) != 0;
|
||||
stateEnableBlendAdd = (bits & STATE_ENABLE_BLEND_ADD) != 0;
|
||||
|
||||
for(int i = 0; i < stateLightsVectors.length; ++i) {
|
||||
stateLightsVectors[i] = new Vector4f(-999.0f, -999.0f, -999.0f, 0.0f);
|
||||
@ -1068,7 +1063,6 @@ public class FixedFunctionPipeline {
|
||||
}
|
||||
|
||||
static void optimize() {
|
||||
FixedFunctionPipeline pp;
|
||||
for(int i = 0, l = pipelineListTracker.size(); i < l; ++i) {
|
||||
pipelineListTracker.get(i).streamBuffer.optimize();
|
||||
}
|
||||
|
@ -44,7 +44,6 @@ public class FixedFunctionShader {
|
||||
|
||||
public class FixedFunctionConstants {
|
||||
|
||||
public static final String VERSION = "#version 300 es";
|
||||
public static final String FILENAME_VSH = "/assets/eagler/glsl/core.vsh";
|
||||
public static final String FILENAME_FSH = "/assets/eagler/glsl/core.fsh";
|
||||
|
||||
|
@ -0,0 +1,99 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.opengl;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import 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 GLSLHeader {
|
||||
|
||||
public static final String GLES2_COMPAT_FILE_NAME = "/assets/eagler/glsl/gles2_compat.glsl";
|
||||
|
||||
private static String header = null;
|
||||
private static String gles2CompatFile = null;
|
||||
|
||||
static void init() {
|
||||
gles2CompatFile = EagRuntime.getRequiredResourceString(GLES2_COMPAT_FILE_NAME);
|
||||
int glesVersion = EaglercraftGPU.checkOpenGLESVersion();
|
||||
StringBuilder headerBuilder;
|
||||
if(glesVersion >= 310) {
|
||||
headerBuilder = new StringBuilder("#version 310 es");
|
||||
boolean oes5 = PlatformOpenGL.checkOESGPUShader5Capable();
|
||||
boolean ext5 = !oes5 && PlatformOpenGL.checkEXTGPUShader5Capable();
|
||||
if(oes5) {
|
||||
headerBuilder.append("\n#extension GL_OES_gpu_shader5 : enable");
|
||||
}else if(ext5) {
|
||||
headerBuilder.append("\n#extension GL_EXT_gpu_shader5 : enable");
|
||||
}
|
||||
headerBuilder.append("\n#define EAGLER_IS_GLES_310");
|
||||
headerBuilder.append("\n#define EAGLER_HAS_GLES_310");
|
||||
headerBuilder.append("\n#define EAGLER_HAS_GLES_300");
|
||||
headerBuilder.append("\n#define EAGLER_HAS_GLES_200");
|
||||
if(oes5 || ext5) {
|
||||
headerBuilder.append("\n#define EAGLER_HAS_GLES_310_SHADER_5");
|
||||
}
|
||||
}else if(glesVersion == 300) {
|
||||
headerBuilder = new StringBuilder("#version 300 es");
|
||||
headerBuilder.append("\n#define EAGLER_IS_GLES_300");
|
||||
headerBuilder.append("\n#define EAGLER_HAS_GLES_300");
|
||||
headerBuilder.append("\n#define EAGLER_HAS_GLES_200");
|
||||
}else if(glesVersion == 200) {
|
||||
boolean texLOD = PlatformOpenGL.checkTextureLODCapable();
|
||||
headerBuilder = new StringBuilder("#version 100");
|
||||
if(texLOD) {
|
||||
headerBuilder.append("\n#extension GL_EXT_shader_texture_lod : enable");
|
||||
}
|
||||
headerBuilder.append("\n#define EAGLER_HAS_GLES_200");
|
||||
headerBuilder.append("\n#define EAGLER_IS_GLES_200");
|
||||
if(texLOD) {
|
||||
headerBuilder.append("\n#define EAGLER_HAS_GLES_200_SHADER_TEXTURE_LOD");
|
||||
}
|
||||
}else {
|
||||
throw new IllegalStateException("Unsupported OpenGL ES version: " + glesVersion);
|
||||
}
|
||||
header = headerBuilder.append('\n').toString();
|
||||
}
|
||||
|
||||
static void destroy() {
|
||||
header = null;
|
||||
}
|
||||
|
||||
public static String getHeader() {
|
||||
if(header == null) throw new IllegalStateException();
|
||||
return header;
|
||||
}
|
||||
|
||||
public static String getVertexHeader(String shaderSrc) {
|
||||
if(header == null) throw new IllegalStateException();
|
||||
return header + "#define EAGLER_IS_VERTEX_SHADER\n" + shaderSrc;
|
||||
}
|
||||
|
||||
public static String getFragmentHeader(String shaderSrc) {
|
||||
if(header == null) throw new IllegalStateException();
|
||||
return header + "#define EAGLER_IS_FRAGMENT_SHADER\n" + shaderSrc;
|
||||
}
|
||||
|
||||
public static String getVertexHeaderCompat(String shaderSrc, String precisions) {
|
||||
if(header == null || gles2CompatFile == null) throw new IllegalStateException();
|
||||
return header + "#define EAGLER_IS_VERTEX_SHADER\n" + (precisions == null ? "" : precisions + "\n") + gles2CompatFile + "\n" + shaderSrc;
|
||||
}
|
||||
|
||||
public static String getFragmentHeaderCompat(String shaderSrc, String precisions) {
|
||||
if(header == null || gles2CompatFile == null) throw new IllegalStateException();
|
||||
return header + "#define EAGLER_IS_FRAGMENT_SHADER\n"+ (precisions == null ? "" : precisions + "\n") + gles2CompatFile + "\n" + shaderSrc;
|
||||
}
|
||||
|
||||
}
|
@ -5,10 +5,13 @@ import net.lax1dude.eaglercraft.v1_8.internal.IRenderbufferGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
|
||||
|
||||
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
|
||||
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2023 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
|
||||
@ -40,10 +43,20 @@ public class GameOverlayFramebuffer {
|
||||
|
||||
private int framebufferColor = -1;
|
||||
|
||||
public void beginRender(int width, int height) {
|
||||
private final boolean enableDepth;
|
||||
|
||||
public GameOverlayFramebuffer() {
|
||||
this(true);
|
||||
}
|
||||
|
||||
public GameOverlayFramebuffer(boolean enableDepth) {
|
||||
this.enableDepth = enableDepth;
|
||||
}
|
||||
|
||||
public boolean beginRender(int width, int height) {
|
||||
if(framebuffer == null) {
|
||||
framebuffer = _wglCreateFramebuffer();
|
||||
depthBuffer = _wglCreateRenderbuffer();
|
||||
depthBuffer = enableDepth ? _wglCreateRenderbuffer() : null;
|
||||
framebufferColor = GlStateManager.generateTexture();
|
||||
_wglBindFramebuffer(_GL_FRAMEBUFFER, framebuffer);
|
||||
GlStateManager.bindTexture(framebufferColor);
|
||||
@ -52,29 +65,35 @@ public class GameOverlayFramebuffer {
|
||||
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
_wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(framebufferColor), 0);
|
||||
_wglBindRenderbuffer(_GL_RENDERBUFFER, depthBuffer);
|
||||
_wglFramebufferRenderbuffer(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, _GL_RENDERBUFFER, depthBuffer);
|
||||
if(enableDepth) {
|
||||
_wglBindRenderbuffer(_GL_RENDERBUFFER, depthBuffer);
|
||||
_wglFramebufferRenderbuffer(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, _GL_RENDERBUFFER, depthBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if(currentWidth != width || currentHeight != height) {
|
||||
boolean resized = currentWidth != width || currentHeight != height;
|
||||
if(resized) {
|
||||
currentWidth = width;
|
||||
currentHeight = height;
|
||||
GlStateManager.bindTexture(framebufferColor);
|
||||
_wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null);
|
||||
_wglBindRenderbuffer(_GL_RENDERBUFFER, depthBuffer);
|
||||
_wglRenderbufferStorage(_GL_RENDERBUFFER, _GL_DEPTH_COMPONENT16, width, height);
|
||||
EaglercraftGPU.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null);
|
||||
if(enableDepth) {
|
||||
_wglBindRenderbuffer(_GL_RENDERBUFFER, depthBuffer);
|
||||
_wglRenderbufferStorage(_GL_RENDERBUFFER, _GL_DEPTH_COMPONENT16, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
_wglBindFramebuffer(_GL_FRAMEBUFFER, framebuffer);
|
||||
return resized;
|
||||
}
|
||||
|
||||
public void endRender() {
|
||||
_wglBindFramebuffer(_GL_FRAMEBUFFER, null);
|
||||
age = System.currentTimeMillis();
|
||||
age = EagRuntime.steadyTimeMillis();
|
||||
}
|
||||
|
||||
public long getAge() {
|
||||
return age == -1l ? -1l : (System.currentTimeMillis() - age);
|
||||
return age == -1l ? -1l : (EagRuntime.steadyTimeMillis() - age);
|
||||
}
|
||||
|
||||
public int getTexture() {
|
||||
@ -84,7 +103,9 @@ public class GameOverlayFramebuffer {
|
||||
public void destroy() {
|
||||
if(framebuffer != null) {
|
||||
_wglDeleteFramebuffer(framebuffer);
|
||||
_wglDeleteRenderbuffer(depthBuffer);
|
||||
if(enableDepth) {
|
||||
_wglDeleteRenderbuffer(depthBuffer);
|
||||
}
|
||||
GlStateManager.deleteTexture(framebufferColor);
|
||||
framebuffer = null;
|
||||
depthBuffer = null;
|
||||
|
@ -30,10 +30,12 @@ public class GlStateManager {
|
||||
static final Logger logger = LogManager.getLogger("GlStateManager");
|
||||
|
||||
static boolean stateDepthTest = false;
|
||||
static boolean stateDepthTestStash = false;
|
||||
static int stateDepthFunc = -1;
|
||||
static boolean stateDepthMask = true;
|
||||
|
||||
static boolean stateCull = false;
|
||||
static boolean stateCullStash = false;
|
||||
static int stateCullFace = GL_BACK;
|
||||
|
||||
static boolean statePolygonOffset = false;
|
||||
@ -58,6 +60,7 @@ public class GlStateManager {
|
||||
static boolean stateEnableShaderBlendColor = false;
|
||||
|
||||
static boolean stateBlend = false;
|
||||
static boolean stateBlendStash = false;
|
||||
static boolean stateGlobalBlend = true;
|
||||
static int stateBlendEquation = -1;
|
||||
static int stateBlendSRC = -1;
|
||||
@ -312,6 +315,30 @@ public class GlStateManager {
|
||||
}
|
||||
}
|
||||
|
||||
public static final void eagPushStateForGLES2BlitHack() {
|
||||
stateDepthTestStash = stateDepthTest;
|
||||
stateCullStash = stateCull;
|
||||
stateBlendStash = stateBlend;
|
||||
}
|
||||
|
||||
public static final void eagPopStateForGLES2BlitHack() {
|
||||
if(stateDepthTestStash) {
|
||||
enableDepth();
|
||||
}else {
|
||||
disableDepth();
|
||||
}
|
||||
if(stateCullStash) {
|
||||
enableCull();
|
||||
}else {
|
||||
disableCull();
|
||||
}
|
||||
if(stateBlendStash) {
|
||||
enableBlend();
|
||||
}else {
|
||||
disableBlend();
|
||||
}
|
||||
}
|
||||
|
||||
public static final void depthFunc(int depthFunc) {
|
||||
int rev = depthFunc;
|
||||
switch(depthFunc) {
|
||||
@ -603,7 +630,9 @@ public class GlStateManager {
|
||||
f2 = f1;
|
||||
}
|
||||
_wglBindTexture(GL_TEXTURE_2D, null);
|
||||
_wglBindTexture(GL_TEXTURE_3D, null);
|
||||
if(EaglercraftGPU.checkOpenGLESVersion() >= 300) {
|
||||
_wglBindTexture(GL_TEXTURE_3D, null);
|
||||
}
|
||||
boundTexture[i] = -1;
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,22 @@ public class ImageData {
|
||||
return new ImageData(pw, ph, img, alpha);
|
||||
}
|
||||
|
||||
public static String getMimeFromType(String nameOrPath) {
|
||||
if(nameOrPath == null) return "image/png";
|
||||
nameOrPath = nameOrPath.toLowerCase();
|
||||
if(nameOrPath.endsWith(".png")) {
|
||||
return "image/png";
|
||||
}else if(nameOrPath.endsWith(".jpg") || nameOrPath.endsWith(".jpeg")) {
|
||||
return "image/jpeg";
|
||||
}else if(nameOrPath.endsWith(".gif")) {
|
||||
return "image/gif";
|
||||
}else if(nameOrPath.endsWith(".bmp")) {
|
||||
return "image/bmp";
|
||||
}else {
|
||||
return "image/png"; // rip
|
||||
}
|
||||
}
|
||||
|
||||
public static final ImageData loadImageFile(String path) {
|
||||
byte[] fileData = EagRuntime.getResourceBytes(path);
|
||||
if(fileData != null) {
|
||||
@ -73,6 +89,23 @@ public class ImageData {
|
||||
return PlatformAssets.loadImageFile(data);
|
||||
}
|
||||
|
||||
public static final ImageData loadImageFile(String path, String mime) {
|
||||
byte[] fileData = EagRuntime.getResourceBytes(path);
|
||||
if(fileData != null) {
|
||||
return loadImageFile(fileData, mime);
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static final ImageData loadImageFile(InputStream data, String mime) {
|
||||
return PlatformAssets.loadImageFile(data, mime);
|
||||
}
|
||||
|
||||
public static final ImageData loadImageFile(byte[] data, String mime) {
|
||||
return PlatformAssets.loadImageFile(data, mime);
|
||||
}
|
||||
|
||||
public void getRGB(int startX, int startY, int w, int h,
|
||||
int[] rgbArray, int offset, int scansize) {
|
||||
for(int y = 0; y < h; ++y) {
|
||||
@ -147,5 +180,22 @@ public class ImageData {
|
||||
public static int swapRB(int c) {
|
||||
return (c & 0xFF00FF00) | ((c & 0x00FF0000) >>> 16) | ((c & 0x000000FF) << 16);
|
||||
}
|
||||
|
||||
public static int[] swapRB(int[] arr) {
|
||||
for(int i = 0; i < arr.length; ++i) {
|
||||
int j = arr[i];
|
||||
arr[i] = (j & 0xFF00FF00) | ((j & 0x00FF0000) >>> 16) |
|
||||
((j & 0x000000FF) << 16);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
public boolean isNPOT() {
|
||||
return (width & (width - 1)) != 0 || (height & (height - 1)) != 0;
|
||||
}
|
||||
|
||||
public static boolean isNPOTStatic(int w, int h) {
|
||||
return (w & (w - 1)) != 0 || (h & (h - 1)) != 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,13 +13,12 @@ import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f;
|
||||
import net.lax1dude.eaglercraft.v1_8.vector.Vector4f;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -38,7 +37,10 @@ public class InstancedFontRenderer {
|
||||
private static final Logger logger = LogManager.getLogger("InstancedFontRenderer");
|
||||
|
||||
public static final String vertexShaderPath = "/assets/eagler/glsl/accel_font.vsh";
|
||||
public static final String vertexShaderPrecision = "precision lowp int;\nprecision highp float;\nprecision mediump sampler2D;\n";
|
||||
|
||||
public static final String fragmentShaderPath = "/assets/eagler/glsl/accel_font.fsh";
|
||||
public static final String fragmentShaderPrecision = "precision lowp int;\nprecision highp float;\nprecision mediump sampler2D;\n";
|
||||
|
||||
private static final int BYTES_PER_CHARACTER = 10;
|
||||
private static final int CHARACTER_LIMIT = 6553;
|
||||
@ -78,21 +80,13 @@ public class InstancedFontRenderer {
|
||||
private static float charCoordHeightValue = -1.0f;
|
||||
|
||||
static void initialize() {
|
||||
|
||||
String vertexSource = EagRuntime.getResourceString(vertexShaderPath);
|
||||
if(vertexSource == null) {
|
||||
throw new RuntimeException("InstancedFontRenderer shader \"" + vertexShaderPath + "\" is missing!");
|
||||
}
|
||||
|
||||
String fragmentSource = EagRuntime.getResourceString(fragmentShaderPath);
|
||||
if(fragmentSource == null) {
|
||||
throw new RuntimeException("InstancedFontRenderer shader \"" + fragmentShaderPath + "\" is missing!");
|
||||
}
|
||||
String vertexSource = EagRuntime.getRequiredResourceString(vertexShaderPath);
|
||||
String fragmentSource = EagRuntime.getRequiredResourceString(fragmentShaderPath);
|
||||
|
||||
IShaderGL vert = _wglCreateShader(GL_VERTEX_SHADER);
|
||||
IShaderGL frag = _wglCreateShader(GL_FRAGMENT_SHADER);
|
||||
|
||||
_wglShaderSource(vert, FixedFunctionConstants.VERSION + "\n" + vertexSource);
|
||||
_wglShaderSource(vert, GLSLHeader.getVertexHeaderCompat(vertexSource, vertexShaderPrecision));
|
||||
_wglCompileShader(vert);
|
||||
|
||||
if(_wglGetShaderi(vert, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
@ -107,7 +101,7 @@ public class InstancedFontRenderer {
|
||||
throw new IllegalStateException("Vertex shader \"" + vertexShaderPath + "\" could not be compiled!");
|
||||
}
|
||||
|
||||
_wglShaderSource(frag, FixedFunctionConstants.VERSION + "\n" + fragmentSource);
|
||||
_wglShaderSource(frag, GLSLHeader.getFragmentHeaderCompat(fragmentSource, fragmentShaderPrecision));
|
||||
_wglCompileShader(frag);
|
||||
|
||||
if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
@ -127,6 +121,10 @@ public class InstancedFontRenderer {
|
||||
_wglAttachShader(shaderProgram, vert);
|
||||
_wglAttachShader(shaderProgram, frag);
|
||||
|
||||
if(EaglercraftGPU.checkOpenGLESVersion() == 200) {
|
||||
VSHInputLayoutParser.applyLayout(shaderProgram, VSHInputLayoutParser.getShaderInputs(vertexSource));
|
||||
}
|
||||
|
||||
_wglLinkProgram(shaderProgram);
|
||||
|
||||
_wglDetachShader(shaderProgram, vert);
|
||||
@ -161,60 +159,62 @@ public class InstancedFontRenderer {
|
||||
|
||||
_wglUniform1i(_wglGetUniformLocation(shaderProgram, "u_inputTexture"), 0);
|
||||
|
||||
vertexArray = _wglGenVertexArrays();
|
||||
vertexArray = EaglercraftGPU.createGLBufferArray();
|
||||
vertexBuffer = _wglGenBuffers();
|
||||
instancesBuffer = _wglGenBuffers();
|
||||
|
||||
FloatBuffer verts = EagRuntime.allocateFloatBuffer(108);
|
||||
float paddingA = 0.005f;
|
||||
float paddingB = 1.0f - paddingA;
|
||||
verts.put(new float[] {
|
||||
|
||||
// (0 - 6 - 12) regular:
|
||||
|
||||
0.0f, 0.0f, 0.25f, 0.0f, 1.0f, 0.25f, 1.0f, 0.0f, 0.25f,
|
||||
1.0f, 0.0f, 0.25f, 0.0f, 1.0f, 0.25f, 1.0f, 1.0f, 0.25f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
|
||||
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
|
||||
paddingA, paddingA, 0.25f, paddingA, paddingB, 0.25f, paddingB, paddingA, 0.25f,
|
||||
paddingB, paddingA, 0.25f, paddingA, paddingB, 0.25f, paddingB, paddingB, 0.25f,
|
||||
paddingA, paddingA, 0.0f, paddingA, paddingB, 0.0f, paddingB, paddingA, 0.0f,
|
||||
paddingB, paddingA, 0.0f, paddingA, paddingB, 0.0f, paddingB, paddingB, 0.0f,
|
||||
|
||||
// (12 - 24 - 36) bold shadow:
|
||||
|
||||
0.0f, 0.0f, 0.25f, 0.0f, 1.0f, 0.25f, 1.0f, 0.0f, 0.25f,
|
||||
1.0f, 0.0f, 0.25f, 0.0f, 1.0f, 0.25f, 1.0f, 1.0f, 0.25f,
|
||||
0.0f, 0.0f, 0.75f, 0.0f, 1.0f, 0.75f, 1.0f, 0.0f, 0.75f,
|
||||
1.0f, 0.0f, 0.75f, 0.0f, 1.0f, 0.75f, 1.0f, 1.0f, 0.75f,
|
||||
paddingA, paddingA, 0.25f, paddingA, paddingB, 0.25f, paddingB, paddingA, 0.25f,
|
||||
paddingB, paddingA, 0.25f, paddingA, paddingB, 0.25f, paddingB, paddingB, 0.25f,
|
||||
paddingA, paddingA, 0.75f, paddingA, paddingB, 0.75f, paddingB, paddingA, 0.75f,
|
||||
paddingB, paddingA, 0.75f, paddingA, paddingB, 0.75f, paddingB, paddingB, 0.75f,
|
||||
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
|
||||
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.5f, 0.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.5f,
|
||||
1.0f, 0.0f, 0.5f, 0.0f, 1.0f, 0.5f, 1.0f, 1.0f, 0.5f
|
||||
paddingA, paddingA, 0.0f, paddingA, paddingB, 0.0f, paddingB, paddingA, 0.0f,
|
||||
paddingB, paddingA, 0.0f, paddingA, paddingB, 0.0f, paddingB, paddingB, 0.0f,
|
||||
paddingA, paddingA, 0.5f, paddingA, paddingB, 0.5f, paddingB, paddingA, 0.5f,
|
||||
paddingB, paddingA, 0.5f, paddingA, paddingB, 0.5f, paddingB, paddingB, 0.5f
|
||||
|
||||
});
|
||||
verts.flip();
|
||||
|
||||
EaglercraftGPU.bindGLBufferArray(vertexArray);
|
||||
|
||||
EaglercraftGPU.bindGLArrayBuffer(vertexBuffer);
|
||||
EaglercraftGPU.bindVAOGLArrayBufferNow(vertexBuffer);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, verts, GL_STATIC_DRAW);
|
||||
|
||||
EagRuntime.freeFloatBuffer(verts);
|
||||
|
||||
_wglEnableVertexAttribArray(0);
|
||||
_wglVertexAttribPointer(0, 3, GL_FLOAT, false, 12, 0);
|
||||
_wglVertexAttribDivisor(0, 0);
|
||||
EaglercraftGPU.enableVertexAttribArray(0);
|
||||
EaglercraftGPU.vertexAttribPointer(0, 3, GL_FLOAT, false, 12, 0);
|
||||
EaglercraftGPU.vertexAttribDivisor(0, 0);
|
||||
|
||||
EaglercraftGPU.bindGLArrayBuffer(instancesBuffer);
|
||||
EaglercraftGPU.bindVAOGLArrayBufferNow(instancesBuffer);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, fontDataBuffer.remaining(), GL_STREAM_DRAW);
|
||||
|
||||
_wglEnableVertexAttribArray(1);
|
||||
_wglVertexAttribPointer(1, 2, GL_SHORT, false, 10, 0);
|
||||
_wglVertexAttribDivisor(1, 1);
|
||||
EaglercraftGPU.enableVertexAttribArray(1);
|
||||
EaglercraftGPU.vertexAttribPointer(1, 2, GL_SHORT, false, 10, 0);
|
||||
EaglercraftGPU.vertexAttribDivisor(1, 1);
|
||||
|
||||
_wglEnableVertexAttribArray(2);
|
||||
_wglVertexAttribPointer(2, 2, GL_UNSIGNED_BYTE, false, 10, 4);
|
||||
_wglVertexAttribDivisor(2, 1);
|
||||
EaglercraftGPU.enableVertexAttribArray(2);
|
||||
EaglercraftGPU.vertexAttribPointer(2, 2, GL_UNSIGNED_BYTE, false, 10, 4);
|
||||
EaglercraftGPU.vertexAttribDivisor(2, 1);
|
||||
|
||||
_wglEnableVertexAttribArray(3);
|
||||
_wglVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, true, 10, 6);
|
||||
_wglVertexAttribDivisor(3, 1);
|
||||
EaglercraftGPU.enableVertexAttribArray(3);
|
||||
EaglercraftGPU.vertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, true, 10, 6);
|
||||
EaglercraftGPU.vertexAttribDivisor(3, 1);
|
||||
|
||||
}
|
||||
|
||||
@ -381,7 +381,7 @@ public class InstancedFontRenderer {
|
||||
fontDataBuffer.position(p);
|
||||
fontDataBuffer.limit(l);
|
||||
|
||||
_wglDrawArraysInstanced(GL_TRIANGLES, shadow ? 0 : 6, shadow ? 12 : 6, charactersDrawn);
|
||||
EaglercraftGPU.doDrawArraysInstanced(GL_TRIANGLES, shadow ? 0 : 6, shadow ? 12 : 6, charactersDrawn);
|
||||
}
|
||||
|
||||
if(boldCharactersDrawn > 0) {
|
||||
@ -394,7 +394,7 @@ public class InstancedFontRenderer {
|
||||
fontBoldDataBuffer.position(p);
|
||||
fontBoldDataBuffer.limit(l);
|
||||
|
||||
_wglDrawArraysInstanced(GL_TRIANGLES, shadow ? 12 : 24, shadow ? 24 : 12, boldCharactersDrawn);
|
||||
EaglercraftGPU.doDrawArraysInstanced(GL_TRIANGLES, shadow ? 12 : 24, shadow ? 24 : 12, boldCharactersDrawn);
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,4 +455,40 @@ public class InstancedFontRenderer {
|
||||
if(y > heightCalcMost || heightCalcMost == Integer.MAX_VALUE) heightCalcMost = y;
|
||||
}
|
||||
|
||||
public static void destroy() {
|
||||
if(fontDataBuffer != null) {
|
||||
EagRuntime.freeByteBuffer(fontDataBuffer);
|
||||
fontDataBuffer = null;
|
||||
}
|
||||
if(fontBoldDataBuffer != null) {
|
||||
EagRuntime.freeByteBuffer(fontBoldDataBuffer);
|
||||
fontBoldDataBuffer = null;
|
||||
}
|
||||
if(shaderProgram != null) {
|
||||
_wglDeleteProgram(shaderProgram);
|
||||
shaderProgram = null;
|
||||
}
|
||||
if(matrixCopyBuffer != null) {
|
||||
EagRuntime.freeFloatBuffer(matrixCopyBuffer);
|
||||
matrixCopyBuffer = null;
|
||||
}
|
||||
u_matrixTransform = null;
|
||||
u_charSize2f = null;
|
||||
u_charCoordSize2f = null;
|
||||
u_color4f = null;
|
||||
u_colorBias4f = null;
|
||||
if(vertexArray != null) {
|
||||
EaglercraftGPU.destroyGLBufferArray(vertexArray);
|
||||
vertexArray = null;
|
||||
}
|
||||
if(vertexBuffer != null) {
|
||||
_wglDeleteBuffers(vertexBuffer);
|
||||
vertexBuffer = null;
|
||||
}
|
||||
if(instancesBuffer != null) {
|
||||
_wglDeleteBuffers(instancesBuffer);
|
||||
instancesBuffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,11 +13,10 @@ import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants;
|
||||
import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -36,7 +35,10 @@ public class InstancedParticleRenderer {
|
||||
private static final Logger logger = LogManager.getLogger("InstancedParticleRenderer");
|
||||
|
||||
public static final String vertexShaderPath = "/assets/eagler/glsl/accel_particle.vsh";
|
||||
public static final String vertexShaderPrecision = "precision lowp int;\nprecision highp float;\nprecision mediump sampler2D;\n";
|
||||
|
||||
public static final String fragmentShaderPath = "/assets/eagler/glsl/accel_particle.fsh";
|
||||
public static final String fragmentShaderPrecision = "precision lowp int;\nprecision mediump float;\nprecision mediump sampler2D;\n";
|
||||
|
||||
private static ByteBuffer particleBuffer = null;
|
||||
private static int particleCount = 0;
|
||||
@ -79,20 +81,13 @@ public class InstancedParticleRenderer {
|
||||
private static float stateTransformParam5 = -999.0f;
|
||||
|
||||
static void initialize() {
|
||||
String vertexSource = EagRuntime.getResourceString(vertexShaderPath);
|
||||
if(vertexSource == null) {
|
||||
throw new RuntimeException("InstancedParticleRenderer shader \"" + vertexShaderPath + "\" is missing!");
|
||||
}
|
||||
|
||||
String fragmentSource = EagRuntime.getResourceString(fragmentShaderPath);
|
||||
if(fragmentSource == null) {
|
||||
throw new RuntimeException("InstancedParticleRenderer shader \"" + fragmentShaderPath + "\" is missing!");
|
||||
}
|
||||
String vertexSource = EagRuntime.getRequiredResourceString(vertexShaderPath);
|
||||
String fragmentSource = EagRuntime.getRequiredResourceString(fragmentShaderPath);
|
||||
|
||||
IShaderGL vert = _wglCreateShader(GL_VERTEX_SHADER);
|
||||
IShaderGL frag = _wglCreateShader(GL_FRAGMENT_SHADER);
|
||||
|
||||
_wglShaderSource(vert, FixedFunctionConstants.VERSION + "\n" + vertexSource);
|
||||
_wglShaderSource(vert, GLSLHeader.getVertexHeaderCompat(vertexSource, vertexShaderPrecision));
|
||||
_wglCompileShader(vert);
|
||||
|
||||
if(_wglGetShaderi(vert, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
@ -107,7 +102,7 @@ public class InstancedParticleRenderer {
|
||||
throw new IllegalStateException("Vertex shader \"" + vertexShaderPath + "\" could not be compiled!");
|
||||
}
|
||||
|
||||
_wglShaderSource(frag, FixedFunctionConstants.VERSION + "\n" + fragmentSource);
|
||||
_wglShaderSource(frag, GLSLHeader.getFragmentHeaderCompat(fragmentSource, fragmentShaderPrecision));
|
||||
_wglCompileShader(frag);
|
||||
|
||||
if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
@ -127,6 +122,10 @@ public class InstancedParticleRenderer {
|
||||
_wglAttachShader(shaderProgram, vert);
|
||||
_wglAttachShader(shaderProgram, frag);
|
||||
|
||||
if(EaglercraftGPU.checkOpenGLESVersion() == 200) {
|
||||
VSHInputLayoutParser.applyLayout(shaderProgram, VSHInputLayoutParser.getShaderInputs(vertexSource));
|
||||
}
|
||||
|
||||
_wglLinkProgram(shaderProgram);
|
||||
|
||||
_wglDetachShader(shaderProgram, vert);
|
||||
@ -161,7 +160,7 @@ public class InstancedParticleRenderer {
|
||||
_wglUniform1i(_wglGetUniformLocation(shaderProgram, "u_inputTexture"), 0);
|
||||
_wglUniform1i(_wglGetUniformLocation(shaderProgram, "u_lightmapTexture"), 1);
|
||||
|
||||
vertexArray = _wglGenVertexArrays();
|
||||
vertexArray = EaglercraftGPU.createGLBufferArray();
|
||||
vertexBuffer = _wglGenBuffers();
|
||||
instancesBuffer = _wglGenBuffers();
|
||||
|
||||
@ -174,37 +173,37 @@ public class InstancedParticleRenderer {
|
||||
|
||||
EaglercraftGPU.bindGLBufferArray(vertexArray);
|
||||
|
||||
EaglercraftGPU.bindGLArrayBuffer(vertexBuffer);
|
||||
EaglercraftGPU.bindVAOGLArrayBufferNow(vertexBuffer);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, verts, GL_STATIC_DRAW);
|
||||
|
||||
EagRuntime.freeFloatBuffer(verts);
|
||||
|
||||
_wglEnableVertexAttribArray(0);
|
||||
_wglVertexAttribPointer(0, 2, GL_FLOAT, false, 8, 0);
|
||||
_wglVertexAttribDivisor(0, 0);
|
||||
EaglercraftGPU.enableVertexAttribArray(0);
|
||||
EaglercraftGPU.vertexAttribPointer(0, 2, GL_FLOAT, false, 8, 0);
|
||||
EaglercraftGPU.vertexAttribDivisor(0, 0);
|
||||
|
||||
EaglercraftGPU.bindGLArrayBuffer(instancesBuffer);
|
||||
EaglercraftGPU.bindVAOGLArrayBufferNow(instancesBuffer);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.remaining(), GL_STREAM_DRAW);
|
||||
|
||||
_wglEnableVertexAttribArray(1);
|
||||
_wglVertexAttribPointer(1, 3, GL_FLOAT, false, 24, 0);
|
||||
_wglVertexAttribDivisor(1, 1);
|
||||
EaglercraftGPU.enableVertexAttribArray(1);
|
||||
EaglercraftGPU.vertexAttribPointer(1, 3, GL_FLOAT, false, 24, 0);
|
||||
EaglercraftGPU.vertexAttribDivisor(1, 1);
|
||||
|
||||
_wglEnableVertexAttribArray(2);
|
||||
_wglVertexAttribPointer(2, 2, GL_UNSIGNED_SHORT, false, 24, 12);
|
||||
_wglVertexAttribDivisor(2, 1);
|
||||
EaglercraftGPU.enableVertexAttribArray(2);
|
||||
EaglercraftGPU.vertexAttribPointer(2, 2, GL_UNSIGNED_SHORT, false, 24, 12);
|
||||
EaglercraftGPU.vertexAttribDivisor(2, 1);
|
||||
|
||||
_wglEnableVertexAttribArray(3);
|
||||
_wglVertexAttribPointer(3, 2, GL_UNSIGNED_BYTE, true, 24, 16);
|
||||
_wglVertexAttribDivisor(3, 1);
|
||||
EaglercraftGPU.enableVertexAttribArray(3);
|
||||
EaglercraftGPU.vertexAttribPointer(3, 2, GL_UNSIGNED_BYTE, true, 24, 16);
|
||||
EaglercraftGPU.vertexAttribDivisor(3, 1);
|
||||
|
||||
_wglEnableVertexAttribArray(4);
|
||||
_wglVertexAttribPointer(4, 2, GL_UNSIGNED_BYTE, false, 24, 18);
|
||||
_wglVertexAttribDivisor(4, 1);
|
||||
EaglercraftGPU.enableVertexAttribArray(4);
|
||||
EaglercraftGPU.vertexAttribPointer(4, 2, GL_UNSIGNED_BYTE, false, 24, 18);
|
||||
EaglercraftGPU.vertexAttribDivisor(4, 1);
|
||||
|
||||
_wglEnableVertexAttribArray(5);
|
||||
_wglVertexAttribPointer(5, 4, GL_UNSIGNED_BYTE, true, 24, 20);
|
||||
_wglVertexAttribDivisor(5, 1);
|
||||
EaglercraftGPU.enableVertexAttribArray(5);
|
||||
EaglercraftGPU.vertexAttribPointer(5, 4, GL_UNSIGNED_BYTE, true, 24, 20);
|
||||
EaglercraftGPU.vertexAttribDivisor(5, 1);
|
||||
|
||||
}
|
||||
|
||||
@ -316,11 +315,43 @@ public class InstancedParticleRenderer {
|
||||
particleBuffer.position(p);
|
||||
particleBuffer.limit(l);
|
||||
|
||||
_wglDrawArraysInstanced(GL_TRIANGLES, 0, 6, particleCount);
|
||||
EaglercraftGPU.doDrawArraysInstanced(GL_TRIANGLES, 0, 6, particleCount);
|
||||
}
|
||||
|
||||
public static void stupidColorSetHack(IUniformGL color4f) {
|
||||
_wglUniform4f(color4f, GlStateManager.stateColorR, GlStateManager.stateColorG, GlStateManager.stateColorB, GlStateManager.stateColorA);
|
||||
}
|
||||
|
||||
public static void destroy() {
|
||||
if(particleBuffer != null) {
|
||||
EagRuntime.freeByteBuffer(particleBuffer);
|
||||
particleBuffer = null;
|
||||
}
|
||||
if(shaderProgram != null) {
|
||||
_wglDeleteProgram(shaderProgram);
|
||||
shaderProgram = null;
|
||||
}
|
||||
if(matrixCopyBuffer != null) {
|
||||
EagRuntime.freeFloatBuffer(matrixCopyBuffer);
|
||||
matrixCopyBuffer = null;
|
||||
}
|
||||
u_matrixTransform = null;
|
||||
u_texCoordSize2f_particleSize1f = null;
|
||||
u_transformParam_1_2_5_f = null;
|
||||
u_transformParam_3_4_f = null;
|
||||
u_color4f = null;
|
||||
if(vertexArray != null) {
|
||||
EaglercraftGPU.destroyGLBufferArray(vertexArray);
|
||||
vertexArray = null;
|
||||
}
|
||||
if(vertexBuffer != null) {
|
||||
_wglDeleteBuffers(vertexBuffer);
|
||||
vertexBuffer = null;
|
||||
}
|
||||
if(instancesBuffer != null) {
|
||||
_wglDeleteBuffers(instancesBuffer);
|
||||
instancesBuffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.opengl;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved.
|
||||
* Copyright (c) 2022-2023 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
|
||||
|
@ -0,0 +1,225 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.opengl;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IBufferArrayGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL;
|
||||
|
||||
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.
|
||||
*
|
||||
*/
|
||||
class SoftGLBufferArray implements IBufferArrayGL {
|
||||
|
||||
Attrib[] attribs = new Attrib[4];
|
||||
int[] attribDivisors = null;
|
||||
int hasAttribDivisorMask = 0;
|
||||
int enabled = 0;
|
||||
int enabledCnt = -1;
|
||||
IBufferGL indexBuffer = null;
|
||||
|
||||
SoftGLBufferArray() {
|
||||
}
|
||||
|
||||
void setAttrib(IBufferGL buffer, int index, int size, int format, boolean normalized, int stride, int offset) {
|
||||
if(index >= attribs.length) {
|
||||
int newLen = attribs.length << 1;
|
||||
while(newLen <= index) {
|
||||
newLen <<= 1;
|
||||
}
|
||||
Attrib[] newAttrib = new Attrib[newLen];
|
||||
System.arraycopy(attribs, 0, newAttrib, 0, attribs.length);
|
||||
attribs = newAttrib;
|
||||
}
|
||||
attribs[index] = new Attrib(buffer, size, format, normalized, stride, offset);
|
||||
}
|
||||
|
||||
void setAttribDivisor(int index, int divisor) {
|
||||
if(attribDivisors == null) {
|
||||
if(divisor != 0) {
|
||||
int newLen = 8;
|
||||
while(newLen <= index) {
|
||||
newLen <<= 1;
|
||||
}
|
||||
attribDivisors = new int[newLen];
|
||||
}
|
||||
}else if(index >= attribDivisors.length) {
|
||||
int newLen = attribDivisors.length << 1;
|
||||
while(newLen <= index) {
|
||||
newLen <<= 1;
|
||||
}
|
||||
int[] newDivisor = new int[newLen];
|
||||
System.arraycopy(attribDivisors, 0, newDivisor, 0, attribDivisors.length);
|
||||
attribDivisors = newDivisor;
|
||||
}
|
||||
if(attribDivisors != null) {
|
||||
attribDivisors[index] = divisor;
|
||||
if(divisor != 0) {
|
||||
hasAttribDivisorMask |= (1 << index);
|
||||
}else {
|
||||
hasAttribDivisorMask &= ~(1 << index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void enableAttrib(int index, boolean en) {
|
||||
if(en) {
|
||||
enabled |= (1 << index);
|
||||
}else {
|
||||
enabled &= ~(1 << index);
|
||||
}
|
||||
enabledCnt = 32 - Integer.numberOfLeadingZeros(enabled);
|
||||
}
|
||||
|
||||
void setIndexBuffer(IBufferGL buffer) {
|
||||
indexBuffer = buffer;
|
||||
}
|
||||
|
||||
void transitionToState(SoftGLBufferState previousState, boolean elements) {
|
||||
int oldEnabled = previousState.oldEnabled;
|
||||
int oldEnabledCnt = previousState.oldEnabledCnt;
|
||||
int[] oldAttribDivisors = previousState.attribDivisors;
|
||||
int oldHasAttribDivisorMask = previousState.hasAttribDivisorMask;
|
||||
Attrib[] oldAttrs = previousState.attribs;
|
||||
boolean instancingCapable = EaglercraftGPU.checkInstancingCapable();
|
||||
int enCnt = enabledCnt;
|
||||
int en = enabled;
|
||||
Attrib[] attrs = attribs;
|
||||
int[] divs = attribDivisors;
|
||||
int hasDivs = hasAttribDivisorMask;
|
||||
if(oldEnabledCnt >= 0) {
|
||||
int enMax = Math.max(enCnt, oldEnabledCnt);
|
||||
for(int i = 0, ii; i < enMax; ++i) {
|
||||
ii = (1 << i);
|
||||
boolean old = i < oldEnabledCnt && (oldEnabled & ii) != 0;
|
||||
boolean _new = i < enCnt && (en & ii) != 0;
|
||||
if(_new) {
|
||||
if(!old) {
|
||||
_wglEnableVertexAttribArray(i);
|
||||
}
|
||||
Attrib attr = i < attrs.length ? attrs[i] : null;
|
||||
if(attr != null) {
|
||||
Attrib oldAttr = oldAttrs[i];
|
||||
if(oldAttr == null || !oldAttr.equalsExplicit(attr)) {
|
||||
EaglercraftGPU.bindGLArrayBuffer(attr.buffer);
|
||||
_wglVertexAttribPointer(i, attr.size, attr.format, attr.normalized, attr.stride, attr.offset);
|
||||
oldAttrs[i] = attr;
|
||||
}
|
||||
}else {
|
||||
oldAttrs[i] = null;
|
||||
}
|
||||
if(instancingCapable) {
|
||||
// instancing is uncommon
|
||||
if((hasDivs & ii) != 0) {
|
||||
int newDivisor = divs[i];
|
||||
if((oldHasAttribDivisorMask & ii) == 0 || newDivisor != oldAttribDivisors[i]) {
|
||||
_wglVertexAttribDivisor(i, newDivisor);
|
||||
oldAttribDivisors[i] = newDivisor;
|
||||
previousState.hasAttribDivisorMask |= ii;
|
||||
}
|
||||
}else {
|
||||
if((oldHasAttribDivisorMask & ii) != 0) {
|
||||
_wglVertexAttribDivisor(i, 0);
|
||||
oldAttribDivisors[i] = 0;
|
||||
previousState.hasAttribDivisorMask &= ~ii;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if(old) {
|
||||
_wglDisableVertexAttribArray(i);
|
||||
}
|
||||
}
|
||||
}else {
|
||||
// Bootstrap code for the emulator's first draw
|
||||
for(int i = 0; i < enCnt; ++i) {
|
||||
int ii = (1 << i);
|
||||
if((en & ii) != 0) {
|
||||
_wglEnableVertexAttribArray(i);
|
||||
Attrib attr = attrs[i];
|
||||
if(attr != null) {
|
||||
EaglercraftGPU.bindGLArrayBuffer(attr.buffer);
|
||||
_wglVertexAttribPointer(i, attr.size, attr.format, attr.normalized, attr.stride, attr.offset);
|
||||
oldAttrs[i] = attr;
|
||||
}else {
|
||||
oldAttrs[i] = null;
|
||||
}
|
||||
if(instancingCapable) {
|
||||
if((hasDivs & ii) != 0) {
|
||||
int newDivisor = divs[i];
|
||||
_wglVertexAttribDivisor(i, newDivisor);
|
||||
oldAttribDivisors[i] = newDivisor;
|
||||
previousState.hasAttribDivisorMask |= ii;
|
||||
}else {
|
||||
_wglVertexAttribDivisor(i, 0);
|
||||
oldAttribDivisors[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(elements) {
|
||||
IBufferGL indexBufferL = indexBuffer;
|
||||
if(indexBufferL != null) {
|
||||
EaglercraftGPU.bindEmulatedVAOIndexBuffer(indexBufferL);
|
||||
}
|
||||
}
|
||||
previousState.oldEnabled = en & ((1 << enCnt) - 1);
|
||||
previousState.oldEnabledCnt = enCnt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free() {
|
||||
}
|
||||
|
||||
static class Attrib {
|
||||
|
||||
final IBufferGL buffer;
|
||||
final int size;
|
||||
final int format;
|
||||
final boolean normalized;
|
||||
final int stride;
|
||||
final int offset;
|
||||
final int hash;
|
||||
final int checkVal;
|
||||
|
||||
Attrib(IBufferGL buffer, int size, int format, boolean normalized, int stride, int offset) {
|
||||
this.buffer = buffer;
|
||||
this.size = size;
|
||||
this.format = format;
|
||||
this.normalized = normalized;
|
||||
this.stride = stride;
|
||||
this.offset = offset;
|
||||
this.checkVal = ((size - 1) & 3) | (normalized ? 4 : 0) | (format << 4);
|
||||
this.hash = (((((31 + buffer.hashCode()) * 31 + size) * 31 + format) * 31 + (normalized ? 1 : 0)) * 31
|
||||
+ stride) * 31 + offset;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if(obj == this) return true;
|
||||
if(!(obj instanceof Attrib)) return false;
|
||||
Attrib o2 = (Attrib)obj;
|
||||
return o2.hash == hash && o2.buffer == buffer && o2.checkVal == checkVal && o2.stride == stride && o2.offset == offset;
|
||||
}
|
||||
|
||||
public boolean equalsExplicit(Attrib o2) {
|
||||
return o2 == this || (o2.hash == hash && o2.buffer == buffer && o2.checkVal == checkVal && o2.stride == stride && o2.offset == offset);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,9 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
package net.lax1dude.eaglercraft.v1_8.opengl;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.SoftGLBufferArray.Attrib;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
* 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
|
||||
@ -18,19 +17,15 @@ import java.io.IOException;
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket02NewClient extends IPacket {
|
||||
|
||||
public String clientId;
|
||||
|
||||
public IPacket02NewClient(String clientId) {
|
||||
this.clientId = clientId;
|
||||
class SoftGLBufferState {
|
||||
|
||||
final Attrib[] attribs = new Attrib[24];
|
||||
int[] attribDivisors = new int[24];
|
||||
int hasAttribDivisorMask = 0;
|
||||
int oldEnabled = 0;
|
||||
int oldEnabledCnt = -1;
|
||||
|
||||
SoftGLBufferState() {
|
||||
}
|
||||
|
||||
public IPacket02NewClient() {
|
||||
}
|
||||
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
clientId = readASCII8(input);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -10,7 +10,6 @@ import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants;
|
||||
import net.lax1dude.eaglercraft.v1_8.vector.Matrix3f;
|
||||
|
||||
/**
|
||||
@ -33,6 +32,7 @@ public class SpriteLevelMixer {
|
||||
private static final Logger LOGGER = LogManager.getLogger("SpriteLevelMixer");
|
||||
|
||||
public static final String fragmentShaderPath = "/assets/eagler/glsl/texture_mix.fsh";
|
||||
public static final String fragmentShaderPrecision = "precision lowp int;\nprecision highp float;\nprecision highp sampler2D;\n";
|
||||
|
||||
private static IProgramGL shaderProgram = null;
|
||||
|
||||
@ -61,15 +61,11 @@ public class SpriteLevelMixer {
|
||||
private static final Matrix3f identityMatrix = new Matrix3f();
|
||||
|
||||
static void initialize() {
|
||||
|
||||
String fragmentSource = EagRuntime.getResourceString(fragmentShaderPath);
|
||||
if(fragmentSource == null) {
|
||||
throw new RuntimeException("SpriteLevelMixer shader \"" + fragmentShaderPath + "\" is missing!");
|
||||
}
|
||||
String fragmentSource = EagRuntime.getRequiredResourceString(fragmentShaderPath);
|
||||
|
||||
IShaderGL frag = _wglCreateShader(GL_FRAGMENT_SHADER);
|
||||
|
||||
_wglShaderSource(frag, FixedFunctionConstants.VERSION + "\n" + fragmentSource);
|
||||
_wglShaderSource(frag, GLSLHeader.getFragmentHeaderCompat(fragmentSource, fragmentShaderPrecision));
|
||||
_wglCompileShader(frag);
|
||||
|
||||
if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
@ -89,6 +85,10 @@ public class SpriteLevelMixer {
|
||||
_wglAttachShader(shaderProgram, DrawUtils.vshLocal);
|
||||
_wglAttachShader(shaderProgram, frag);
|
||||
|
||||
if(EaglercraftGPU.checkOpenGLESVersion() == 200) {
|
||||
VSHInputLayoutParser.applyLayout(shaderProgram, DrawUtils.vshLocalLayout);
|
||||
}
|
||||
|
||||
_wglLinkProgram(shaderProgram);
|
||||
|
||||
_wglDetachShader(shaderProgram, DrawUtils.vshLocal);
|
||||
@ -155,7 +155,14 @@ public class SpriteLevelMixer {
|
||||
public static void drawSprite(float level) {
|
||||
EaglercraftGPU.bindGLShaderProgram(shaderProgram);
|
||||
|
||||
_wglUniform1f(u_textureLod1f, level);
|
||||
if(EaglercraftGPU.checkTextureLODCapable()) {
|
||||
_wglUniform1f(u_textureLod1f, level);
|
||||
}else {
|
||||
if(level != 0.0f) {
|
||||
LOGGER.error("Tried to copy from mipmap level {}, but this GPU does not support textureLod!", level);
|
||||
}
|
||||
_wglUniform1f(u_textureLod1f, 0.0f);
|
||||
}
|
||||
|
||||
if(blendColorChanged) {
|
||||
_wglUniform4f(u_blendFactor4f, blendColorR, blendColorG, blendColorB, blendColorA);
|
||||
@ -178,4 +185,19 @@ public class SpriteLevelMixer {
|
||||
DrawUtils.drawStandardQuad2D();
|
||||
}
|
||||
|
||||
public static void destroy() {
|
||||
if(matrixCopyBuffer != null) {
|
||||
EagRuntime.freeFloatBuffer(matrixCopyBuffer);
|
||||
matrixCopyBuffer = null;
|
||||
}
|
||||
if(shaderProgram != null) {
|
||||
_wglDeleteProgram(shaderProgram);
|
||||
shaderProgram = null;
|
||||
}
|
||||
u_textureLod1f = null;
|
||||
u_blendFactor4f = null;
|
||||
u_blendBias4f = null;
|
||||
u_matrixTransform = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ public class StreamBuffer {
|
||||
next.vertexBuffer = _wglGenBuffers();
|
||||
}
|
||||
if(next.vertexArray == null) {
|
||||
next.vertexArray = _wglGenVertexArrays();
|
||||
next.vertexArray = EaglercraftGPU.createGLBufferArray();
|
||||
initializer.initialize(next.vertexArray, next.vertexBuffer);
|
||||
}
|
||||
if(next.vertexBufferSize < requiredMemory) {
|
||||
@ -100,7 +100,7 @@ public class StreamBuffer {
|
||||
newArray[i] = buffers[i];
|
||||
}else {
|
||||
if(buffers[i].vertexArray != null) {
|
||||
_wglDeleteVertexArrays(buffers[i].vertexArray);
|
||||
EaglercraftGPU.destroyGLBufferArray(buffers[i].vertexArray);
|
||||
}
|
||||
if(buffers[i].vertexBuffer != null) {
|
||||
_wglDeleteBuffers(buffers[i].vertexBuffer);
|
||||
@ -135,7 +135,7 @@ public class StreamBuffer {
|
||||
for(int i = 0; i < buffers.length; ++i) {
|
||||
StreamBufferInstance next = buffers[i];
|
||||
if(next.vertexArray != null) {
|
||||
_wglDeleteVertexArrays(next.vertexArray);
|
||||
EaglercraftGPU.destroyGLBufferArray(next.vertexArray);
|
||||
}
|
||||
if(next.vertexBuffer != null) {
|
||||
_wglDeleteBuffers(next.vertexBuffer);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user