Skip to content

Commit e79eb8a

Browse files
committed
Progress on fixing stuff
1 parent ed49a28 commit e79eb8a

File tree

16 files changed

+258
-22
lines changed

16 files changed

+258
-22
lines changed

client/src/main/java/com/fox2code/foxloader/client/mixins/MixinNetClientHandler.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,12 @@ public void onHandlePluginMessage(Packet250PluginMessage packet250, CallbackInfo
7171
NetworkPlayer networkPlayer = (NetworkPlayer)
7272
Minecraft.getInstance().thePlayer;
7373
if (ModLoader.FOX_LOADER_MOD_ID.equals(packet250.channel)) {
74+
ModLoader.getModLoaderLogger().info("Got FoxLoader packet");
7475
this.isFoxLoader = true;
7576
}
7677
ModContainer modContainer = ModLoader.getModContainer(packet250.channel);
7778
if (networkPlayer != null && modContainer != null && packet250.data != null) {
79+
ModLoader.getModLoaderLogger().info("Processing FoxLoader packet");
7880
modContainer.notifyReceiveServerPacket(networkPlayer, packet250.data);
7981
}
8082
}

client/src/main/java/com/fox2code/foxloader/loader/ClientModLoader.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ private static void computeClientHello() {
4545
final byte[] nullSHA256 = new byte[32];
4646
try {
4747
ArrayList<ClientHello.ClientModData> clientModData =
48-
new ArrayList<>(ModLoader.modContainers.size());
48+
new ArrayList<>(ModLoader.modContainers.size() +
49+
ModLoader.coreMods.size());
4950
for (File coreMod : ModLoader.coreMods) {
5051
byte[] sha256 = NetUtils.hashOf(coreMod);
5152
clientModData.add(new ClientHello.ClientModData(
@@ -76,6 +77,12 @@ public void onServerStart(NetworkPlayer.ConnectionType connectionType) {
7677
GameRegistryClient.resetMappings(connectionType.isServer);
7778
}
7879

80+
@Override
81+
public void onReceiveServerPacket(NetworkPlayer networkPlayer, byte[] data) {
82+
ModLoader.foxLoader.logger.info("Received server packet");
83+
LoaderNetworkManager.executeServerPacketData(networkPlayer, data);
84+
}
85+
7986
@Override
8087
void loaderHandleServerHello(NetworkPlayer networkPlayer, ServerHello serverHello) {
8188
ModLoader.foxLoader.logger.info("Initializing id translator");

common/src/main/java/com/fox2code/foxloader/launcher/StackTraceStringifier.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.fox2code.foxloader.launcher;
22

3+
import com.fox2code.foxloader.launcher.utils.FastThreadLocal;
34
import org.jetbrains.annotations.NotNull;
45

56
import java.io.IOException;
@@ -37,8 +38,8 @@ public String stringify(Throwable throwable) {
3738
return stringBuilder.toString();
3839
}
3940

40-
private static final ThreadLocal<StackTraceStringifier> stringifier =
41-
ThreadLocal.withInitial(StackTraceStringifier::new);
41+
private static final FastThreadLocal<StackTraceStringifier> stringifier =
42+
FastThreadLocal.withInitial(StackTraceStringifier::new);
4243

4344
public static String stringifyStackTrace(Throwable throwable) {
4445
return stringifier.get().stringify(throwable);
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package com.fox2code.foxloader.launcher.utils;
2+
3+
import java.util.Objects;
4+
import java.util.function.Supplier;
5+
6+
/**
7+
* Faster implementation of {@link ThreadLocal} made to work better at low threads counts.
8+
*/
9+
public class FastThreadLocal<T> extends ThreadLocal<T> {
10+
private static final FastThreadLocalCache<?> NO_CACHE = new FastThreadLocalCache<>(null);
11+
// Java cache value per thread to improve performance.
12+
// Usually we would want to use volatile for fields accessed from multiple threads.
13+
// but for this, not using volatile is on purpose and works in our favor.
14+
private FastThreadLocalCache<T> fastThreadLocalCache;
15+
private final boolean withCustomSupplier;
16+
17+
@SuppressWarnings("unchecked")
18+
private static <T> FastThreadLocalCache<T> noCache() {
19+
return (FastThreadLocalCache<T>) NO_CACHE;
20+
}
21+
22+
public static <S> FastThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
23+
return new SuppliedFastThreadLocal<>(supplier);
24+
}
25+
26+
public FastThreadLocal() {
27+
boolean customSupplier = true;
28+
try { // Assume custom supplier if this fails
29+
customSupplier = this.getClass().getMethod("initialValue")
30+
.getDeclaringClass() != Thread.class;
31+
} catch (NoSuchMethodException ignored) {}
32+
this.withCustomSupplier = customSupplier;
33+
this.fastThreadLocalCache = customSupplier ? noCache() :
34+
new FastThreadLocalCache<>(Thread.currentThread());
35+
}
36+
37+
@Override
38+
public final T get() {
39+
final Thread thread = Thread.currentThread();
40+
final FastThreadLocalCache<T> fastThreadLocalCache = this.fastThreadLocalCache;
41+
if (fastThreadLocalCache.thread == thread)
42+
return fastThreadLocalCache.value;
43+
return (this.fastThreadLocalCache = new FastThreadLocalCache<>(thread, super.get())).value;
44+
}
45+
46+
@Override
47+
public final void set(T value) {
48+
final Thread thread = Thread.currentThread();
49+
final FastThreadLocalCache<T> fastThreadLocalCache = this.fastThreadLocalCache;
50+
if (fastThreadLocalCache.thread == thread)
51+
fastThreadLocalCache.value = value;
52+
if (value == null && !this.withCustomSupplier)
53+
super.remove();
54+
else
55+
super.set(value);
56+
}
57+
58+
@Override
59+
@SuppressWarnings("ThreadLocalSetWithNull")
60+
public final void remove() {
61+
if (this.withCustomSupplier) {
62+
// Since we use volatile for speed
63+
// and do not lock fastThreadLocalCache
64+
// we cannot remove cache conditionally
65+
// for thread safety reason
66+
this.fastThreadLocalCache = noCache();
67+
super.remove();
68+
} else this.set(null);
69+
}
70+
71+
private static class FastThreadLocalCache<T> {
72+
private final Thread thread;
73+
private T value;
74+
75+
private FastThreadLocalCache(Thread thread) {
76+
this.thread = thread;
77+
}
78+
79+
private FastThreadLocalCache(Thread thread, T value) {
80+
this.thread = thread;
81+
this.value = value;
82+
}
83+
}
84+
85+
static final class SuppliedFastThreadLocal<T> extends FastThreadLocal<T> {
86+
private final Supplier<? extends T> supplier;
87+
88+
SuppliedFastThreadLocal(Supplier<? extends T> supplier) {
89+
this.supplier = Objects.requireNonNull(supplier);
90+
}
91+
92+
@Override
93+
protected T initialValue() {
94+
return Objects.requireNonNull(supplier.get(), "Initial value cannot be null");
95+
}
96+
}
97+
}

common/src/main/java/com/fox2code/foxloader/loader/LoaderNetworkManager.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.fox2code.foxloader.loader;
22

3+
import com.fox2code.foxloader.launcher.utils.IOUtils;
4+
import com.fox2code.foxloader.launcher.utils.NetUtils;
35
import com.fox2code.foxloader.loader.packet.ClientHello;
46
import com.fox2code.foxloader.loader.packet.FoxPacket;
57
import com.fox2code.foxloader.loader.packet.ServerHello;
@@ -16,7 +18,6 @@
1618

1719
final class LoaderNetworkManager {
1820
static void executeClientPacketData(NetworkPlayer networkPlayer, byte[] data) {
19-
2021
try (DataInputStream dataInputStream =
2122
new NetworkDataInputStream(new ByteArrayInputStream(data))) {
2223
int packetId = dataInputStream.readUnsignedByte();
@@ -50,9 +51,10 @@ static void sendClientPacketData(NetworkPlayer networkPlayer, FoxPacket foxPacke
5051
}
5152

5253
static void executeServerPacketData(NetworkPlayer networkPlayer, byte[] data) {
53-
byte compressed = data[0];
5454
InputStream inputStream = new ByteArrayInputStream(data);
5555
try {
56+
int compressed = inputStream.read();
57+
ModLoader.foxLoader.logger.info("Compression: " + compressed);
5658
switch (compressed) {
5759
case 0:
5860
break;
@@ -63,14 +65,32 @@ static void executeServerPacketData(NetworkPlayer networkPlayer, byte[] data) {
6365
inputStream = new DeflaterInputStream(inputStream);
6466
break;
6567
default:
68+
ModLoader.foxLoader.logger.log(Level.WARNING, "Unknown compression: " + compressed);
6669
return;
6770
}
6871
} catch (IOException e) {
69-
ModLoader.foxLoader.logger.log(Level.WARNING, "Failed to read server packet", e);
72+
ModLoader.foxLoader.logger.log(Level.SEVERE, "Failed to read server packet", e);
7073
}
7174
try (DataInputStream dataInputStream =
7275
new NetworkDataInputStream(inputStream)) {
7376
int packetId = dataInputStream.readUnsignedByte();
77+
ModLoader.foxLoader.logger.info("PacketID: " + packetId);
78+
79+
if (packetId == 120) {
80+
StringBuilder stringBuilder = new StringBuilder();
81+
try {
82+
while (true)
83+
stringBuilder.append(Integer.toHexString(dataInputStream.readUnsignedByte())).append(" ");
84+
} catch (Exception e) {
85+
ModLoader.foxLoader.logger.info("PacketOfDeath: " + stringBuilder);
86+
stringBuilder.setLength(0);
87+
for (byte b : data) {
88+
stringBuilder.append(String.format("%02X", b));
89+
}
90+
ModLoader.foxLoader.logger.info("RAW Data: " + stringBuilder);
91+
System.exit(1);
92+
}
93+
}
7494
//noinspection SwitchStatementWithTooFewBranches
7595
switch (packetId) {
7696
case 0:
@@ -81,7 +101,9 @@ static void executeServerPacketData(NetworkPlayer networkPlayer, byte[] data) {
81101
networkPlayer, serverHello);
82102
break;
83103
}
84-
} catch (IOException ignored) {}
104+
} catch (IOException e) {
105+
ModLoader.foxLoader.logger.log(Level.SEVERE, "Failed to read server packet", e);
106+
}
85107
}
86108

87109
static void sendServerPacketData(NetworkPlayer networkPlayer, FoxPacket foxPacket) {

common/src/main/java/com/fox2code/foxloader/loader/ModContainer.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.fox2code.foxloader.loader;
22

33
import com.fox2code.foxloader.launcher.FoxLauncher;
4+
import com.fox2code.foxloader.launcher.utils.FastThreadLocal;
45
import com.fox2code.foxloader.loader.lua.LuaVMHelper;
56
import com.fox2code.foxloader.loader.packet.ClientHello;
67
import com.fox2code.foxloader.loader.transformer.PreClassTransformer;
@@ -15,11 +16,12 @@
1516
import java.nio.charset.StandardCharsets;
1617
import java.util.Objects;
1718
import java.util.Properties;
19+
import java.util.function.Function;
1820
import java.util.logging.Level;
1921
import java.util.logging.Logger;
2022

2123
public final class ModContainer {
22-
private static final ThreadLocal<ModContainer> activeModContainer = new ThreadLocal<>();
24+
private static final FastThreadLocal<ModContainer> activeModContainer = new FastThreadLocal<>();
2325
// tmp is used to make getModContainer work in constructor.
2426
static ModContainer tmp;
2527
public final File file;
@@ -61,6 +63,7 @@ public final class ModContainer {
6163
this.description = description;
6264
this.jitpack = jitpack;
6365
this.logger = Logger.getLogger(name);
66+
FoxLauncher.installLoggerHelperOn(this.logger);
6467
this.unofficial = unofficial;
6568
this.injected = injected;
6669
if (ModLoader.DEV_MODE) {
@@ -85,8 +88,22 @@ static void setActiveModContainer(ModContainer modContainer) {
8588

8689
public void runInContext(Runnable runnable) {
8790
ModContainer modContainer = markActive();
88-
runnable.run();
89-
setActiveModContainer(modContainer);
91+
try {
92+
runnable.run();
93+
} finally {
94+
setActiveModContainer(modContainer);
95+
}
96+
}
97+
98+
public <T, R> R runFuncInContext(T thing, Function<T, R> func) {
99+
ModContainer modContainer = markActive();
100+
R result;
101+
try {
102+
result = func.apply(thing);
103+
} finally {
104+
setActiveModContainer(modContainer);
105+
}
106+
return result;
90107
}
91108

92109
public Mod getClientMod() {

dev/src/main/groovy/com/fox2code/foxloader/dev/GradlePlugin.groovy

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,27 @@ class GradlePlugin implements Plugin<Project> {
365365
try {
366366
System.out.println("Decompiling patched ReIndev " + logSideName)
367367
new FoxLoaderDecompiler(unpickedJarFox, sourcesJarFox, client).decompile()
368+
} catch (OutOfMemoryError oom) {
369+
boolean deleteFailed = false
370+
try {
371+
closeJarFileSystem(unpickedJarFox)
372+
closeJarFileSystem(sourcesJarFox)
373+
} finally {
374+
if (!sourcesJarFox.delete()) {
375+
sourcesJarFox.deleteOnExit()
376+
deleteFailed = true
377+
}
378+
}
379+
Throwable root = oom
380+
while (root.getCause() != null)
381+
root = root.getCause()
382+
383+
root.initCause(deleteFailed ? // If delete failed, restart
384+
UserMessage.UNRECOVERABLE_STATE_DECOMPILE :
385+
client ? UserMessage.FAIL_DECOMPILE_CLIENT :
386+
UserMessage.FAIL_DECOMPILE_SERVER)
387+
if (deleteFailed) throw oom // If delete failed, we can't recover
388+
oom.printStackTrace()
368389
} catch (Throwable throwable) {
369390
boolean deleteFailed = false
370391
try {

final/src/main/resources/mmc/instance.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
[General]
12
InstanceType=OneSix
23
LogPrePostOutput=true
34
JoinServerOnLaunch=false
5+
IgnoreJavaCompatibility=true
46
OverrideCommands=false
57
OverrideConsole=false
68
OverrideGameTime=false

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ org.gradle.parallel=true
33
org.gradle.jvmargs=-Xmx1024m -XX:-UseGCOverheadLimit -Dfile.encoding=UTF-8
44

55
# FoxLoader properties
6-
foxloader.version=1.2.23
6+
foxloader.version=1.2.24
77
foxloader.lastReIndevTransformerChanges=1.2.22
88

99
# ReIndev properties

server/src/main/java/com/fox2code/foxloader/loader/ServerModLoader.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package com.fox2code.foxloader.loader;
22

3+
import com.fox2code.foxloader.launcher.FoxLauncher;
34
import com.fox2code.foxloader.loader.packet.ClientHello;
45
import com.fox2code.foxloader.network.NetworkPlayer;
56
import com.fox2code.foxloader.registry.CommandCompat;
67
import com.fox2code.foxloader.registry.GameRegistryServer;
78
import com.fox2code.foxloader.server.ServerCommandWrapper;
89
import com.fox2code.foxloader.server.ServerCommandWrapper4ReIndevPatches;
10+
import com.fox2code.foxloader.server.network.NetworkPlayerImpl;
911
import com.fox2code.foxloader.updater.UpdateManager;
1012
import net.minecraft.mitask.PlayerCommandHandler;
1113
import net.minecraft.server.MinecraftServer;
@@ -23,6 +25,16 @@ public static void launchModdedServer(String... args) {
2325
}
2426

2527
public static void notifyNetworkPlayerJoined(NetworkPlayer networkPlayer) {
28+
if (networkPlayer.hasFoxLoader()) {
29+
ModLoader.getModLoaderLogger().info("Starting Thread check");
30+
new Thread(() -> {
31+
try {
32+
Thread.sleep(2500);
33+
if (!((NetworkPlayerImpl) networkPlayer).hasClientHello())
34+
networkPlayer.kick("You have a broken and outdated version of FoxLoader");
35+
} catch (InterruptedException ignored) {}
36+
}, "Async - Client Hello Player Check").start();
37+
}
2638
for (ModContainer modContainer : ModLoader.modContainers.values()) {
2739
modContainer.notifyNetworkPlayerJoined(networkPlayer);
2840
}
@@ -66,6 +78,7 @@ public void onReceiveClientPacket(NetworkPlayer networkPlayer, byte[] data) {
6678

6779
@Override
6880
void loaderHandleClientHello(NetworkPlayer networkPlayer, ClientHello clientHello) {
81+
((NetworkPlayerImpl) networkPlayer).notifyClientHello();
6982
for (ModContainer modContainer : ModLoader.modContainers.values()) {
7083
modContainer.notifyNetworkPlayerHello(networkPlayer, clientHello);
7184
}

0 commit comments

Comments
 (0)