diff --git a/src/main/java/net/minecraftforge/fml/CrashReportExtender.java b/src/main/java/net/minecraftforge/fml/CrashReportExtender.java index 41ba3f694..f94301a5d 100644 --- a/src/main/java/net/minecraftforge/fml/CrashReportExtender.java +++ b/src/main/java/net/minecraftforge/fml/CrashReportExtender.java @@ -25,12 +25,13 @@ import net.minecraft.crash.CrashReportCategory; import net.minecraftforge.fml.common.ICrashCallable; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.concurrent.Callable; public class CrashReportExtender { - private static List crashCallables = new ArrayList<>(); + private static List crashCallables = Collections.synchronizedList(new ArrayList<>()); public static void enhanceCrashReport(final CrashReport crashReport, final CrashReportCategory category) { diff --git a/src/main/java/net/minecraftforge/fml/network/FMLMCRegisterPacketHandler.java b/src/main/java/net/minecraftforge/fml/network/FMLMCRegisterPacketHandler.java index 16f2cdb1a..2d83fc286 100644 --- a/src/main/java/net/minecraftforge/fml/network/FMLMCRegisterPacketHandler.java +++ b/src/main/java/net/minecraftforge/fml/network/FMLMCRegisterPacketHandler.java @@ -32,7 +32,9 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.HashSet; +import java.util.Optional; import java.util.Set; +import java.util.function.Supplier; public class FMLMCRegisterPacketHandler { public static final FMLMCRegisterPacketHandler INSTANCE = new FMLMCRegisterPacketHandler(); @@ -40,10 +42,18 @@ public class FMLMCRegisterPacketHandler { public static class ChannelList { private Set locations = new HashSet<>(); - public void updateFrom(PacketBuffer buffer) { - byte[] data = new byte[buffer.readableBytes() < 0 ? 0 : buffer.readableBytes()]; + public void updateFrom(final Supplier source, PacketBuffer buffer, final NetworkEvent.RegistrationChangeType changeType) { + byte[] data = new byte[Math.max(buffer.readableBytes(), 0)]; buffer.readBytes(data); - locations = bytesToResLocation(data); + Set oldLocations = this.locations; + this.locations = bytesToResLocation(data); + // ensure all locations receive updates, old and new. + oldLocations.addAll(this.locations); + oldLocations.stream() + .map(NetworkRegistry::findTarget) + .filter(Optional::isPresent) + .map(Optional::get) + .forEach(t->t.dispatchEvent(new NetworkEvent.ChannelRegistrationChangeEvent(source, changeType))); } byte[] toByteArray() { @@ -79,13 +89,13 @@ public class FMLMCRegisterPacketHandler { void registerListener(NetworkEvent evt) { final ChannelList channelList = getFrom(evt); - channelList.updateFrom(evt.getPayload()); + channelList.updateFrom(evt.getSource(), evt.getPayload(), NetworkEvent.RegistrationChangeType.REGISTER); evt.getSource().get().setPacketHandled(true); } void unregisterListener(NetworkEvent evt) { final ChannelList channelList = getFrom(evt); - channelList.updateFrom(evt.getPayload()); + channelList.updateFrom(evt.getSource(), evt.getPayload(), NetworkEvent.RegistrationChangeType.UNREGISTER); evt.getSource().get().setPacketHandled(true); } diff --git a/src/main/java/net/minecraftforge/fml/network/NetworkEvent.java b/src/main/java/net/minecraftforge/fml/network/NetworkEvent.java index a50a0435c..170e7bab9 100644 --- a/src/main/java/net/minecraftforge/fml/network/NetworkEvent.java +++ b/src/main/java/net/minecraftforge/fml/network/NetworkEvent.java @@ -58,6 +58,12 @@ public class NetworkEvent extends Event this.loginIndex = loginIndex; } + public NetworkEvent(final Supplier source) { + this.source = source; + this.payload = null; + this.loginIndex = -1; + } + public PacketBuffer getPayload() { return payload; @@ -122,6 +128,30 @@ public class NetworkEvent extends Event super(payload, source, loginIndex); } } + + public enum RegistrationChangeType { + REGISTER, UNREGISTER; + } + + /** + * Fired when the channel registration (see minecraft custom channel documentation) changes. Note the payload + * is not exposed. This fires to the resource location that owns the channel, when it's registration changes state. + * + * It seems plausible that this will fire multiple times for the same state, depending on what the server is doing. + * It just directly dispatches upon receipt. + */ + public static class ChannelRegistrationChangeEvent extends NetworkEvent { + private final RegistrationChangeType changeType; + + ChannelRegistrationChangeEvent(final Supplier source, RegistrationChangeType changeType) { + super(source); + this.changeType = changeType; + } + + public RegistrationChangeType getRegistrationChangeType() { + return this.changeType; + } + } /** * Context for {@link NetworkEvent} */ diff --git a/src/main/java/net/minecraftforge/fml/network/NetworkInstance.java b/src/main/java/net/minecraftforge/fml/network/NetworkInstance.java index 38456d1bb..7999a96df 100644 --- a/src/main/java/net/minecraftforge/fml/network/NetworkInstance.java +++ b/src/main/java/net/minecraftforge/fml/network/NetworkInstance.java @@ -25,9 +25,11 @@ import net.minecraftforge.eventbus.api.BusBuilder; import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.IEventListener; +import net.minecraftforge.fml.network.simple.SimpleChannel; import java.util.List; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; @@ -83,7 +85,6 @@ public class NetworkInstance return context.getPacketHandled(); } - String getNetworkProtocolVersion() { return networkProtocolVersion; } @@ -103,4 +104,8 @@ public class NetworkInstance void dispatchLoginPacket(final NetworkEvent.LoginPayloadEvent loginPayloadEvent) { this.networkEventBus.post(loginPayloadEvent); } + + void dispatchEvent(final NetworkEvent networkEvent) { + this.networkEventBus.post(networkEvent); + } }