diff --git a/libraries/networking-impl/gradle.properties b/libraries/networking-impl/gradle.properties index 1b7839883..a23f11719 100644 --- a/libraries/networking-impl/gradle.properties +++ b/libraries/networking-impl/gradle.properties @@ -6,4 +6,4 @@ library_version = 0.1.1 entrypoint_init = net.ornithemc.osl.networking.impl.Networking entrypoint_client_init = net.ornithemc.osl.networking.impl.Networking entrypoint_server_init = net.ornithemc.osl.networking.impl.Networking -osl_dependencies = core:>=0.7.0,entrypoints:>=0.5.0,lifecycle-events:>=0.6.0,networking:>=0.9.0 +osl_dependencies = core:>=0.7.0,entrypoints:>=0.5.0,lifecycle-events:>=0.6.0,executors:>=0.1.0,text-components:>=0.1.0-,networking:>=0.9.0 diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/Networking.java b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/Networking.java index 6748a0b32..dfa03a6d8 100644 --- a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/Networking.java +++ b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/Networking.java @@ -13,8 +13,11 @@ import net.ornithemc.osl.networking.api.StringChannelIdentifierParser; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; public class Networking implements ModInitializer, ClientModInitializer, ServerModInitializer { @@ -29,8 +32,11 @@ public void init() { // send channel registration data as a response to receiving client channel registration data ServerPlayNetworkingImpl.sendNoCheck(context.player(), HandshakePayload.CHANNEL, HandshakePayload.server()); - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ServerConnectionEvents.PLAY_READY.invoker().accept(context.server(), context.player()); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) context.networkHandler(); + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ServerConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } @@ -41,8 +47,11 @@ public void initClient() { ClientPlayNetworkingImpl.setUpPacketFactory((channel, data) -> new CustomPayloadC2SPacket(StringChannelIdentifierParser.toString(channel), PacketBuffers.unwrapped(data))); ClientPlayNetworkingImpl.registerListener(HandshakePayload.CHANNEL, HandshakePayload::new, (context, payload) -> { - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ClientConnectionEvents.PLAY_READY.invoker().accept(context.minecraft()); + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) context.networkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ClientConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..e067a1831 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +public interface ClientNetworkHandlerAccess extends NetworkHandlerAccess { + + ClientConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java new file mode 100644 index 000000000..1d596400b --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +public interface ServerNetworkHandlerAccess extends NetworkHandlerAccess { + + ServerConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java index ef5dbdfbb..e43da06c8 100644 --- a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java @@ -1,5 +1,6 @@ package net.ornithemc.osl.networking.impl.mixin.client; +import java.net.SocketAddress; import java.util.LinkedHashSet; import java.util.Set; @@ -13,23 +14,36 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.network.Connection; import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; +import net.minecraft.network.packet.s2c.play.DisconnectS2CPacket; +import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.text.Text; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.AddressParser; import net.ornithemc.osl.networking.impl.HandshakePayload; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ClientPlayNetworkHandler.class) -public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { +public class ClientPlayNetworkHandlerMixin implements ClientNetworkHandlerAccess { - @Shadow @Final private Minecraft minecraft; + @Shadow @Final + private Minecraft minecraft; + @Shadow @Final + private Connection connection; + @Unique + private ClientConnectionContext connectionContext; /** * Channels that the server is listening to. */ - @Unique private Set serverChannels; + @Unique + private Set serverChannels; @Inject( method = "handleLogin", @@ -38,10 +52,34 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { ) ) private void osl$networking$handleLogin(CallbackInfo ci) { + if (minecraft.isIntegratedServerRunning()) { + IntegratedServer server = minecraft.getServer(); + String worldName = server.getWorldName(); + + connectionContext = new ClientConnectionContext(minecraft, worldName); + } else { + SocketAddress address = connection.getAddress(); + + String serverAddress = AddressParser.getAddress(address); + int serverPort = AddressParser.getPort(address); + + connectionContext = new ClientConnectionContext(minecraft, serverAddress, serverPort); + } + // send channel registration data as soon as login occurs ClientPlayNetworkingImpl.sendNoCheck(HandshakePayload.CHANNEL, HandshakePayload.client()); - ClientConnectionEvents.LOGIN.invoker().accept(minecraft); + ClientConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "handleDisconnect", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(DisconnectS2CPacket packet, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(packet.getReason())); } @Inject( @@ -50,9 +88,8 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ClientConnectionEvents.DISCONNECT.invoker().accept(minecraft); - serverChannels = null; + private void osl$networking$handleDisconnect(Text reason, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(reason)); } @Inject( @@ -68,6 +105,11 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ClientConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$isPlayReady() { return serverChannels != null; diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java index 1b011d9d0..bc5386d1b 100644 --- a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java +++ b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java @@ -1,18 +1,41 @@ package net.ornithemc.osl.networking.impl.mixin.client; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import net.minecraft.client.Minecraft; -import net.minecraft.util.BlockableEventLoop; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.client.world.ClientWorld; -import net.ornithemc.osl.networking.impl.access.TaskRunnerAccess; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; @Mixin(Minecraft.class) -public abstract class MinecraftMixin implements BlockableEventLoop, TaskRunnerAccess { +public class MinecraftMixin { - @Override - public boolean osl$networking$submit(Runnable task) { - this.executeTask(task); - return true; + @Shadow + private ClientWorld world; + + @Shadow + private ClientPlayNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "setWorld(Lnet/minecraft/client/world/ClientWorld;Lnet/minecraft/client/gui/screen/Screen;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(ClientWorld world, Screen screen, CallbackInfo ci) { + if (this.world != null && world == null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } } } diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java deleted file mode 100644 index acd027e07..000000000 --- a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.ornithemc.osl.networking.impl.mixin.common; - -import org.spongepowered.asm.mixin.Mixin; - -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.BlockableEventLoop; - -import net.ornithemc.osl.networking.impl.access.TaskRunnerAccess; - -@Mixin(MinecraftServer.class) -public abstract class MinecraftServerMixin implements BlockableEventLoop, TaskRunnerAccess { - - @Override - public boolean osl$networking$submit(Runnable task) { - this.executeTask(task); - return true; - } -} diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java index e88d1f5a4..463dde8b5 100644 --- a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java +++ b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java @@ -9,13 +9,16 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import net.minecraft.network.Connection; +import com.llamalad7.mixinextras.sugar.Local; + import net.minecraft.server.MinecraftServer; import net.minecraft.server.PlayerManager; import net.minecraft.server.entity.living.player.ServerPlayerEntity; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; import net.ornithemc.osl.networking.impl.access.PlayerManagerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; @Mixin(PlayerManager.class) public class PlayerManagerMixin implements PlayerManagerAccess { @@ -29,8 +32,24 @@ public class PlayerManagerMixin implements PlayerManagerAccess { value = "TAIL" ) ) - private void osl$networking$handleLogin(Connection connection, ServerPlayerEntity player, CallbackInfo ci) { - ServerConnectionEvents.LOGIN.invoker().accept(server, player); + private void osl$networking$handleLogin(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "remove", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); } @Override diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java index ac66d4400..270f4b80b 100644 --- a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java @@ -15,22 +15,40 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.entity.living.player.ServerPlayerEntity; import net.minecraft.server.network.handler.ServerPlayNetworkHandler; +import net.minecraft.text.Text; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; -import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ServerPlayNetworkHandler.class) -public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { +public class ServerPlayNetworkHandlerMixin implements ServerNetworkHandlerAccess { - @Shadow @Final private MinecraftServer server; - @Shadow @Final private ServerPlayerEntity player; + @Shadow @Final + private MinecraftServer server; + @Shadow + private ServerPlayerEntity player; + + @Unique + private ServerConnectionContext connectionContext; /** * Channels that the client is listening to. */ - @Unique private Set clientChannels; + @Unique + private Set clientChannels; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$initConnectionContext(CallbackInfo ci) { + connectionContext = new ServerConnectionContext(server, (ServerPlayNetworkHandler) (Object) this); + } @Inject( method = "onDisconnect", @@ -38,9 +56,8 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ServerConnectionEvents.DISCONNECT.invoker().accept(server, player); - clientChannels = null; + private void osl$networking$handleDisconnect(Text reason, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(reason)); } @Inject( @@ -56,6 +73,11 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ServerConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$isPlayReady() { return clientChannels != null; diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/MinecraftServerMixin.java b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/MinecraftServerMixin.java new file mode 100644 index 000000000..3c389c76d --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/MinecraftServerMixin.java @@ -0,0 +1,42 @@ +package net.ornithemc.osl.networking.impl.mixin.server; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.PlayerManagerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + + @Shadow + private PlayerManager playerManager; + + @Inject( + method = "stop", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$stop(CallbackInfo ci) { + List players = ((PlayerManagerAccess) this.playerManager).osl$networking$getAll(); + + for (ServerPlayerEntity player : players) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/resources/fabric.mod.json b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/resources/fabric.mod.json index 0da0ddaab..738808f8f 100644 --- a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/resources/fabric.mod.json +++ b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/resources/fabric.mod.json @@ -23,6 +23,8 @@ "osl-core": "\u003e\u003d0.7.0", "osl-entrypoints": "\u003e\u003d0.5.0", "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", "osl-networking": "\u003e\u003d0.9.0" }, "name": "OSL Networking Implementation", diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/resources/osl.networking-impl.mixins.json b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/resources/osl.networking-impl.mixins.json index f64bbc230..4c0a97f4c 100644 --- a/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/resources/osl.networking-impl.mixins.json +++ b/libraries/networking-impl/networking-impl-mc1.13-pre3-mc1.13-pre3/src/main/resources/osl.networking-impl.mixins.json @@ -6,7 +6,6 @@ "mixins": [ "common.CustomPayloadC2SPacketMixin", "common.CustomPayloadS2CPacketMixin", - "common.MinecraftServerMixin", "common.PlayerManagerMixin", "common.ServerPlayNetworkHandlerMixin" ], @@ -15,6 +14,7 @@ "client.MinecraftMixin" ], "server": [ + "server.MinecraftServerMixin" ], "injectors": { "defaultRequire": 1 diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/Networking.java b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/Networking.java index 2785b5e81..9bc0ddf8f 100644 --- a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/Networking.java +++ b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/Networking.java @@ -12,8 +12,11 @@ import net.ornithemc.osl.networking.api.PacketBuffers; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; public class Networking implements ModInitializer, ClientModInitializer, ServerModInitializer { @@ -28,8 +31,11 @@ public void init() { // send channel registration data as a response to receiving client channel registration data ServerPlayNetworkingImpl.sendNoCheck(context.player(), HandshakePayload.CHANNEL, HandshakePayload.server()); - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ServerConnectionEvents.PLAY_READY.invoker().accept(context.server(), context.player()); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) context.networkHandler(); + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ServerConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } @@ -40,8 +46,11 @@ public void initClient() { ClientPlayNetworkingImpl.setUpPacketFactory((channel, data) -> new CustomPayloadC2SPacket(IdentifierChannelIdentifierParser.toIdentifier(channel), PacketBuffers.unwrapped(data))); ClientPlayNetworkingImpl.registerListener(HandshakePayload.CHANNEL, HandshakePayload::new, (context, payload) -> { - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ClientConnectionEvents.PLAY_READY.invoker().accept(context.minecraft()); + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) context.networkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ClientConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/NetworkingMixinPlugin.java b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/NetworkingMixinPlugin.java new file mode 100644 index 000000000..608aea8ba --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/NetworkingMixinPlugin.java @@ -0,0 +1,54 @@ +package net.ornithemc.osl.networking.impl; + +import java.util.List; +import java.util.Set; + +import org.objectweb.asm.tree.ClassNode; + +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import net.ornithemc.osl.core.impl.util.MinecraftVersion; + +public class NetworkingMixinPlugin implements IMixinConfigPlugin { + + public static final boolean MINECRAFT_SET_WORLD_HAS_NETWORK_ID_PARAMETER = MinecraftVersion.resolve().compareTo("18w30b") == 0; + + @Override + public void onLoad(String mixinPackage) { + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if ("net.ornithemc.osl.networking.impl.mixin.client.MinecraftMixin".equals(mixinClassName)) { + return !MINECRAFT_SET_WORLD_HAS_NETWORK_ID_PARAMETER; + } + if ("net.ornithemc.osl.networking.impl.mixin.client.MinecraftMixin18w30b".equals(mixinClassName)) { + return MINECRAFT_SET_WORLD_HAS_NETWORK_ID_PARAMETER; + } + + return true; + } + + @Override + public void acceptTargets(Set myTargets, Set otherTargets) { + } + + @Override + public List getMixins() { + return null; + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } +} diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..e067a1831 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +public interface ClientNetworkHandlerAccess extends NetworkHandlerAccess { + + ClientConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java new file mode 100644 index 000000000..1d596400b --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +public interface ServerNetworkHandlerAccess extends NetworkHandlerAccess { + + ServerConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java index ef5dbdfbb..e43da06c8 100644 --- a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java @@ -1,5 +1,6 @@ package net.ornithemc.osl.networking.impl.mixin.client; +import java.net.SocketAddress; import java.util.LinkedHashSet; import java.util.Set; @@ -13,23 +14,36 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.network.Connection; import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; +import net.minecraft.network.packet.s2c.play.DisconnectS2CPacket; +import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.text.Text; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.AddressParser; import net.ornithemc.osl.networking.impl.HandshakePayload; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ClientPlayNetworkHandler.class) -public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { +public class ClientPlayNetworkHandlerMixin implements ClientNetworkHandlerAccess { - @Shadow @Final private Minecraft minecraft; + @Shadow @Final + private Minecraft minecraft; + @Shadow @Final + private Connection connection; + @Unique + private ClientConnectionContext connectionContext; /** * Channels that the server is listening to. */ - @Unique private Set serverChannels; + @Unique + private Set serverChannels; @Inject( method = "handleLogin", @@ -38,10 +52,34 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { ) ) private void osl$networking$handleLogin(CallbackInfo ci) { + if (minecraft.isIntegratedServerRunning()) { + IntegratedServer server = minecraft.getServer(); + String worldName = server.getWorldName(); + + connectionContext = new ClientConnectionContext(minecraft, worldName); + } else { + SocketAddress address = connection.getAddress(); + + String serverAddress = AddressParser.getAddress(address); + int serverPort = AddressParser.getPort(address); + + connectionContext = new ClientConnectionContext(minecraft, serverAddress, serverPort); + } + // send channel registration data as soon as login occurs ClientPlayNetworkingImpl.sendNoCheck(HandshakePayload.CHANNEL, HandshakePayload.client()); - ClientConnectionEvents.LOGIN.invoker().accept(minecraft); + ClientConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "handleDisconnect", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(DisconnectS2CPacket packet, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(packet.getReason())); } @Inject( @@ -50,9 +88,8 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ClientConnectionEvents.DISCONNECT.invoker().accept(minecraft); - serverChannels = null; + private void osl$networking$handleDisconnect(Text reason, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(reason)); } @Inject( @@ -68,6 +105,11 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ClientConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$isPlayReady() { return serverChannels != null; diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java index 1b011d9d0..bc5386d1b 100644 --- a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java +++ b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java @@ -1,18 +1,41 @@ package net.ornithemc.osl.networking.impl.mixin.client; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import net.minecraft.client.Minecraft; -import net.minecraft.util.BlockableEventLoop; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.client.world.ClientWorld; -import net.ornithemc.osl.networking.impl.access.TaskRunnerAccess; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; @Mixin(Minecraft.class) -public abstract class MinecraftMixin implements BlockableEventLoop, TaskRunnerAccess { +public class MinecraftMixin { - @Override - public boolean osl$networking$submit(Runnable task) { - this.executeTask(task); - return true; + @Shadow + private ClientWorld world; + + @Shadow + private ClientPlayNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "setWorld(Lnet/minecraft/client/world/ClientWorld;Lnet/minecraft/client/gui/screen/Screen;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(ClientWorld world, Screen screen, CallbackInfo ci) { + if (this.world != null && world == null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } } } diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin18w30b.java b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin18w30b.java new file mode 100644 index 000000000..e0d53ec6b --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin18w30b.java @@ -0,0 +1,41 @@ +package net.ornithemc.osl.networking.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.client.world.ClientWorld; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +@Mixin(Minecraft.class) +public class MinecraftMixin18w30b { + + @Shadow + private ClientWorld world; + + @Shadow + private ClientPlayNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "m_62116716", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(ClientWorld world, Screen screen, int networkId, CallbackInfo ci) { + if (this.world != null && world == null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java deleted file mode 100644 index acd027e07..000000000 --- a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.ornithemc.osl.networking.impl.mixin.common; - -import org.spongepowered.asm.mixin.Mixin; - -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.BlockableEventLoop; - -import net.ornithemc.osl.networking.impl.access.TaskRunnerAccess; - -@Mixin(MinecraftServer.class) -public abstract class MinecraftServerMixin implements BlockableEventLoop, TaskRunnerAccess { - - @Override - public boolean osl$networking$submit(Runnable task) { - this.executeTask(task); - return true; - } -} diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java index e88d1f5a4..463dde8b5 100644 --- a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java +++ b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java @@ -9,13 +9,16 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import net.minecraft.network.Connection; +import com.llamalad7.mixinextras.sugar.Local; + import net.minecraft.server.MinecraftServer; import net.minecraft.server.PlayerManager; import net.minecraft.server.entity.living.player.ServerPlayerEntity; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; import net.ornithemc.osl.networking.impl.access.PlayerManagerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; @Mixin(PlayerManager.class) public class PlayerManagerMixin implements PlayerManagerAccess { @@ -29,8 +32,24 @@ public class PlayerManagerMixin implements PlayerManagerAccess { value = "TAIL" ) ) - private void osl$networking$handleLogin(Connection connection, ServerPlayerEntity player, CallbackInfo ci) { - ServerConnectionEvents.LOGIN.invoker().accept(server, player); + private void osl$networking$handleLogin(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "remove", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); } @Override diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java index ac66d4400..270f4b80b 100644 --- a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java @@ -15,22 +15,40 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.entity.living.player.ServerPlayerEntity; import net.minecraft.server.network.handler.ServerPlayNetworkHandler; +import net.minecraft.text.Text; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; -import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ServerPlayNetworkHandler.class) -public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { +public class ServerPlayNetworkHandlerMixin implements ServerNetworkHandlerAccess { - @Shadow @Final private MinecraftServer server; - @Shadow @Final private ServerPlayerEntity player; + @Shadow @Final + private MinecraftServer server; + @Shadow + private ServerPlayerEntity player; + + @Unique + private ServerConnectionContext connectionContext; /** * Channels that the client is listening to. */ - @Unique private Set clientChannels; + @Unique + private Set clientChannels; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$initConnectionContext(CallbackInfo ci) { + connectionContext = new ServerConnectionContext(server, (ServerPlayNetworkHandler) (Object) this); + } @Inject( method = "onDisconnect", @@ -38,9 +56,8 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ServerConnectionEvents.DISCONNECT.invoker().accept(server, player); - clientChannels = null; + private void osl$networking$handleDisconnect(Text reason, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(reason)); } @Inject( @@ -56,6 +73,11 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ServerConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$isPlayReady() { return clientChannels != null; diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/MinecraftServerMixin.java b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/MinecraftServerMixin.java new file mode 100644 index 000000000..3c389c76d --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/MinecraftServerMixin.java @@ -0,0 +1,42 @@ +package net.ornithemc.osl.networking.impl.mixin.server; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.PlayerManagerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + + @Shadow + private PlayerManager playerManager; + + @Inject( + method = "stop", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$stop(CallbackInfo ci) { + List players = ((PlayerManagerAccess) this.playerManager).osl$networking$getAll(); + + for (ServerPlayerEntity player : players) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/resources/fabric.mod.json b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/resources/fabric.mod.json index 82188a844..89358be75 100644 --- a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/resources/fabric.mod.json +++ b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/resources/fabric.mod.json @@ -23,6 +23,8 @@ "osl-core": "\u003e\u003d0.7.0", "osl-entrypoints": "\u003e\u003d0.5.0", "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", "osl-networking": "\u003e\u003d0.9.0" }, "name": "OSL Networking Implementation", diff --git a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/resources/osl.networking-impl.mixins.json b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/resources/osl.networking-impl.mixins.json index f64bbc230..a8084bf89 100644 --- a/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/resources/osl.networking-impl.mixins.json +++ b/libraries/networking-impl/networking-impl-mc1.13-pre4-mc1.13.2/src/main/resources/osl.networking-impl.mixins.json @@ -3,18 +3,20 @@ "minVersion": "0.8", "package": "net.ornithemc.osl.networking.impl.mixin", "compatibilityLevel": "JAVA_8", + "plugin": "net.ornithemc.osl.networking.impl.NetworkingMixinPlugin", "mixins": [ "common.CustomPayloadC2SPacketMixin", "common.CustomPayloadS2CPacketMixin", - "common.MinecraftServerMixin", "common.PlayerManagerMixin", "common.ServerPlayNetworkHandlerMixin" ], "client": [ "client.ClientPlayNetworkHandlerMixin", - "client.MinecraftMixin" + "client.MinecraftMixin", + "client.MinecraftMixin18w30b" ], "server": [ + "server.MinecraftServerMixin" ], "injectors": { "defaultRequire": 1 diff --git a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java index 08410b9eb..89ea1e8c0 100644 --- a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java +++ b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java @@ -1,6 +1,7 @@ package net.ornithemc.osl.networking.impl; import net.minecraft.network.packet.CustomPayloadPacket; + import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.entrypoints.api.ModInitializer; import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; @@ -10,8 +11,11 @@ import net.ornithemc.osl.networking.api.StringChannelIdentifierParser; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; public class Networking implements ModInitializer, ClientModInitializer, ServerModInitializer { @@ -27,8 +31,11 @@ public void initClient() { MinecraftClientEvents.STOP.register(ClientPlayNetworkingImpl::destroy); ClientPlayNetworkingImpl.setUpPacketFactory(Networking::newCustomPayloadPacket); ClientPlayNetworkingImpl.registerListener(HandshakePayload.CHANNEL, HandshakePayload::new, (context, payload) -> { - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ClientConnectionEvents.PLAY_READY.invoker().accept(context.minecraft()); + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) context.networkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ClientConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } @@ -41,8 +48,11 @@ public void initServer() { // send channel registration data as a response to receiving client channel registration data ServerPlayNetworkingImpl.sendNoCheck(context.player(), HandshakePayload.CHANNEL, HandshakePayload.server()); - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ServerConnectionEvents.PLAY_READY.invoker().accept(context.server(), context.player()); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) context.networkHandler(); + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ServerConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } diff --git a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..e067a1831 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +public interface ClientNetworkHandlerAccess extends NetworkHandlerAccess { + + ClientConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java similarity index 58% rename from libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java rename to libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java index 47f751c13..995b11495 100644 --- a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java +++ b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java @@ -1,8 +1,8 @@ -package net.ornithemc.osl.networking.impl.interfaces.mixin; +package net.ornithemc.osl.networking.impl.access; import net.minecraft.network.packet.CustomPayloadPacket; -public interface INetworkHandler { +public interface PacketHandlerAccess { boolean osl$networking$handleCustomPayload(CustomPayloadPacket packet); diff --git a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java new file mode 100644 index 000000000..1d596400b --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +public interface ServerNetworkHandlerAccess extends NetworkHandlerAccess { + + ServerConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java index 6faff580f..83a73afb9 100644 --- a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java @@ -1,8 +1,10 @@ package net.ornithemc.osl.networking.impl.mixin.client; +import java.net.SocketAddress; import java.util.LinkedHashSet; import java.util.Set; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -13,25 +15,37 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.network.handler.ClientNetworkHandler; import net.minecraft.client.world.MultiplayerWorld; +import net.minecraft.network.Connection; import net.minecraft.network.packet.CustomPayloadPacket; +import net.minecraft.network.packet.DisconnectPacket; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.AddressParser; import net.ornithemc.osl.networking.impl.HandshakePayload; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ClientNetworkHandler.class) -public class ClientNetworkHandlerMixin implements NetworkHandlerAccess, INetworkHandler { +public class ClientNetworkHandlerMixin implements ClientNetworkHandlerAccess, PacketHandlerAccess { - @Shadow private Minecraft minecraft; - @Shadow private MultiplayerWorld world; + @Shadow @Final + private Minecraft minecraft; + @Shadow @Final + private MultiplayerWorld world; + @Shadow @Final + private Connection connection; + @Unique + private ClientConnectionContext connectionContext; /** * Channels that the server is listening to. */ - @Unique private Set serverChannels; + @Unique + private Set serverChannels; @Inject( method = "handleLogin", @@ -40,10 +54,29 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess, INetwork ) ) private void osl$networking$handleLogin(CallbackInfo ci) { + { + SocketAddress address = connection.socket.getRemoteSocketAddress(); + + String serverAddress = AddressParser.getAddress(address); + int serverPort = AddressParser.getPort(address); + + connectionContext = new ClientConnectionContext(minecraft, serverAddress, serverPort); + } + // send channel registration data as soon as login occurs ClientPlayNetworkingImpl.sendNoCheck(HandshakePayload.CHANNEL, HandshakePayload.client()); - ClientConnectionEvents.LOGIN.invoker().accept(minecraft); + ClientConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "handleDisconnect", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(DisconnectPacket packet, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(packet.reason)); } @Inject( @@ -52,9 +85,15 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess, INetwork value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ClientConnectionEvents.DISCONNECT.invoker().accept(minecraft); - serverChannels = null; + private void osl$networking$handleDisconnect(String reason, Object[] args, CallbackInfo ci) { + connectionContext.offerDisconnectReason(args == null + ? TextComponents.translatable(reason) + : TextComponents.translatable(reason, args)); + } + + @Override + public ClientConnectionContext osl$networking$connectionContext() { + return connectionContext; } @Override diff --git a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java new file mode 100644 index 000000000..6600fd992 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java @@ -0,0 +1,41 @@ +package net.ornithemc.osl.networking.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.handler.ClientNetworkHandler; +import net.minecraft.client.world.MultiplayerWorld; +import net.minecraft.world.World; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +@Mixin(Minecraft.class) +public class MinecraftMixin { + + @Shadow + private World world; + + @Shadow + private ClientNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "setWorld(Lnet/minecraft/world/World;Ljava/lang/String;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(World world, String title, CallbackInfo ci) { + if (this.world != null && this.world instanceof MultiplayerWorld && world == null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PacketHandlerMixin.java b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PacketHandlerMixin.java index 310e1e828..1b5d4a108 100644 --- a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PacketHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PacketHandlerMixin.java @@ -8,7 +8,7 @@ import net.minecraft.network.PacketHandler; import net.minecraft.network.packet.CustomPayloadPacket; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; @Mixin(PacketHandler.class) public class PacketHandlerMixin { @@ -21,7 +21,7 @@ public class PacketHandlerMixin { ) ) private void osl$networking$handleCustomPayload(CustomPayloadPacket packet, CallbackInfo ci) { - if (this instanceof INetworkHandler && ((INetworkHandler)this).osl$networking$handleCustomPayload(packet)) { + if (this instanceof PacketHandlerAccess && ((PacketHandlerAccess) this).osl$networking$handleCustomPayload(packet)) { ci.cancel(); } } diff --git a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/PlayerManagerMixin.java b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/PlayerManagerMixin.java new file mode 100644 index 000000000..445e1c415 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/PlayerManagerMixin.java @@ -0,0 +1,37 @@ +package net.ornithemc.osl.networking.impl.mixin.server; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.mob.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final private MinecraftServer server; + + @Inject( + method = "remove", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } +} diff --git a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java index bf2aedb71..0b2b70524 100644 --- a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java @@ -14,6 +14,8 @@ import net.minecraft.server.network.handler.ServerLoginNetworkHandler; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; @Mixin(ServerLoginNetworkHandler.class) public class ServerLoginNetworkHandlerMixin { @@ -28,7 +30,10 @@ public class ServerLoginNetworkHandlerMixin { ) private void osl$networking$handleLogin(CallbackInfo ci, @Local ServerPlayerEntity player) { if (player != null) { - ServerConnectionEvents.LOGIN.invoker().accept(server, player); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.LOGIN.invoker().accept(connectionContext); } } } diff --git a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java index fd9e42b45..6ce6f6eed 100644 --- a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java @@ -3,6 +3,7 @@ import java.util.LinkedHashSet; import java.util.Set; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -11,26 +12,54 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import net.minecraft.network.packet.CustomPayloadPacket; +import net.minecraft.network.packet.DisconnectPacket; import net.minecraft.server.MinecraftServer; import net.minecraft.server.entity.mob.player.ServerPlayerEntity; import net.minecraft.server.network.handler.ServerPlayNetworkHandler; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; -import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ServerPlayNetworkHandler.class) -public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess, INetworkHandler { +public class ServerPlayNetworkHandlerMixin implements ServerNetworkHandlerAccess, PacketHandlerAccess { - @Shadow private MinecraftServer server; - @Shadow private ServerPlayerEntity player; + @Shadow @Final + private MinecraftServer server; + @Shadow + private ServerPlayerEntity player; + + @Unique + private ServerConnectionContext connectionContext; /** * Channels that the client is listening to. */ - @Unique private Set clientChannels; + @Unique + private Set clientChannels; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$initConnectionContext(CallbackInfo ci) { + connectionContext = new ServerConnectionContext(server, (ServerPlayNetworkHandler) (Object) this); + } + + @Inject( + method = "handleDisconnect", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(DisconnectPacket packet, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(packet.reason)); + } @Inject( method = "onDisconnect", @@ -38,9 +67,15 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess, INet value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ServerConnectionEvents.DISCONNECT.invoker().accept(server, player); - clientChannels = null; + private void osl$networking$handleDisconnect(String reason, Object[] args, CallbackInfo ci) { + connectionContext.offerDisconnectReason(args == null + ? TextComponents.translatable(reason) + : TextComponents.translatable(reason, args)); + } + + @Override + public ServerConnectionContext osl$networking$connectionContext() { + return connectionContext; } @Override diff --git a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/resources/fabric.mod.json b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/resources/fabric.mod.json index 225ab3c44..7309aa67e 100644 --- a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/resources/fabric.mod.json +++ b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/resources/fabric.mod.json @@ -23,6 +23,8 @@ "osl-core": "\u003e\u003d0.7.0", "osl-entrypoints": "\u003e\u003d0.5.0", "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", "osl-networking": "\u003e\u003d0.9.0" }, "name": "OSL Networking Implementation", diff --git a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/resources/osl.networking-impl.classtweaker b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/resources/osl.networking-impl.classtweaker new file mode 100644 index 000000000..938816a7d --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/resources/osl.networking-impl.classtweaker @@ -0,0 +1,3 @@ +classTweaker v1 named + +accessible field net/minecraft/network/Connection socket Ljava/net/Socket; \ No newline at end of file diff --git a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/resources/osl.networking-impl.mixins.json b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/resources/osl.networking-impl.mixins.json index b8b717774..4799bb11e 100644 --- a/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/resources/osl.networking-impl.mixins.json +++ b/libraries/networking-impl/networking-impl-mc11w49a-mc12w16a/src/main/resources/osl.networking-impl.mixins.json @@ -9,9 +9,11 @@ "common.PacketHandlerMixin" ], "client": [ - "client.ClientNetworkHandlerMixin" + "client.ClientNetworkHandlerMixin", + "client.MinecraftMixin" ], "server": [ + "server.PlayerManagerMixin", "server.ServerLoginNetworkHandlerMixin", "server.ServerPlayNetworkHandlerMixin" ], diff --git a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java index 68d5629c9..89ea1e8c0 100644 --- a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java +++ b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java @@ -11,8 +11,11 @@ import net.ornithemc.osl.networking.api.StringChannelIdentifierParser; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; public class Networking implements ModInitializer, ClientModInitializer, ServerModInitializer { @@ -28,8 +31,11 @@ public void initClient() { MinecraftClientEvents.STOP.register(ClientPlayNetworkingImpl::destroy); ClientPlayNetworkingImpl.setUpPacketFactory(Networking::newCustomPayloadPacket); ClientPlayNetworkingImpl.registerListener(HandshakePayload.CHANNEL, HandshakePayload::new, (context, payload) -> { - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ClientConnectionEvents.PLAY_READY.invoker().accept(context.minecraft()); + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) context.networkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ClientConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } @@ -42,8 +48,11 @@ public void initServer() { // send channel registration data as a response to receiving client channel registration data ServerPlayNetworkingImpl.sendNoCheck(context.player(), HandshakePayload.CHANNEL, HandshakePayload.server()); - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ServerConnectionEvents.PLAY_READY.invoker().accept(context.server(), context.player()); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) context.networkHandler(); + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ServerConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } diff --git a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..e067a1831 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +public interface ClientNetworkHandlerAccess extends NetworkHandlerAccess { + + ClientConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java similarity index 58% rename from libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java rename to libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java index 47f751c13..995b11495 100644 --- a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java +++ b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java @@ -1,8 +1,8 @@ -package net.ornithemc.osl.networking.impl.interfaces.mixin; +package net.ornithemc.osl.networking.impl.access; import net.minecraft.network.packet.CustomPayloadPacket; -public interface INetworkHandler { +public interface PacketHandlerAccess { boolean osl$networking$handleCustomPayload(CustomPayloadPacket packet); diff --git a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java new file mode 100644 index 000000000..1d596400b --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +public interface ServerNetworkHandlerAccess extends NetworkHandlerAccess { + + ServerConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java index 6faff580f..83a73afb9 100644 --- a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java @@ -1,8 +1,10 @@ package net.ornithemc.osl.networking.impl.mixin.client; +import java.net.SocketAddress; import java.util.LinkedHashSet; import java.util.Set; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -13,25 +15,37 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.network.handler.ClientNetworkHandler; import net.minecraft.client.world.MultiplayerWorld; +import net.minecraft.network.Connection; import net.minecraft.network.packet.CustomPayloadPacket; +import net.minecraft.network.packet.DisconnectPacket; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.AddressParser; import net.ornithemc.osl.networking.impl.HandshakePayload; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ClientNetworkHandler.class) -public class ClientNetworkHandlerMixin implements NetworkHandlerAccess, INetworkHandler { +public class ClientNetworkHandlerMixin implements ClientNetworkHandlerAccess, PacketHandlerAccess { - @Shadow private Minecraft minecraft; - @Shadow private MultiplayerWorld world; + @Shadow @Final + private Minecraft minecraft; + @Shadow @Final + private MultiplayerWorld world; + @Shadow @Final + private Connection connection; + @Unique + private ClientConnectionContext connectionContext; /** * Channels that the server is listening to. */ - @Unique private Set serverChannels; + @Unique + private Set serverChannels; @Inject( method = "handleLogin", @@ -40,10 +54,29 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess, INetwork ) ) private void osl$networking$handleLogin(CallbackInfo ci) { + { + SocketAddress address = connection.socket.getRemoteSocketAddress(); + + String serverAddress = AddressParser.getAddress(address); + int serverPort = AddressParser.getPort(address); + + connectionContext = new ClientConnectionContext(minecraft, serverAddress, serverPort); + } + // send channel registration data as soon as login occurs ClientPlayNetworkingImpl.sendNoCheck(HandshakePayload.CHANNEL, HandshakePayload.client()); - ClientConnectionEvents.LOGIN.invoker().accept(minecraft); + ClientConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "handleDisconnect", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(DisconnectPacket packet, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(packet.reason)); } @Inject( @@ -52,9 +85,15 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess, INetwork value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ClientConnectionEvents.DISCONNECT.invoker().accept(minecraft); - serverChannels = null; + private void osl$networking$handleDisconnect(String reason, Object[] args, CallbackInfo ci) { + connectionContext.offerDisconnectReason(args == null + ? TextComponents.translatable(reason) + : TextComponents.translatable(reason, args)); + } + + @Override + public ClientConnectionContext osl$networking$connectionContext() { + return connectionContext; } @Override diff --git a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java new file mode 100644 index 000000000..6600fd992 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java @@ -0,0 +1,41 @@ +package net.ornithemc.osl.networking.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.handler.ClientNetworkHandler; +import net.minecraft.client.world.MultiplayerWorld; +import net.minecraft.world.World; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +@Mixin(Minecraft.class) +public class MinecraftMixin { + + @Shadow + private World world; + + @Shadow + private ClientNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "setWorld(Lnet/minecraft/world/World;Ljava/lang/String;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(World world, String title, CallbackInfo ci) { + if (this.world != null && this.world instanceof MultiplayerWorld && world == null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PacketHandlerMixin.java b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PacketHandlerMixin.java index 310e1e828..1b5d4a108 100644 --- a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PacketHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PacketHandlerMixin.java @@ -8,7 +8,7 @@ import net.minecraft.network.PacketHandler; import net.minecraft.network.packet.CustomPayloadPacket; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; @Mixin(PacketHandler.class) public class PacketHandlerMixin { @@ -21,7 +21,7 @@ public class PacketHandlerMixin { ) ) private void osl$networking$handleCustomPayload(CustomPayloadPacket packet, CallbackInfo ci) { - if (this instanceof INetworkHandler && ((INetworkHandler)this).osl$networking$handleCustomPayload(packet)) { + if (this instanceof PacketHandlerAccess && ((PacketHandlerAccess) this).osl$networking$handleCustomPayload(packet)) { ci.cancel(); } } diff --git a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/PlayerManagerMixin.java b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/PlayerManagerMixin.java new file mode 100644 index 000000000..445e1c415 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/PlayerManagerMixin.java @@ -0,0 +1,37 @@ +package net.ornithemc.osl.networking.impl.mixin.server; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.mob.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final private MinecraftServer server; + + @Inject( + method = "remove", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } +} diff --git a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java index bf2aedb71..0b2b70524 100644 --- a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java @@ -14,6 +14,8 @@ import net.minecraft.server.network.handler.ServerLoginNetworkHandler; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; @Mixin(ServerLoginNetworkHandler.class) public class ServerLoginNetworkHandlerMixin { @@ -28,7 +30,10 @@ public class ServerLoginNetworkHandlerMixin { ) private void osl$networking$handleLogin(CallbackInfo ci, @Local ServerPlayerEntity player) { if (player != null) { - ServerConnectionEvents.LOGIN.invoker().accept(server, player); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.LOGIN.invoker().accept(connectionContext); } } } diff --git a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java index a07c8490c..9b1e6ce46 100644 --- a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java @@ -3,6 +3,7 @@ import java.util.LinkedHashSet; import java.util.Set; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -16,21 +17,38 @@ import net.minecraft.server.network.handler.ServerPlayNetworkHandler; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; -import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ServerPlayNetworkHandler.class) -public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess, INetworkHandler { +public class ServerPlayNetworkHandlerMixin implements ServerNetworkHandlerAccess, PacketHandlerAccess { - @Shadow private MinecraftServer server; - @Shadow private ServerPlayerEntity player; + @Shadow @Final + private MinecraftServer server; + @Shadow + private ServerPlayerEntity player; + + @Unique + private ServerConnectionContext connectionContext; /** * Channels that the client is listening to. */ - @Unique private Set clientChannels; + @Unique + private Set clientChannels; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$initConnectionContext(CallbackInfo ci) { + connectionContext = new ServerConnectionContext(server, (ServerPlayNetworkHandler) (Object) this); + } @Inject( method = "onDisconnect", @@ -38,9 +56,10 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess, INet value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ServerConnectionEvents.DISCONNECT.invoker().accept(server, player); - clientChannels = null; + private void osl$networking$handleDisconnect(String reason, Object[] args, CallbackInfo ci) { + connectionContext.offerDisconnectReason(args == null + ? TextComponents.translatable(reason) + : TextComponents.translatable(reason, args)); } @Inject( @@ -56,6 +75,11 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess, INet } } + @Override + public ServerConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$canRunOffMainThread() { return true; diff --git a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/resources/fabric.mod.json b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/resources/fabric.mod.json index 15de3ea6f..f240f699f 100644 --- a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/resources/fabric.mod.json +++ b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/resources/fabric.mod.json @@ -23,6 +23,8 @@ "osl-core": "\u003e\u003d0.7.0", "osl-entrypoints": "\u003e\u003d0.5.0", "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", "osl-networking": "\u003e\u003d0.9.0" }, "name": "OSL Networking Implementation", diff --git a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/resources/osl.networking-impl.classtweaker b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/resources/osl.networking-impl.classtweaker new file mode 100644 index 000000000..938816a7d --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/resources/osl.networking-impl.classtweaker @@ -0,0 +1,3 @@ +classTweaker v1 named + +accessible field net/minecraft/network/Connection socket Ljava/net/Socket; \ No newline at end of file diff --git a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/resources/osl.networking-impl.mixins.json b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/resources/osl.networking-impl.mixins.json index b8b717774..4799bb11e 100644 --- a/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/resources/osl.networking-impl.mixins.json +++ b/libraries/networking-impl/networking-impl-mc12w17a-mc12w17a/src/main/resources/osl.networking-impl.mixins.json @@ -9,9 +9,11 @@ "common.PacketHandlerMixin" ], "client": [ - "client.ClientNetworkHandlerMixin" + "client.ClientNetworkHandlerMixin", + "client.MinecraftMixin" ], "server": [ + "server.PlayerManagerMixin", "server.ServerLoginNetworkHandlerMixin", "server.ServerPlayNetworkHandlerMixin" ], diff --git a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java index f97e0a068..77c8c0396 100644 --- a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java +++ b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java @@ -11,8 +11,11 @@ import net.ornithemc.osl.networking.api.StringChannelIdentifierParser; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; public class Networking implements ModInitializer, ClientModInitializer, ServerModInitializer { @@ -26,8 +29,11 @@ public void init() { // send channel registration data as a response to receiving client channel registration data ServerPlayNetworkingImpl.sendNoCheck(context.player(), HandshakePayload.CHANNEL, HandshakePayload.server()); - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ServerConnectionEvents.PLAY_READY.invoker().accept(context.server(), context.player()); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) context.networkHandler(); + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ServerConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } @@ -37,8 +43,11 @@ public void initClient() { MinecraftClientEvents.STOP.register(ClientPlayNetworkingImpl::destroy); ClientPlayNetworkingImpl.setUpPacketFactory(Networking::newCustomPayloadPacket); ClientPlayNetworkingImpl.registerListener(HandshakePayload.CHANNEL, HandshakePayload::new, (context, payload) -> { - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ClientConnectionEvents.PLAY_READY.invoker().accept(context.minecraft()); + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) context.networkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ClientConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } diff --git a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..e067a1831 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +public interface ClientNetworkHandlerAccess extends NetworkHandlerAccess { + + ClientConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/access/LocalServerAccess.java b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/access/LocalServerAccess.java new file mode 100644 index 000000000..2537236c8 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/access/LocalServerAccess.java @@ -0,0 +1,7 @@ +package net.ornithemc.osl.networking.impl.access; + +public interface LocalServerAccess { + + String osl$networking$worldSaveName(); + +} diff --git a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java new file mode 100644 index 000000000..1d596400b --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +public interface ServerNetworkHandlerAccess extends NetworkHandlerAccess { + + ServerConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java index a5a8a07b2..d61a44207 100644 --- a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java @@ -1,8 +1,10 @@ package net.ornithemc.osl.networking.impl.mixin.client; +import java.net.SocketAddress; import java.util.LinkedHashSet; import java.util.Set; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -13,24 +15,37 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.network.handler.ClientNetworkHandler; import net.minecraft.client.world.ClientWorld; +import net.minecraft.network.Connection; import net.minecraft.network.packet.CustomPayloadPacket; +import net.minecraft.network.packet.DisconnectPacket; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.AddressParser; import net.ornithemc.osl.networking.impl.HandshakePayload; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.networking.impl.access.LocalServerAccess; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ClientNetworkHandler.class) -public class ClientNetworkHandlerMixin implements NetworkHandlerAccess { +public class ClientNetworkHandlerMixin implements ClientNetworkHandlerAccess { - @Shadow private Minecraft minecraft; - @Shadow private ClientWorld world; + @Shadow @Final + private Minecraft minecraft; + @Shadow @Final + private ClientWorld world; + @Shadow @Final + private Connection connection; + @Unique + private ClientConnectionContext connectionContext; /** * Channels that the server is listening to. */ - @Unique private Set serverChannels; + @Unique + private Set serverChannels; @Inject( method = "handleLogin", @@ -39,10 +54,34 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess { ) ) private void osl$networking$handleLogin(CallbackInfo ci) { + if (minecraft.getLocalServer().isRunning()) { + LocalServerAccess server = (LocalServerAccess) minecraft.getLocalServer(); + String worldName = server.osl$networking$worldSaveName(); + + connectionContext = new ClientConnectionContext(minecraft, worldName); + } else { + SocketAddress address = connection.getAddress(); + + String serverAddress = AddressParser.getAddress(address); + int serverPort = AddressParser.getPort(address); + + connectionContext = new ClientConnectionContext(minecraft, serverAddress, serverPort); + } + // send channel registration data as soon as login occurs ClientPlayNetworkingImpl.sendNoCheck(HandshakePayload.CHANNEL, HandshakePayload.client()); - ClientConnectionEvents.LOGIN.invoker().accept(minecraft); + ClientConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "handleDisconnect", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(DisconnectPacket packet, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(packet.reason)); } @Inject( @@ -51,9 +90,10 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ClientConnectionEvents.DISCONNECT.invoker().accept(minecraft); - serverChannels = null; + private void osl$networking$handleDisconnect(String reason, Object[] args, CallbackInfo ci) { + connectionContext.offerDisconnectReason(args == null + ? TextComponents.translatable(reason) + : TextComponents.translatable(reason, args)); } @Inject( @@ -69,6 +109,11 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ClientConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$canRunOffMainThread() { return minecraft != null && minecraft.world != null && minecraft.player != null && world != null; diff --git a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/LocalServerMixin.java b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/LocalServerMixin.java new file mode 100644 index 000000000..12b4690c4 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/LocalServerMixin.java @@ -0,0 +1,35 @@ +package net.ornithemc.osl.networking.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.client.server.LocalServer; + +import net.ornithemc.osl.networking.impl.access.LocalServerAccess; + +@Mixin(LocalServer.class) +public class LocalServerMixin implements LocalServerAccess { + + @Unique + private String worldSaveName; + + @Inject( + method = "start", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$start(CallbackInfo ci, @Local String worldSaveName) { + this.worldSaveName = worldSaveName; + } + + @Override + public String osl$networking$worldSaveName() { + return this.worldSaveName; + } +} diff --git a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java new file mode 100644 index 000000000..6f6989749 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.networking.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.handler.ClientNetworkHandler; +import net.minecraft.client.world.ClientWorld; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +@Mixin(Minecraft.class) +public class MinecraftMixin { + + @Shadow + private ClientWorld world; + + @Shadow + private ClientNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "setWorld(Lnet/minecraft/client/world/ClientWorld;Ljava/lang/String;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(ClientWorld world, String title, CallbackInfo ci) { + if (this.world != null && world == null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java new file mode 100644 index 000000000..32ec4bae7 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,37 @@ +package net.ornithemc.osl.networking.impl.mixin.common; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.mob.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final private MinecraftServer server; + + @Inject( + method = "remove", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } +} diff --git a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerLoginNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerLoginNetworkHandlerMixin.java index bcdecf706..2f4e70f3e 100644 --- a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerLoginNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerLoginNetworkHandlerMixin.java @@ -14,6 +14,8 @@ import net.minecraft.server.network.handler.ServerLoginNetworkHandler; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; @Mixin(ServerLoginNetworkHandler.class) public class ServerLoginNetworkHandlerMixin { @@ -28,7 +30,10 @@ public class ServerLoginNetworkHandlerMixin { ) private void osl$networking$handleLogin(CallbackInfo ci, @Local ServerPlayerEntity player) { if (player != null) { - ServerConnectionEvents.LOGIN.invoker().accept(server, player); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.LOGIN.invoker().accept(connectionContext); } } } diff --git a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java index c05277df0..5fb807bd9 100644 --- a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java @@ -3,6 +3,7 @@ import java.util.LinkedHashSet; import java.util.Set; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -16,20 +17,37 @@ import net.minecraft.server.network.handler.ServerPlayNetworkHandler; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; -import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ServerPlayNetworkHandler.class) -public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { +public class ServerPlayNetworkHandlerMixin implements ServerNetworkHandlerAccess { - @Shadow private MinecraftServer server; - @Shadow private ServerPlayerEntity player; + @Shadow @Final + private MinecraftServer server; + @Shadow + private ServerPlayerEntity player; + + @Unique + private ServerConnectionContext connectionContext; /** * Channels that the client is listening to. */ - @Unique private Set clientChannels; + @Unique + private Set clientChannels; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$initConnectionContext(CallbackInfo ci) { + connectionContext = new ServerConnectionContext(server, (ServerPlayNetworkHandler) (Object) this); + } @Inject( method = "onDisconnect", @@ -37,9 +55,10 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ServerConnectionEvents.DISCONNECT.invoker().accept(server, player); - clientChannels = null; + private void osl$networking$handleDisconnect(String reason, Object[] args, CallbackInfo ci) { + connectionContext.offerDisconnectReason(args == null + ? TextComponents.translatable(reason) + : TextComponents.translatable(reason, args)); } @Inject( @@ -55,6 +74,11 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ServerConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$canRunOffMainThread() { return true; diff --git a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/resources/fabric.mod.json b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/resources/fabric.mod.json index f58bac871..593432470 100644 --- a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/resources/fabric.mod.json +++ b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/resources/fabric.mod.json @@ -23,6 +23,8 @@ "osl-core": "\u003e\u003d0.7.0", "osl-entrypoints": "\u003e\u003d0.5.0", "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", "osl-networking": "\u003e\u003d0.9.0" }, "name": "OSL Networking Implementation", diff --git a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/resources/osl.networking-impl.mixins.json b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/resources/osl.networking-impl.mixins.json index 6e7aac370..7239176e2 100644 --- a/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/resources/osl.networking-impl.mixins.json +++ b/libraries/networking-impl/networking-impl-mc12w18a-mc12w19a/src/main/resources/osl.networking-impl.mixins.json @@ -10,7 +10,9 @@ "common.ServerPlayNetworkHandlerMixin" ], "client": [ - "client.ClientNetworkHandlerMixin" + "client.ClientNetworkHandlerMixin", + "client.LocalServerAccess", + "client.MinecraftMixin" ], "server": [ ], diff --git a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/Networking.java b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/Networking.java index f97e0a068..77c8c0396 100644 --- a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/Networking.java +++ b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/Networking.java @@ -11,8 +11,11 @@ import net.ornithemc.osl.networking.api.StringChannelIdentifierParser; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; public class Networking implements ModInitializer, ClientModInitializer, ServerModInitializer { @@ -26,8 +29,11 @@ public void init() { // send channel registration data as a response to receiving client channel registration data ServerPlayNetworkingImpl.sendNoCheck(context.player(), HandshakePayload.CHANNEL, HandshakePayload.server()); - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ServerConnectionEvents.PLAY_READY.invoker().accept(context.server(), context.player()); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) context.networkHandler(); + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ServerConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } @@ -37,8 +43,11 @@ public void initClient() { MinecraftClientEvents.STOP.register(ClientPlayNetworkingImpl::destroy); ClientPlayNetworkingImpl.setUpPacketFactory(Networking::newCustomPayloadPacket); ClientPlayNetworkingImpl.registerListener(HandshakePayload.CHANNEL, HandshakePayload::new, (context, payload) -> { - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ClientConnectionEvents.PLAY_READY.invoker().accept(context.minecraft()); + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) context.networkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ClientConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } diff --git a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/NetworkingMixinPlugin.java b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/NetworkingMixinPlugin.java new file mode 100644 index 000000000..5ca85f599 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/NetworkingMixinPlugin.java @@ -0,0 +1,54 @@ +package net.ornithemc.osl.networking.impl; + +import java.util.List; +import java.util.Set; + +import org.objectweb.asm.tree.ClassNode; + +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import net.ornithemc.osl.core.impl.util.MinecraftVersion; + +public class NetworkingMixinPlugin implements IMixinConfigPlugin { + + public static final boolean PACKET_READ_QUEUE_IS_LIST = MinecraftVersion.resolve().compareTo("1.6.1") <= 0; + + @Override + public void onLoad(String mixinPackage) { + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if ("net.ornithemc.osl.networking.impl.mixin.common.RemoteConnectionMixinNew".equals(mixinClassName)) { + return !PACKET_READ_QUEUE_IS_LIST; + } + if ("net.ornithemc.osl.networking.impl.mixin.common.RemoteConnectionMixinOld".equals(mixinClassName)) { + return PACKET_READ_QUEUE_IS_LIST; + } + + return true; + } + + @Override + public void acceptTargets(Set myTargets, Set otherTargets) { + } + + @Override + public List getMixins() { + return null; + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } +} diff --git a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..e067a1831 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +public interface ClientNetworkHandlerAccess extends NetworkHandlerAccess { + + ClientConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java new file mode 100644 index 000000000..1d596400b --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +public interface ServerNetworkHandlerAccess extends NetworkHandlerAccess { + + ServerConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java index a5a8a07b2..67a6060c8 100644 --- a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java @@ -1,8 +1,10 @@ package net.ornithemc.osl.networking.impl.mixin.client; +import java.net.SocketAddress; import java.util.LinkedHashSet; import java.util.Set; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -13,24 +15,37 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.network.handler.ClientNetworkHandler; import net.minecraft.client.world.ClientWorld; +import net.minecraft.network.Connection; import net.minecraft.network.packet.CustomPayloadPacket; +import net.minecraft.network.packet.DisconnectPacket; +import net.minecraft.server.integrated.IntegratedServer; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.AddressParser; import net.ornithemc.osl.networking.impl.HandshakePayload; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ClientNetworkHandler.class) -public class ClientNetworkHandlerMixin implements NetworkHandlerAccess { +public class ClientNetworkHandlerMixin implements ClientNetworkHandlerAccess { - @Shadow private Minecraft minecraft; - @Shadow private ClientWorld world; + @Shadow @Final + private Minecraft minecraft; + @Shadow @Final + private ClientWorld world; + @Shadow @Final + private Connection connection; + @Unique + private ClientConnectionContext connectionContext; /** * Channels that the server is listening to. */ - @Unique private Set serverChannels; + @Unique + private Set serverChannels; @Inject( method = "handleLogin", @@ -39,10 +54,34 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess { ) ) private void osl$networking$handleLogin(CallbackInfo ci) { + if (minecraft.isIntegratedServerRunning()) { + IntegratedServer server = minecraft.getServer(); + String worldName = server.getWorldName(); + + connectionContext = new ClientConnectionContext(minecraft, worldName); + } else { + SocketAddress address = connection.getAddress(); + + String serverAddress = AddressParser.getAddress(address); + int serverPort = AddressParser.getPort(address); + + connectionContext = new ClientConnectionContext(minecraft, serverAddress, serverPort); + } + // send channel registration data as soon as login occurs ClientPlayNetworkingImpl.sendNoCheck(HandshakePayload.CHANNEL, HandshakePayload.client()); - ClientConnectionEvents.LOGIN.invoker().accept(minecraft); + ClientConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "handleDisconnect", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(DisconnectPacket packet, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(packet.reason)); } @Inject( @@ -51,9 +90,10 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ClientConnectionEvents.DISCONNECT.invoker().accept(minecraft); - serverChannels = null; + private void osl$networking$handleDisconnect(String reason, Object[] args, CallbackInfo ci) { + connectionContext.offerDisconnectReason(args == null + ? TextComponents.translatable(reason) + : TextComponents.translatable(reason, args)); } @Inject( @@ -69,6 +109,11 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ClientConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$canRunOffMainThread() { return minecraft != null && minecraft.world != null && minecraft.player != null && world != null; diff --git a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java new file mode 100644 index 000000000..6f6989749 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.networking.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.handler.ClientNetworkHandler; +import net.minecraft.client.world.ClientWorld; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +@Mixin(Minecraft.class) +public class MinecraftMixin { + + @Shadow + private ClientWorld world; + + @Shadow + private ClientNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "setWorld(Lnet/minecraft/client/world/ClientWorld;Ljava/lang/String;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(ClientWorld world, String title, CallbackInfo ci) { + if (this.world != null && world == null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java new file mode 100644 index 000000000..718f04e3d --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java @@ -0,0 +1,42 @@ +package net.ornithemc.osl.networking.impl.mixin.common; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.mob.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + + @Shadow + private PlayerManager playerManager; + + @Inject( + method = "stop", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$stop(CallbackInfo ci) { + @SuppressWarnings("unchecked") + List players = (List) this.playerManager.players; + + for (ServerPlayerEntity player : players) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java index 524a0e780..6fc5bdde8 100644 --- a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java +++ b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java @@ -7,12 +7,15 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import net.minecraft.network.Connection; +import com.llamalad7.mixinextras.sugar.Local; + import net.minecraft.server.MinecraftServer; import net.minecraft.server.PlayerManager; import net.minecraft.server.entity.mob.player.ServerPlayerEntity; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; @Mixin(PlayerManager.class) public class PlayerManagerMixin { @@ -25,7 +28,23 @@ public class PlayerManagerMixin { value = "TAIL" ) ) - private void osl$networking$handleLogin(Connection connection, ServerPlayerEntity player, CallbackInfo ci) { - ServerConnectionEvents.LOGIN.invoker().accept(server, player); + private void osl$networking$handleLogin(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "remove", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); } } diff --git a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/RemoteConnectionMixin.java b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/RemoteConnectionMixinNew.java similarity index 60% rename from libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/RemoteConnectionMixin.java rename to libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/RemoteConnectionMixinNew.java index dcf4301b1..e481b3fc9 100644 --- a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/RemoteConnectionMixin.java +++ b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/RemoteConnectionMixinNew.java @@ -15,35 +15,19 @@ import net.ornithemc.osl.networking.impl.Connections; @Mixin(RemoteConnection.class) -public class RemoteConnectionMixin { +public class RemoteConnectionMixinNew { @Shadow private PacketHandler listener; @Inject( method = "read", cancellable = true, - require = 0, // will fail in 1.6.2+ - at = @At( - value = "INVOKE", - target = "Ljava/util/List;add(Ljava/lang/Object;)Z" - ) - ) - private void osl$networking$asyncCustomPayloads1(CallbackInfoReturnable cir, @Local Packet packet) { - if (Connections.handleAsyncPacket(packet, listener)) { - cir.setReturnValue(true); - } - } - - @Inject( - method = "read", - cancellable = true, - require = 0, // will fail in 1.6.1- at = @At( value = "INVOKE", target = "Ljava/util/Queue;add(Ljava/lang/Object;)Z" ) ) - private void osl$networking$asyncCustomPayloads2(CallbackInfoReturnable cir, @Local Packet packet) { + private void osl$networking$asyncCustomPayloads(CallbackInfoReturnable cir, @Local Packet packet) { if (Connections.handleAsyncPacket(packet, listener)) { cir.setReturnValue(true); } diff --git a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/RemoteConnectionMixinOld.java b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/RemoteConnectionMixinOld.java new file mode 100644 index 000000000..b47de07d9 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/RemoteConnectionMixinOld.java @@ -0,0 +1,35 @@ +package net.ornithemc.osl.networking.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.network.PacketHandler; +import net.minecraft.network.RemoteConnection; +import net.minecraft.network.packet.Packet; + +import net.ornithemc.osl.networking.impl.Connections; + +@Mixin(RemoteConnection.class) +public class RemoteConnectionMixinOld { + + @Shadow private PacketHandler listener; + + @Inject( + method = "read", + cancellable = true, + at = @At( + value = "INVOKE", + target = "Ljava/util/List;add(Ljava/lang/Object;)Z" + ) + ) + private void osl$networking$asyncCustomPayloads(CallbackInfoReturnable cir, @Local Packet packet) { + if (Connections.handleAsyncPacket(packet, listener)) { + cir.setReturnValue(true); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java index c05277df0..5fb807bd9 100644 --- a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java @@ -3,6 +3,7 @@ import java.util.LinkedHashSet; import java.util.Set; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -16,20 +17,37 @@ import net.minecraft.server.network.handler.ServerPlayNetworkHandler; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; -import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ServerPlayNetworkHandler.class) -public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { +public class ServerPlayNetworkHandlerMixin implements ServerNetworkHandlerAccess { - @Shadow private MinecraftServer server; - @Shadow private ServerPlayerEntity player; + @Shadow @Final + private MinecraftServer server; + @Shadow + private ServerPlayerEntity player; + + @Unique + private ServerConnectionContext connectionContext; /** * Channels that the client is listening to. */ - @Unique private Set clientChannels; + @Unique + private Set clientChannels; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$initConnectionContext(CallbackInfo ci) { + connectionContext = new ServerConnectionContext(server, (ServerPlayNetworkHandler) (Object) this); + } @Inject( method = "onDisconnect", @@ -37,9 +55,10 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ServerConnectionEvents.DISCONNECT.invoker().accept(server, player); - clientChannels = null; + private void osl$networking$handleDisconnect(String reason, Object[] args, CallbackInfo ci) { + connectionContext.offerDisconnectReason(args == null + ? TextComponents.translatable(reason) + : TextComponents.translatable(reason, args)); } @Inject( @@ -55,6 +74,11 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ServerConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$canRunOffMainThread() { return true; diff --git a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/resources/fabric.mod.json b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/resources/fabric.mod.json index 2a1b77d23..dfa09175c 100644 --- a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/resources/fabric.mod.json +++ b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/resources/fabric.mod.json @@ -23,6 +23,8 @@ "osl-core": "\u003e\u003d0.7.0", "osl-entrypoints": "\u003e\u003d0.5.0", "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", "osl-networking": "\u003e\u003d0.9.0" }, "name": "OSL Networking Implementation", diff --git a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/resources/osl.networking-impl.mixins.json b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/resources/osl.networking-impl.mixins.json index bfb2c375e..b739362a3 100644 --- a/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/resources/osl.networking-impl.mixins.json +++ b/libraries/networking-impl/networking-impl-mc12w21a-mc13w39b/src/main/resources/osl.networking-impl.mixins.json @@ -3,15 +3,19 @@ "minVersion": "0.8", "package": "net.ornithemc.osl.networking.impl.mixin", "compatibilityLevel": "JAVA_8", + "plugin": "net.ornithemc.osl.networking.impl.NetworkingMixinPlugin", "mixins": [ "common.CustomPayloadPacketMixin", + "common.MinecraftServerMixin", "common.PlayerManagerMixin", - "common.RemoteConnectionMixin", + "common.RemoteConnectionMixinNew", + "common.RemoteConnectionMixinOld", "common.ServerPlayNetworkHandlerMixin" ], "client": [ "client.ClientNetworkHandlerMixin", - "client.LocalConnectionMixin" + "client.LocalConnectionMixin", + "client.MinecraftMixin" ], "server": [ ], diff --git a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/Networking.java b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/Networking.java index 10f44a335..3aea1c461 100644 --- a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/Networking.java +++ b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/Networking.java @@ -12,8 +12,11 @@ import net.ornithemc.osl.networking.api.StringChannelIdentifierParser; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; public class Networking implements ModInitializer, ClientModInitializer, ServerModInitializer { @@ -28,8 +31,11 @@ public void init() { // send channel registration data as a response to receiving client channel registration data ServerPlayNetworkingImpl.sendNoCheck(context.player(), HandshakePayload.CHANNEL, HandshakePayload.server()); - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ServerConnectionEvents.PLAY_READY.invoker().accept(context.server(), context.player()); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) context.networkHandler(); + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ServerConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } @@ -40,8 +46,11 @@ public void initClient() { ClientPlayNetworkingImpl.setUpPacketFactory((channel, data) -> new CustomPayloadC2SPacket(StringChannelIdentifierParser.toString(channel), PacketBuffers.unwrapped(data))); ClientPlayNetworkingImpl.registerListener(HandshakePayload.CHANNEL, HandshakePayload::new, (context, payload) -> { - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ClientConnectionEvents.PLAY_READY.invoker().accept(context.minecraft()); + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) context.networkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ClientConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } diff --git a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..e067a1831 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +public interface ClientNetworkHandlerAccess extends NetworkHandlerAccess { + + ClientConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java new file mode 100644 index 000000000..1d596400b --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +public interface ServerNetworkHandlerAccess extends NetworkHandlerAccess { + + ServerConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java index ef5dbdfbb..e43da06c8 100644 --- a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java @@ -1,5 +1,6 @@ package net.ornithemc.osl.networking.impl.mixin.client; +import java.net.SocketAddress; import java.util.LinkedHashSet; import java.util.Set; @@ -13,23 +14,36 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.network.Connection; import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; +import net.minecraft.network.packet.s2c.play.DisconnectS2CPacket; +import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.text.Text; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.AddressParser; import net.ornithemc.osl.networking.impl.HandshakePayload; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ClientPlayNetworkHandler.class) -public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { +public class ClientPlayNetworkHandlerMixin implements ClientNetworkHandlerAccess { - @Shadow @Final private Minecraft minecraft; + @Shadow @Final + private Minecraft minecraft; + @Shadow @Final + private Connection connection; + @Unique + private ClientConnectionContext connectionContext; /** * Channels that the server is listening to. */ - @Unique private Set serverChannels; + @Unique + private Set serverChannels; @Inject( method = "handleLogin", @@ -38,10 +52,34 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { ) ) private void osl$networking$handleLogin(CallbackInfo ci) { + if (minecraft.isIntegratedServerRunning()) { + IntegratedServer server = minecraft.getServer(); + String worldName = server.getWorldName(); + + connectionContext = new ClientConnectionContext(minecraft, worldName); + } else { + SocketAddress address = connection.getAddress(); + + String serverAddress = AddressParser.getAddress(address); + int serverPort = AddressParser.getPort(address); + + connectionContext = new ClientConnectionContext(minecraft, serverAddress, serverPort); + } + // send channel registration data as soon as login occurs ClientPlayNetworkingImpl.sendNoCheck(HandshakePayload.CHANNEL, HandshakePayload.client()); - ClientConnectionEvents.LOGIN.invoker().accept(minecraft); + ClientConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "handleDisconnect", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(DisconnectS2CPacket packet, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(packet.getReason())); } @Inject( @@ -50,9 +88,8 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ClientConnectionEvents.DISCONNECT.invoker().accept(minecraft); - serverChannels = null; + private void osl$networking$handleDisconnect(Text reason, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(reason)); } @Inject( @@ -68,6 +105,11 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ClientConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$isPlayReady() { return serverChannels != null; diff --git a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java new file mode 100644 index 000000000..a53f875a5 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.networking.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.client.world.ClientWorld; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +@Mixin(Minecraft.class) +public class MinecraftMixin { + + @Shadow + private ClientWorld world; + + @Shadow + private ClientPlayNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "setWorld(Lnet/minecraft/client/world/ClientWorld;Ljava/lang/String;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(ClientWorld world, String title, CallbackInfo ci) { + if (this.world != null && world == null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java new file mode 100644 index 000000000..7f4d67405 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java @@ -0,0 +1,50 @@ +package net.ornithemc.osl.networking.impl.mixin.common; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.core.impl.util.MinecraftVersion; +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + + private static final boolean INTEGRATED_SERVER_REMOVES_PLAYERS_ON_STOP = MinecraftVersion.resolve().compareTo("14w06a") >= 0; + + @Shadow + private PlayerManager playerManager; + + @Shadow + private boolean isDedicated() { return false; } + + @Inject( + method = "stop", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$stop(CallbackInfo ci) { + if (!INTEGRATED_SERVER_REMOVES_PLAYERS_ON_STOP || this.isDedicated()) { + @SuppressWarnings("unchecked") + List players = (List) this.playerManager.players; + + for (ServerPlayerEntity player : players) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java index 77688e80f..463dde8b5 100644 --- a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java +++ b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java @@ -1,5 +1,7 @@ package net.ornithemc.osl.networking.impl.mixin.common; +import java.util.List; + import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -14,11 +16,15 @@ import net.minecraft.server.entity.living.player.ServerPlayerEntity; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.PlayerManagerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; @Mixin(PlayerManager.class) -public class PlayerManagerMixin { +public class PlayerManagerMixin implements PlayerManagerAccess { @Shadow @Final private MinecraftServer server; + @Shadow @Final private List players; @Inject( method = "onLogin", @@ -27,6 +33,27 @@ public class PlayerManagerMixin { ) ) private void osl$networking$handleLogin(CallbackInfo ci, @Local ServerPlayerEntity player) { - ServerConnectionEvents.LOGIN.invoker().accept(server, player); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "remove", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + + @Override + public List osl$networking$getAll() { + return players; } } diff --git a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java index ac66d4400..270f4b80b 100644 --- a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java @@ -15,22 +15,40 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.entity.living.player.ServerPlayerEntity; import net.minecraft.server.network.handler.ServerPlayNetworkHandler; +import net.minecraft.text.Text; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; -import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ServerPlayNetworkHandler.class) -public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { +public class ServerPlayNetworkHandlerMixin implements ServerNetworkHandlerAccess { - @Shadow @Final private MinecraftServer server; - @Shadow @Final private ServerPlayerEntity player; + @Shadow @Final + private MinecraftServer server; + @Shadow + private ServerPlayerEntity player; + + @Unique + private ServerConnectionContext connectionContext; /** * Channels that the client is listening to. */ - @Unique private Set clientChannels; + @Unique + private Set clientChannels; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$initConnectionContext(CallbackInfo ci) { + connectionContext = new ServerConnectionContext(server, (ServerPlayNetworkHandler) (Object) this); + } @Inject( method = "onDisconnect", @@ -38,9 +56,8 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ServerConnectionEvents.DISCONNECT.invoker().accept(server, player); - clientChannels = null; + private void osl$networking$handleDisconnect(Text reason, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(reason)); } @Inject( @@ -56,6 +73,11 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ServerConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$isPlayReady() { return clientChannels != null; diff --git a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/resources/fabric.mod.json b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/resources/fabric.mod.json index 7a03c9bfd..b5b15263d 100644 --- a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/resources/fabric.mod.json +++ b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/resources/fabric.mod.json @@ -23,6 +23,8 @@ "osl-core": "\u003e\u003d0.7.0", "osl-entrypoints": "\u003e\u003d0.5.0", "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", "osl-networking": "\u003e\u003d0.9.0" }, "name": "OSL Networking Implementation", diff --git a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/resources/osl.networking-impl.mixins.json b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/resources/osl.networking-impl.mixins.json index 24982b358..7d6b73fee 100644 --- a/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/resources/osl.networking-impl.mixins.json +++ b/libraries/networking-impl/networking-impl-mc13w41a-mc14w20b/src/main/resources/osl.networking-impl.mixins.json @@ -7,11 +7,13 @@ "common.ConnectionMixin", "common.CustomPayloadC2SPacketMixin", "common.CustomPayloadS2CPacketMixin", + "common.MinecraftServerMixin", "common.PlayerManagerMixin", "common.ServerPlayNetworkHandlerMixin" ], "client": [ - "client.ClientPlayNetworkHandlerMixin" + "client.ClientPlayNetworkHandlerMixin", + "client.MinecraftMixin" ], "server": [ ], diff --git a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/Networking.java b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/Networking.java index 10f44a335..3aea1c461 100644 --- a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/Networking.java +++ b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/Networking.java @@ -12,8 +12,11 @@ import net.ornithemc.osl.networking.api.StringChannelIdentifierParser; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; public class Networking implements ModInitializer, ClientModInitializer, ServerModInitializer { @@ -28,8 +31,11 @@ public void init() { // send channel registration data as a response to receiving client channel registration data ServerPlayNetworkingImpl.sendNoCheck(context.player(), HandshakePayload.CHANNEL, HandshakePayload.server()); - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ServerConnectionEvents.PLAY_READY.invoker().accept(context.server(), context.player()); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) context.networkHandler(); + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ServerConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } @@ -40,8 +46,11 @@ public void initClient() { ClientPlayNetworkingImpl.setUpPacketFactory((channel, data) -> new CustomPayloadC2SPacket(StringChannelIdentifierParser.toString(channel), PacketBuffers.unwrapped(data))); ClientPlayNetworkingImpl.registerListener(HandshakePayload.CHANNEL, HandshakePayload::new, (context, payload) -> { - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ClientConnectionEvents.PLAY_READY.invoker().accept(context.minecraft()); + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) context.networkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ClientConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } diff --git a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..e067a1831 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +public interface ClientNetworkHandlerAccess extends NetworkHandlerAccess { + + ClientConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java new file mode 100644 index 000000000..1d596400b --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +public interface ServerNetworkHandlerAccess extends NetworkHandlerAccess { + + ServerConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java index ef5dbdfbb..e43da06c8 100644 --- a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java @@ -1,5 +1,6 @@ package net.ornithemc.osl.networking.impl.mixin.client; +import java.net.SocketAddress; import java.util.LinkedHashSet; import java.util.Set; @@ -13,23 +14,36 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.network.Connection; import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; +import net.minecraft.network.packet.s2c.play.DisconnectS2CPacket; +import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.text.Text; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.AddressParser; import net.ornithemc.osl.networking.impl.HandshakePayload; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ClientPlayNetworkHandler.class) -public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { +public class ClientPlayNetworkHandlerMixin implements ClientNetworkHandlerAccess { - @Shadow @Final private Minecraft minecraft; + @Shadow @Final + private Minecraft minecraft; + @Shadow @Final + private Connection connection; + @Unique + private ClientConnectionContext connectionContext; /** * Channels that the server is listening to. */ - @Unique private Set serverChannels; + @Unique + private Set serverChannels; @Inject( method = "handleLogin", @@ -38,10 +52,34 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { ) ) private void osl$networking$handleLogin(CallbackInfo ci) { + if (minecraft.isIntegratedServerRunning()) { + IntegratedServer server = minecraft.getServer(); + String worldName = server.getWorldName(); + + connectionContext = new ClientConnectionContext(minecraft, worldName); + } else { + SocketAddress address = connection.getAddress(); + + String serverAddress = AddressParser.getAddress(address); + int serverPort = AddressParser.getPort(address); + + connectionContext = new ClientConnectionContext(minecraft, serverAddress, serverPort); + } + // send channel registration data as soon as login occurs ClientPlayNetworkingImpl.sendNoCheck(HandshakePayload.CHANNEL, HandshakePayload.client()); - ClientConnectionEvents.LOGIN.invoker().accept(minecraft); + ClientConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "handleDisconnect", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(DisconnectS2CPacket packet, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(packet.getReason())); } @Inject( @@ -50,9 +88,8 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ClientConnectionEvents.DISCONNECT.invoker().accept(minecraft); - serverChannels = null; + private void osl$networking$handleDisconnect(Text reason, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(reason)); } @Inject( @@ -68,6 +105,11 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ClientConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$isPlayReady() { return serverChannels != null; diff --git a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java index 1b011d9d0..a53f875a5 100644 --- a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java +++ b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java @@ -1,18 +1,40 @@ package net.ornithemc.osl.networking.impl.mixin.client; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import net.minecraft.client.Minecraft; -import net.minecraft.util.BlockableEventLoop; +import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.client.world.ClientWorld; -import net.ornithemc.osl.networking.impl.access.TaskRunnerAccess; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; @Mixin(Minecraft.class) -public abstract class MinecraftMixin implements BlockableEventLoop, TaskRunnerAccess { +public class MinecraftMixin { - @Override - public boolean osl$networking$submit(Runnable task) { - this.executeTask(task); - return true; + @Shadow + private ClientWorld world; + + @Shadow + private ClientPlayNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "setWorld(Lnet/minecraft/client/world/ClientWorld;Ljava/lang/String;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(ClientWorld world, String title, CallbackInfo ci) { + if (this.world != null && world == null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } } } diff --git a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java deleted file mode 100644 index acd027e07..000000000 --- a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.ornithemc.osl.networking.impl.mixin.common; - -import org.spongepowered.asm.mixin.Mixin; - -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.BlockableEventLoop; - -import net.ornithemc.osl.networking.impl.access.TaskRunnerAccess; - -@Mixin(MinecraftServer.class) -public abstract class MinecraftServerMixin implements BlockableEventLoop, TaskRunnerAccess { - - @Override - public boolean osl$networking$submit(Runnable task) { - this.executeTask(task); - return true; - } -} diff --git a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java index e88d1f5a4..463dde8b5 100644 --- a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java +++ b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java @@ -9,13 +9,16 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import net.minecraft.network.Connection; +import com.llamalad7.mixinextras.sugar.Local; + import net.minecraft.server.MinecraftServer; import net.minecraft.server.PlayerManager; import net.minecraft.server.entity.living.player.ServerPlayerEntity; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; import net.ornithemc.osl.networking.impl.access.PlayerManagerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; @Mixin(PlayerManager.class) public class PlayerManagerMixin implements PlayerManagerAccess { @@ -29,8 +32,24 @@ public class PlayerManagerMixin implements PlayerManagerAccess { value = "TAIL" ) ) - private void osl$networking$handleLogin(Connection connection, ServerPlayerEntity player, CallbackInfo ci) { - ServerConnectionEvents.LOGIN.invoker().accept(server, player); + private void osl$networking$handleLogin(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "remove", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); } @Override diff --git a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java index ac66d4400..270f4b80b 100644 --- a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java @@ -15,22 +15,40 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.entity.living.player.ServerPlayerEntity; import net.minecraft.server.network.handler.ServerPlayNetworkHandler; +import net.minecraft.text.Text; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; -import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ServerPlayNetworkHandler.class) -public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { +public class ServerPlayNetworkHandlerMixin implements ServerNetworkHandlerAccess { - @Shadow @Final private MinecraftServer server; - @Shadow @Final private ServerPlayerEntity player; + @Shadow @Final + private MinecraftServer server; + @Shadow + private ServerPlayerEntity player; + + @Unique + private ServerConnectionContext connectionContext; /** * Channels that the client is listening to. */ - @Unique private Set clientChannels; + @Unique + private Set clientChannels; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$initConnectionContext(CallbackInfo ci) { + connectionContext = new ServerConnectionContext(server, (ServerPlayNetworkHandler) (Object) this); + } @Inject( method = "onDisconnect", @@ -38,9 +56,8 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ServerConnectionEvents.DISCONNECT.invoker().accept(server, player); - clientChannels = null; + private void osl$networking$handleDisconnect(Text reason, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(reason)); } @Inject( @@ -56,6 +73,11 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ServerConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$isPlayReady() { return clientChannels != null; diff --git a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/MinecraftServerMixin.java b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/MinecraftServerMixin.java new file mode 100644 index 000000000..cc6cfb489 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/MinecraftServerMixin.java @@ -0,0 +1,42 @@ +package net.ornithemc.osl.networking.impl.mixin.server; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + + @Shadow + private PlayerManager playerManager; + + @Inject( + method = "stop", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$stop(CallbackInfo ci) { + @SuppressWarnings("unchecked") + List players = (List) this.playerManager.players; + + for (ServerPlayerEntity player : players) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/resources/fabric.mod.json b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/resources/fabric.mod.json index ed03b0640..074ccede0 100644 --- a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/resources/fabric.mod.json +++ b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/resources/fabric.mod.json @@ -23,6 +23,8 @@ "osl-core": "\u003e\u003d0.7.0", "osl-entrypoints": "\u003e\u003d0.5.0", "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", "osl-networking": "\u003e\u003d0.9.0" }, "name": "OSL Networking Implementation", diff --git a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/resources/osl.networking-impl.mixins.json b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/resources/osl.networking-impl.mixins.json index f64bbc230..4c0a97f4c 100644 --- a/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/resources/osl.networking-impl.mixins.json +++ b/libraries/networking-impl/networking-impl-mc14w21a-mc14w30c/src/main/resources/osl.networking-impl.mixins.json @@ -6,7 +6,6 @@ "mixins": [ "common.CustomPayloadC2SPacketMixin", "common.CustomPayloadS2CPacketMixin", - "common.MinecraftServerMixin", "common.PlayerManagerMixin", "common.ServerPlayNetworkHandlerMixin" ], @@ -15,6 +14,7 @@ "client.MinecraftMixin" ], "server": [ + "server.MinecraftServerMixin" ], "injectors": { "defaultRequire": 1 diff --git a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/Networking.java b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/Networking.java index 10f44a335..3aea1c461 100644 --- a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/Networking.java +++ b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/Networking.java @@ -12,8 +12,11 @@ import net.ornithemc.osl.networking.api.StringChannelIdentifierParser; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; public class Networking implements ModInitializer, ClientModInitializer, ServerModInitializer { @@ -28,8 +31,11 @@ public void init() { // send channel registration data as a response to receiving client channel registration data ServerPlayNetworkingImpl.sendNoCheck(context.player(), HandshakePayload.CHANNEL, HandshakePayload.server()); - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ServerConnectionEvents.PLAY_READY.invoker().accept(context.server(), context.player()); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) context.networkHandler(); + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ServerConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } @@ -40,8 +46,11 @@ public void initClient() { ClientPlayNetworkingImpl.setUpPacketFactory((channel, data) -> new CustomPayloadC2SPacket(StringChannelIdentifierParser.toString(channel), PacketBuffers.unwrapped(data))); ClientPlayNetworkingImpl.registerListener(HandshakePayload.CHANNEL, HandshakePayload::new, (context, payload) -> { - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ClientConnectionEvents.PLAY_READY.invoker().accept(context.minecraft()); + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) context.networkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ClientConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } diff --git a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/NetworkingMixinPlugin.java b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/NetworkingMixinPlugin.java new file mode 100644 index 000000000..cbf86c514 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/NetworkingMixinPlugin.java @@ -0,0 +1,58 @@ +package net.ornithemc.osl.networking.impl; + +import java.util.List; +import java.util.Set; + +import org.objectweb.asm.tree.ClassNode; + +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import net.ornithemc.osl.core.impl.util.MinecraftVersion; + +public class NetworkingMixinPlugin implements IMixinConfigPlugin { + + public static final boolean MINECRAFT_SET_WORLD_HAS_SCREEN_PARAMETER = MinecraftVersion.resolve().compareTo("18w15a") >= 0; + public static final boolean MINECRAFT_SET_WORLD_HAS_TITLE_PARAMETER = MinecraftVersion.resolve().compareTo("17w50a") <= 0; + + @Override + public void onLoad(String mixinPackage) { + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if ("net.ornithemc.osl.networking.impl.mixin.client.MinecraftMixinNew".equals(mixinClassName)) { + return MINECRAFT_SET_WORLD_HAS_SCREEN_PARAMETER; + } + if ("net.ornithemc.osl.networking.impl.mixin.client.MinecraftMixinMid".equals(mixinClassName)) { + return !MINECRAFT_SET_WORLD_HAS_SCREEN_PARAMETER && !MINECRAFT_SET_WORLD_HAS_TITLE_PARAMETER; + } + if ("net.ornithemc.osl.networking.impl.mixin.client.MinecraftMixinOld".equals(mixinClassName)) { + return MINECRAFT_SET_WORLD_HAS_TITLE_PARAMETER; + } + + return true; + } + + @Override + public void acceptTargets(Set myTargets, Set otherTargets) { + } + + @Override + public List getMixins() { + return null; + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } +} diff --git a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..e067a1831 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +public interface ClientNetworkHandlerAccess extends NetworkHandlerAccess { + + ClientConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java new file mode 100644 index 000000000..1d596400b --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +public interface ServerNetworkHandlerAccess extends NetworkHandlerAccess { + + ServerConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java index ef5dbdfbb..e43da06c8 100644 --- a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java @@ -1,5 +1,6 @@ package net.ornithemc.osl.networking.impl.mixin.client; +import java.net.SocketAddress; import java.util.LinkedHashSet; import java.util.Set; @@ -13,23 +14,36 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.network.Connection; import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; +import net.minecraft.network.packet.s2c.play.DisconnectS2CPacket; +import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.text.Text; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.AddressParser; import net.ornithemc.osl.networking.impl.HandshakePayload; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ClientPlayNetworkHandler.class) -public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { +public class ClientPlayNetworkHandlerMixin implements ClientNetworkHandlerAccess { - @Shadow @Final private Minecraft minecraft; + @Shadow @Final + private Minecraft minecraft; + @Shadow @Final + private Connection connection; + @Unique + private ClientConnectionContext connectionContext; /** * Channels that the server is listening to. */ - @Unique private Set serverChannels; + @Unique + private Set serverChannels; @Inject( method = "handleLogin", @@ -38,10 +52,34 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { ) ) private void osl$networking$handleLogin(CallbackInfo ci) { + if (minecraft.isIntegratedServerRunning()) { + IntegratedServer server = minecraft.getServer(); + String worldName = server.getWorldName(); + + connectionContext = new ClientConnectionContext(minecraft, worldName); + } else { + SocketAddress address = connection.getAddress(); + + String serverAddress = AddressParser.getAddress(address); + int serverPort = AddressParser.getPort(address); + + connectionContext = new ClientConnectionContext(minecraft, serverAddress, serverPort); + } + // send channel registration data as soon as login occurs ClientPlayNetworkingImpl.sendNoCheck(HandshakePayload.CHANNEL, HandshakePayload.client()); - ClientConnectionEvents.LOGIN.invoker().accept(minecraft); + ClientConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "handleDisconnect", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(DisconnectS2CPacket packet, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(packet.getReason())); } @Inject( @@ -50,9 +88,8 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ClientConnectionEvents.DISCONNECT.invoker().accept(minecraft); - serverChannels = null; + private void osl$networking$handleDisconnect(Text reason, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(reason)); } @Inject( @@ -68,6 +105,11 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ClientConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$isPlayReady() { return serverChannels != null; diff --git a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java deleted file mode 100644 index 1b011d9d0..000000000 --- a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.ornithemc.osl.networking.impl.mixin.client; - -import org.spongepowered.asm.mixin.Mixin; - -import net.minecraft.client.Minecraft; -import net.minecraft.util.BlockableEventLoop; - -import net.ornithemc.osl.networking.impl.access.TaskRunnerAccess; - -@Mixin(Minecraft.class) -public abstract class MinecraftMixin implements BlockableEventLoop, TaskRunnerAccess { - - @Override - public boolean osl$networking$submit(Runnable task) { - this.executeTask(task); - return true; - } -} diff --git a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixinMid.java b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixinMid.java new file mode 100644 index 000000000..48b129884 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixinMid.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.networking.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.client.world.ClientWorld; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +@Mixin(Minecraft.class) +public class MinecraftMixinMid { + + @Shadow + private ClientWorld world; + + @Shadow + private ClientPlayNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "m_85741928", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(ClientWorld world, CallbackInfo ci) { + if (this.world != null && world == null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixinNew.java b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixinNew.java new file mode 100644 index 000000000..5b88c3f59 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixinNew.java @@ -0,0 +1,41 @@ +package net.ornithemc.osl.networking.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.client.world.ClientWorld; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +@Mixin(Minecraft.class) +public class MinecraftMixinNew { + + @Shadow + private ClientWorld world; + + @Shadow + private ClientPlayNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "setWorld(Lnet/minecraft/client/world/ClientWorld;Lnet/minecraft/client/gui/screen/Screen;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(ClientWorld world, Screen screen, CallbackInfo ci) { + if (this.world != null && world == null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixinOld.java b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixinOld.java new file mode 100644 index 000000000..f055ed648 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixinOld.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.networking.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.client.world.ClientWorld; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +@Mixin(Minecraft.class) +public class MinecraftMixinOld { + + @Shadow + private ClientWorld world; + + @Shadow + private ClientPlayNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "m_49232044", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(ClientWorld world, String title, CallbackInfo ci) { + if (this.world != null && world == null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java deleted file mode 100644 index acd027e07..000000000 --- a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.ornithemc.osl.networking.impl.mixin.common; - -import org.spongepowered.asm.mixin.Mixin; - -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.BlockableEventLoop; - -import net.ornithemc.osl.networking.impl.access.TaskRunnerAccess; - -@Mixin(MinecraftServer.class) -public abstract class MinecraftServerMixin implements BlockableEventLoop, TaskRunnerAccess { - - @Override - public boolean osl$networking$submit(Runnable task) { - this.executeTask(task); - return true; - } -} diff --git a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java index e88d1f5a4..463dde8b5 100644 --- a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java +++ b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java @@ -9,13 +9,16 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import net.minecraft.network.Connection; +import com.llamalad7.mixinextras.sugar.Local; + import net.minecraft.server.MinecraftServer; import net.minecraft.server.PlayerManager; import net.minecraft.server.entity.living.player.ServerPlayerEntity; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; import net.ornithemc.osl.networking.impl.access.PlayerManagerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; @Mixin(PlayerManager.class) public class PlayerManagerMixin implements PlayerManagerAccess { @@ -29,8 +32,24 @@ public class PlayerManagerMixin implements PlayerManagerAccess { value = "TAIL" ) ) - private void osl$networking$handleLogin(Connection connection, ServerPlayerEntity player, CallbackInfo ci) { - ServerConnectionEvents.LOGIN.invoker().accept(server, player); + private void osl$networking$handleLogin(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "remove", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); } @Override diff --git a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java index ac66d4400..270f4b80b 100644 --- a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java @@ -15,22 +15,40 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.entity.living.player.ServerPlayerEntity; import net.minecraft.server.network.handler.ServerPlayNetworkHandler; +import net.minecraft.text.Text; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; -import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ServerPlayNetworkHandler.class) -public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { +public class ServerPlayNetworkHandlerMixin implements ServerNetworkHandlerAccess { - @Shadow @Final private MinecraftServer server; - @Shadow @Final private ServerPlayerEntity player; + @Shadow @Final + private MinecraftServer server; + @Shadow + private ServerPlayerEntity player; + + @Unique + private ServerConnectionContext connectionContext; /** * Channels that the client is listening to. */ - @Unique private Set clientChannels; + @Unique + private Set clientChannels; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$initConnectionContext(CallbackInfo ci) { + connectionContext = new ServerConnectionContext(server, (ServerPlayNetworkHandler) (Object) this); + } @Inject( method = "onDisconnect", @@ -38,9 +56,8 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ServerConnectionEvents.DISCONNECT.invoker().accept(server, player); - clientChannels = null; + private void osl$networking$handleDisconnect(Text reason, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(reason)); } @Inject( @@ -56,6 +73,11 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ServerConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$isPlayReady() { return clientChannels != null; diff --git a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/MinecraftServerMixin.java b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/MinecraftServerMixin.java new file mode 100644 index 000000000..3c389c76d --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/MinecraftServerMixin.java @@ -0,0 +1,42 @@ +package net.ornithemc.osl.networking.impl.mixin.server; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.PlayerManagerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + + @Shadow + private PlayerManager playerManager; + + @Inject( + method = "stop", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$stop(CallbackInfo ci) { + List players = ((PlayerManagerAccess) this.playerManager).osl$networking$getAll(); + + for (ServerPlayerEntity player : players) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/resources/fabric.mod.json b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/resources/fabric.mod.json index 34f9bebdf..6bdb081e1 100644 --- a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/resources/fabric.mod.json +++ b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/resources/fabric.mod.json @@ -23,6 +23,8 @@ "osl-core": "\u003e\u003d0.7.0", "osl-entrypoints": "\u003e\u003d0.5.0", "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", "osl-networking": "\u003e\u003d0.9.0" }, "name": "OSL Networking Implementation", diff --git a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/resources/osl.networking-impl.mixins.json b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/resources/osl.networking-impl.mixins.json index f64bbc230..d4dcc4aa6 100644 --- a/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/resources/osl.networking-impl.mixins.json +++ b/libraries/networking-impl/networking-impl-mc14w31a-mc1.13-pre2/src/main/resources/osl.networking-impl.mixins.json @@ -3,18 +3,21 @@ "minVersion": "0.8", "package": "net.ornithemc.osl.networking.impl.mixin", "compatibilityLevel": "JAVA_8", + "plugin": "net.ornithemc.osl.networking.impl.NetworkingMixinPlugin", "mixins": [ "common.CustomPayloadC2SPacketMixin", "common.CustomPayloadS2CPacketMixin", - "common.MinecraftServerMixin", "common.PlayerManagerMixin", "common.ServerPlayNetworkHandlerMixin" ], "client": [ "client.ClientPlayNetworkHandlerMixin", - "client.MinecraftMixin" + "client.MinecraftMixinMid", + "client.MinecraftMixinNew", + "client.MinecraftMixinOld" ], "server": [ + "server.MinecraftServerMixin" ], "injectors": { "defaultRequire": 1 diff --git a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/Networking.java b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/Networking.java index 2785b5e81..9bc0ddf8f 100644 --- a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/Networking.java +++ b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/Networking.java @@ -12,8 +12,11 @@ import net.ornithemc.osl.networking.api.PacketBuffers; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; public class Networking implements ModInitializer, ClientModInitializer, ServerModInitializer { @@ -28,8 +31,11 @@ public void init() { // send channel registration data as a response to receiving client channel registration data ServerPlayNetworkingImpl.sendNoCheck(context.player(), HandshakePayload.CHANNEL, HandshakePayload.server()); - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ServerConnectionEvents.PLAY_READY.invoker().accept(context.server(), context.player()); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) context.networkHandler(); + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ServerConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } @@ -40,8 +46,11 @@ public void initClient() { ClientPlayNetworkingImpl.setUpPacketFactory((channel, data) -> new CustomPayloadC2SPacket(IdentifierChannelIdentifierParser.toIdentifier(channel), PacketBuffers.unwrapped(data))); ClientPlayNetworkingImpl.registerListener(HandshakePayload.CHANNEL, HandshakePayload::new, (context, payload) -> { - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ClientConnectionEvents.PLAY_READY.invoker().accept(context.minecraft()); + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) context.networkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ClientConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } diff --git a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/NetworkingMixinPlugin.java b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/NetworkingMixinPlugin.java new file mode 100644 index 000000000..0e2807932 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/NetworkingMixinPlugin.java @@ -0,0 +1,54 @@ +package net.ornithemc.osl.networking.impl; + +import java.util.List; +import java.util.Set; + +import org.objectweb.asm.tree.ClassNode; + +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import net.ornithemc.osl.core.impl.util.MinecraftVersion; + +public class NetworkingMixinPlugin implements IMixinConfigPlugin { + + public static final boolean MINECRAFT_DISCONNECT_METHOD_EXISTS = MinecraftVersion.resolve().compareTo("19w06a") >= 0; + + @Override + public void onLoad(String mixinPackage) { + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if ("net.ornithemc.osl.networking.impl.mixin.client.MinecraftMixinNew".equals(mixinClassName)) { + return MINECRAFT_DISCONNECT_METHOD_EXISTS; + } + if ("net.ornithemc.osl.networking.impl.mixin.client.MinecraftMixinOld".equals(mixinClassName)) { + return !MINECRAFT_DISCONNECT_METHOD_EXISTS; + } + + return true; + } + + @Override + public void acceptTargets(Set myTargets, Set otherTargets) { + } + + @Override + public List getMixins() { + return null; + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } +} diff --git a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..e067a1831 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +public interface ClientNetworkHandlerAccess extends NetworkHandlerAccess { + + ClientConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java new file mode 100644 index 000000000..1d596400b --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +public interface ServerNetworkHandlerAccess extends NetworkHandlerAccess { + + ServerConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java index ef5dbdfbb..e43da06c8 100644 --- a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientPlayNetworkHandlerMixin.java @@ -1,5 +1,6 @@ package net.ornithemc.osl.networking.impl.mixin.client; +import java.net.SocketAddress; import java.util.LinkedHashSet; import java.util.Set; @@ -13,23 +14,36 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.network.Connection; import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; +import net.minecraft.network.packet.s2c.play.DisconnectS2CPacket; +import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.text.Text; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.AddressParser; import net.ornithemc.osl.networking.impl.HandshakePayload; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ClientPlayNetworkHandler.class) -public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { +public class ClientPlayNetworkHandlerMixin implements ClientNetworkHandlerAccess { - @Shadow @Final private Minecraft minecraft; + @Shadow @Final + private Minecraft minecraft; + @Shadow @Final + private Connection connection; + @Unique + private ClientConnectionContext connectionContext; /** * Channels that the server is listening to. */ - @Unique private Set serverChannels; + @Unique + private Set serverChannels; @Inject( method = "handleLogin", @@ -38,10 +52,34 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { ) ) private void osl$networking$handleLogin(CallbackInfo ci) { + if (minecraft.isIntegratedServerRunning()) { + IntegratedServer server = minecraft.getServer(); + String worldName = server.getWorldName(); + + connectionContext = new ClientConnectionContext(minecraft, worldName); + } else { + SocketAddress address = connection.getAddress(); + + String serverAddress = AddressParser.getAddress(address); + int serverPort = AddressParser.getPort(address); + + connectionContext = new ClientConnectionContext(minecraft, serverAddress, serverPort); + } + // send channel registration data as soon as login occurs ClientPlayNetworkingImpl.sendNoCheck(HandshakePayload.CHANNEL, HandshakePayload.client()); - ClientConnectionEvents.LOGIN.invoker().accept(minecraft); + ClientConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "handleDisconnect", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(DisconnectS2CPacket packet, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(packet.getReason())); } @Inject( @@ -50,9 +88,8 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ClientConnectionEvents.DISCONNECT.invoker().accept(minecraft); - serverChannels = null; + private void osl$networking$handleDisconnect(Text reason, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(reason)); } @Inject( @@ -68,6 +105,11 @@ public class ClientPlayNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ClientConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$isPlayReady() { return serverChannels != null; diff --git a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java deleted file mode 100644 index 2749c72de..000000000 --- a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java +++ /dev/null @@ -1,22 +0,0 @@ -package net.ornithemc.osl.networking.impl.mixin.client; - -import org.spongepowered.asm.mixin.Mixin; - -import net.minecraft.client.Minecraft; -import net.minecraft.util.BlockableEventLoop; - -import net.ornithemc.osl.networking.impl.access.TaskRunnerAccess; - -@Mixin(Minecraft.class) -public abstract class MinecraftMixin extends BlockableEventLoop implements TaskRunnerAccess { - - private MinecraftMixin(String name) { - super(name); - } - - @Override - public boolean osl$networking$submit(Runnable task) { - this.execute(task); - return true; - } -} diff --git a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixinNew.java b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixinNew.java new file mode 100644 index 000000000..c31e69f0a --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixinNew.java @@ -0,0 +1,40 @@ +package net.ornithemc.osl.networking.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.client.world.ClientWorld; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +@Mixin(Minecraft.class) +public class MinecraftMixinNew { + + @Shadow + private ClientWorld world; + + @Shadow + private ClientPlayNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "m_62273487", // disconnect + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(CallbackInfo ci) { + if (world != null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixinOld.java b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixinOld.java new file mode 100644 index 000000000..e01c0f436 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixinOld.java @@ -0,0 +1,41 @@ +package net.ornithemc.osl.networking.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.network.handler.ClientPlayNetworkHandler; +import net.minecraft.client.world.ClientWorld; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +@Mixin(Minecraft.class) +public class MinecraftMixinOld { + + @Shadow + private ClientWorld world; + + @Shadow + private ClientPlayNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "m_62116716", // setWorld + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(ClientWorld world, Screen screen, CallbackInfo ci) { + if (this.world != null && world == null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java deleted file mode 100644 index eb2bc2be6..000000000 --- a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/MinecraftServerMixin.java +++ /dev/null @@ -1,22 +0,0 @@ -package net.ornithemc.osl.networking.impl.mixin.common; - -import org.spongepowered.asm.mixin.Mixin; - -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.BlockableEventLoop; - -import net.ornithemc.osl.networking.impl.access.TaskRunnerAccess; - -@Mixin(MinecraftServer.class) -public abstract class MinecraftServerMixin extends BlockableEventLoop implements TaskRunnerAccess { - - private MinecraftServerMixin(String name) { - super(name); - } - - @Override - public boolean osl$networking$submit(Runnable task) { - this.execute(task); - return true; - } -} diff --git a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java index eaca81ebb..2f8c8bce4 100644 --- a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java +++ b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/PlayerManagerMixin.java @@ -7,12 +7,15 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import net.minecraft.network.Connection; +import com.llamalad7.mixinextras.sugar.Local; + import net.minecraft.server.MinecraftServer; import net.minecraft.server.PlayerManager; import net.minecraft.server.entity.living.player.ServerPlayerEntity; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; @Mixin(PlayerManager.class) public class PlayerManagerMixin { @@ -25,7 +28,23 @@ public class PlayerManagerMixin { value = "TAIL" ) ) - private void osl$networking$handleLogin(Connection connection, ServerPlayerEntity player, CallbackInfo ci) { - ServerConnectionEvents.LOGIN.invoker().accept(server, player); + private void osl$networking$handleLogin(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "remove", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); } } diff --git a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java index ac66d4400..270f4b80b 100644 --- a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/common/ServerPlayNetworkHandlerMixin.java @@ -15,22 +15,40 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.entity.living.player.ServerPlayerEntity; import net.minecraft.server.network.handler.ServerPlayNetworkHandler; +import net.minecraft.text.Text; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; -import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ServerPlayNetworkHandler.class) -public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { +public class ServerPlayNetworkHandlerMixin implements ServerNetworkHandlerAccess { - @Shadow @Final private MinecraftServer server; - @Shadow @Final private ServerPlayerEntity player; + @Shadow @Final + private MinecraftServer server; + @Shadow + private ServerPlayerEntity player; + + @Unique + private ServerConnectionContext connectionContext; /** * Channels that the client is listening to. */ - @Unique private Set clientChannels; + @Unique + private Set clientChannels; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$initConnectionContext(CallbackInfo ci) { + connectionContext = new ServerConnectionContext(server, (ServerPlayNetworkHandler) (Object) this); + } @Inject( method = "onDisconnect", @@ -38,9 +56,8 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ServerConnectionEvents.DISCONNECT.invoker().accept(server, player); - clientChannels = null; + private void osl$networking$handleDisconnect(Text reason, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(reason)); } @Inject( @@ -56,6 +73,11 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess { } } + @Override + public ServerConnectionContext osl$networking$connectionContext() { + return connectionContext; + } + @Override public boolean osl$networking$isPlayReady() { return clientChannels != null; diff --git a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/MinecraftServerMixin.java b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/MinecraftServerMixin.java new file mode 100644 index 000000000..3c389c76d --- /dev/null +++ b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/MinecraftServerMixin.java @@ -0,0 +1,42 @@ +package net.ornithemc.osl.networking.impl.mixin.server; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.PlayerManagerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + + @Shadow + private PlayerManager playerManager; + + @Inject( + method = "stop", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$stop(CallbackInfo ci) { + List players = ((PlayerManagerAccess) this.playerManager).osl$networking$getAll(); + + for (ServerPlayerEntity player : players) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json index 0ab46b3f7..932d872aa 100644 --- a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json +++ b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json @@ -23,6 +23,8 @@ "osl-core": "\u003e\u003d0.7.0", "osl-entrypoints": "\u003e\u003d0.5.0", "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", "osl-networking": "\u003e\u003d0.9.0" }, "name": "OSL Networking Implementation", diff --git a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/resources/osl.networking-impl.mixins.json b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/resources/osl.networking-impl.mixins.json index f64bbc230..c71fb00f2 100644 --- a/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/resources/osl.networking-impl.mixins.json +++ b/libraries/networking-impl/networking-impl-mc18w43a-mc1.14.4/src/main/resources/osl.networking-impl.mixins.json @@ -3,18 +3,20 @@ "minVersion": "0.8", "package": "net.ornithemc.osl.networking.impl.mixin", "compatibilityLevel": "JAVA_8", + "plugin": "net.ornithemc.osl.networking.impl.NetworkingMixinPlugin", "mixins": [ "common.CustomPayloadC2SPacketMixin", "common.CustomPayloadS2CPacketMixin", - "common.MinecraftServerMixin", "common.PlayerManagerMixin", "common.ServerPlayNetworkHandlerMixin" ], "client": [ "client.ClientPlayNetworkHandlerMixin", - "client.MinecraftMixin" + "client.MinecraftMixinNew", + "client.MinecraftMixinOld" ], "server": [ + "server.MinecraftServerMixin" ], "injectors": { "defaultRequire": 1 diff --git a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java index eb5576241..e95e2602f 100644 --- a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java +++ b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java @@ -10,7 +10,7 @@ import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.StringChannelIdentifierParser; import net.ornithemc.osl.networking.impl.access.CustomPayloadPacketAccess; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; public class CustomPayloadPacket extends Packet implements CustomPayloadPacketAccess { @@ -52,8 +52,8 @@ public void write(DataOutputStream output) throws IOException { @Override public void handle(PacketHandler handler) { - if (handler instanceof INetworkHandler) { - ((INetworkHandler)handler).osl$networking$handleCustomPayload(this); + if (handler instanceof PacketHandlerAccess) { + ((PacketHandlerAccess) handler).osl$networking$handleCustomPayload(this); } } diff --git a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/Networking.java b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/Networking.java index 7c0a837b4..58fbbc991 100644 --- a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/Networking.java +++ b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/Networking.java @@ -5,8 +5,9 @@ import net.ornithemc.osl.entrypoints.api.server.ServerModInitializer; import net.ornithemc.osl.lifecycle.api.server.MinecraftServerEvents; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; import net.ornithemc.osl.networking.impl.mixin.common.PacketAccessor; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; public class Networking implements ModInitializer, ClientModInitializer, ServerModInitializer { @@ -27,8 +28,11 @@ public void initServer() { MinecraftServerEvents.STOP.register(ServerPlayNetworkingImpl::destroy); ServerPlayNetworkingImpl.setUpPacketFactory(CustomPayloadPacket::new); ServerPlayNetworkingImpl.registerListener(HandshakePayload.CHANNEL, HandshakePayload::new, (context, payload) -> { - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ServerConnectionEvents.PLAY_READY.invoker().accept(context.server(), context.player()); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) context.networkHandler(); + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ServerConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } } diff --git a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java similarity index 59% rename from libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java rename to libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java index 283c296dd..d5dc849d4 100644 --- a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java +++ b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java @@ -1,8 +1,8 @@ -package net.ornithemc.osl.networking.impl.interfaces.mixin; +package net.ornithemc.osl.networking.impl.access; import net.ornithemc.osl.networking.impl.CustomPayloadPacket; -public interface INetworkHandler { +public interface PacketHandlerAccess { boolean osl$networking$handleCustomPayload(CustomPayloadPacket packet); diff --git a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java new file mode 100644 index 000000000..1d596400b --- /dev/null +++ b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +public interface ServerNetworkHandlerAccess extends NetworkHandlerAccess { + + ServerConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/PlayerManagerMixin.java b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/PlayerManagerMixin.java new file mode 100644 index 000000000..445e1c415 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/PlayerManagerMixin.java @@ -0,0 +1,37 @@ +package net.ornithemc.osl.networking.impl.mixin.server; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.mob.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final private MinecraftServer server; + + @Inject( + method = "remove", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } +} diff --git a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java index 15b8f09f4..6b80b7e9a 100644 --- a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java @@ -18,6 +18,8 @@ import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; import net.ornithemc.osl.networking.impl.Constants; import net.ornithemc.osl.networking.impl.HandshakePayload; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; @Mixin(ServerLoginNetworkHandler.class) @@ -28,7 +30,8 @@ public class ServerLoginNetworkHandlerMixin { /** * is the client also running OSL? */ - @Unique private boolean ornithe; + @Unique + private boolean ornithe; @Inject( method = "handleHandshake", @@ -55,7 +58,10 @@ public class ServerLoginNetworkHandlerMixin { ServerPlayNetworkingImpl.sendNoCheck(player, HandshakePayload.CHANNEL, HandshakePayload.server()); } - ServerConnectionEvents.LOGIN.invoker().accept(server, player); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.LOGIN.invoker().accept(connectionContext); } } } diff --git a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java index 381c06974..2928389be 100644 --- a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java @@ -3,6 +3,7 @@ import java.util.LinkedHashSet; import java.util.Set; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -15,22 +16,39 @@ import net.minecraft.server.network.handler.ServerPlayNetworkHandler; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; -import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; import net.ornithemc.osl.networking.impl.CustomPayloadPacket; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ServerPlayNetworkHandler.class) -public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess, INetworkHandler { +public class ServerPlayNetworkHandlerMixin implements ServerNetworkHandlerAccess, PacketHandlerAccess { - @Shadow private MinecraftServer server; - @Shadow private ServerPlayerEntity player; + @Shadow @Final + private MinecraftServer server; + @Shadow + private ServerPlayerEntity player; + + @Unique + private ServerConnectionContext connectionContext; /** * Channels that the client is listening to. */ - @Unique private Set clientChannels; + @Unique + private Set clientChannels; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$initConnectionContext(CallbackInfo ci) { + connectionContext = new ServerConnectionContext(server, (ServerPlayNetworkHandler) (Object) this); + } @Inject( method = "onDisconnect", @@ -38,9 +56,13 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess, INet value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ServerConnectionEvents.DISCONNECT.invoker().accept(server, player); - clientChannels = null; + private void osl$networking$handleDisconnect(String reason, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(reason)); + } + + @Override + public ServerConnectionContext osl$networking$connectionContext() { + return connectionContext; } @Override diff --git a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/resources/fabric.mod.json b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/resources/fabric.mod.json index a277a3cb0..a39a44db5 100644 --- a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/resources/fabric.mod.json +++ b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/resources/fabric.mod.json @@ -23,6 +23,8 @@ "osl-core": "\u003e\u003d0.7.0", "osl-entrypoints": "\u003e\u003d0.5.0", "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", "osl-networking": "\u003e\u003d0.9.0" }, "name": "OSL Networking Implementation", diff --git a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/resources/osl.networking-impl.mixins.json b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/resources/osl.networking-impl.mixins.json index f0a604fc8..d0d42247f 100644 --- a/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/resources/osl.networking-impl.mixins.json +++ b/libraries/networking-impl/networking-impl-mca0.1.2_01-mca0.2.8/src/main/resources/osl.networking-impl.mixins.json @@ -10,6 +10,7 @@ "client": [ ], "server": [ + "server.PlayerManagerMixin", "server.ServerLoginNetworkHandlerMixin", "server.ServerPlayNetworkHandlerMixin" ], diff --git a/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java index eb5576241..e95e2602f 100644 --- a/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java +++ b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java @@ -10,7 +10,7 @@ import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.StringChannelIdentifierParser; import net.ornithemc.osl.networking.impl.access.CustomPayloadPacketAccess; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; public class CustomPayloadPacket extends Packet implements CustomPayloadPacketAccess { @@ -52,8 +52,8 @@ public void write(DataOutputStream output) throws IOException { @Override public void handle(PacketHandler handler) { - if (handler instanceof INetworkHandler) { - ((INetworkHandler)handler).osl$networking$handleCustomPayload(this); + if (handler instanceof PacketHandlerAccess) { + ((PacketHandlerAccess) handler).osl$networking$handleCustomPayload(this); } } diff --git a/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/Networking.java b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/Networking.java index df5a55ff9..4fd4b8116 100644 --- a/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/Networking.java +++ b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/Networking.java @@ -5,7 +5,8 @@ import net.ornithemc.osl.entrypoints.api.server.ServerModInitializer; import net.ornithemc.osl.lifecycle.api.client.MinecraftClientEvents; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; import net.ornithemc.osl.networking.impl.mixin.common.PacketAccessor; @@ -29,8 +30,11 @@ public void initClient() { // send channel registration data as a response to receiving server channel registration data ClientPlayNetworkingImpl.sendNoCheck(HandshakePayload.CHANNEL, HandshakePayload.client()); - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ClientConnectionEvents.PLAY_READY.invoker().accept(context.minecraft()); + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) context.networkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ClientConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } diff --git a/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..e067a1831 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +public interface ClientNetworkHandlerAccess extends NetworkHandlerAccess { + + ClientConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java similarity index 59% rename from libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java rename to libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java index 283c296dd..d5dc849d4 100644 --- a/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java +++ b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java @@ -1,8 +1,8 @@ -package net.ornithemc.osl.networking.impl.interfaces.mixin; +package net.ornithemc.osl.networking.impl.access; import net.ornithemc.osl.networking.impl.CustomPayloadPacket; -public interface INetworkHandler { +public interface PacketHandlerAccess { boolean osl$networking$handleCustomPayload(CustomPayloadPacket packet); diff --git a/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java index c48e552f6..cf2bd3228 100644 --- a/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java @@ -1,8 +1,10 @@ package net.ornithemc.osl.networking.impl.mixin.client; +import java.net.SocketAddress; import java.util.LinkedHashSet; import java.util.Set; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -13,24 +15,36 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.network.handler.ClientNetworkHandler; import net.minecraft.client.world.MultiplayerWorld; +import net.minecraft.network.Connection; +import net.minecraft.network.packet.DisconnectPacket; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.AddressParser; import net.ornithemc.osl.networking.impl.CustomPayloadPacket; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ClientNetworkHandler.class) -public class ClientNetworkHandlerMixin implements NetworkHandlerAccess, INetworkHandler { +public class ClientNetworkHandlerMixin implements ClientNetworkHandlerAccess, PacketHandlerAccess { - @Shadow private Minecraft minecraft; - @Shadow private MultiplayerWorld world; + @Shadow @Final + private Minecraft minecraft; + @Shadow @Final + private MultiplayerWorld world; + @Shadow @Final + private Connection connection; + @Unique + private ClientConnectionContext connectionContext; /** * Channels that the server is listening to. */ - @Unique private Set serverChannels; + @Unique + private Set serverChannels; @Inject( method = "handleLogin", @@ -39,7 +53,26 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess, INetwork ) ) private void osl$networking$handleLogin(CallbackInfo ci) { - ClientConnectionEvents.LOGIN.invoker().accept(minecraft); + { + SocketAddress address = connection.socket.getRemoteSocketAddress(); + + String serverAddress = AddressParser.getAddress(address); + int serverPort = AddressParser.getPort(address); + + connectionContext = new ClientConnectionContext(minecraft, serverAddress, serverPort); + } + + ClientConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "handleDisconnect", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(DisconnectPacket packet, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(packet.reason)); } @Inject( @@ -48,9 +81,13 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess, INetwork value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ClientConnectionEvents.DISCONNECT.invoker().accept(minecraft); - serverChannels = null; + private void osl$networking$handleDisconnect(String reason, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(reason)); + } + + @Override + public ClientConnectionContext osl$networking$connectionContext() { + return connectionContext; } @Override diff --git a/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java new file mode 100644 index 000000000..4caa6dd3a --- /dev/null +++ b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java @@ -0,0 +1,42 @@ +package net.ornithemc.osl.networking.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.mob.player.ClientPlayerEntity; +import net.minecraft.client.world.MultiplayerWorld; +import net.minecraft.world.World; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.LocalClientPlayerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +@Mixin(Minecraft.class) +public class MinecraftMixin { + + @Shadow + private World world; + @Shadow + private ClientPlayerEntity player; + + @Inject( + method = "setWorld(Lnet/minecraft/world/World;Ljava/lang/String;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(World world, String title, CallbackInfo ci) { + if (this.world != null && this.world instanceof MultiplayerWorld && world == null) { + LocalClientPlayerAccess player = (LocalClientPlayerAccess) this.player; + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) player.osl$networking$getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/resources/fabric.mod.json b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/resources/fabric.mod.json index f744be9bd..fde6d33d0 100644 --- a/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/resources/fabric.mod.json +++ b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/resources/fabric.mod.json @@ -23,6 +23,8 @@ "osl-core": "\u003e\u003d0.7.0", "osl-entrypoints": "\u003e\u003d0.5.0", "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", "osl-networking": "\u003e\u003d0.9.0" }, "name": "OSL Networking Implementation", diff --git a/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/resources/osl.networking-impl.classtweaker b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/resources/osl.networking-impl.classtweaker new file mode 100644 index 000000000..938816a7d --- /dev/null +++ b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/resources/osl.networking-impl.classtweaker @@ -0,0 +1,3 @@ +classTweaker v1 named + +accessible field net/minecraft/network/Connection socket Ljava/net/Socket; \ No newline at end of file diff --git a/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/resources/osl.networking-impl.mixins.json b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/resources/osl.networking-impl.mixins.json index c9867435e..ded2c522a 100644 --- a/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/resources/osl.networking-impl.mixins.json +++ b/libraries/networking-impl/networking-impl-mca1.0.16-mca1.2.6/src/main/resources/osl.networking-impl.mixins.json @@ -10,7 +10,8 @@ "client": [ "client.ClientNetworkHandlerMixin", "client.HandshakePacketMixin", - "client.LocalClientPlayerEntityMixin" + "client.LocalClientPlayerEntityMixin", + "client.MinecraftMixin" ], "server": [ ], diff --git a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java index eb5576241..e95e2602f 100644 --- a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java +++ b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java @@ -10,7 +10,7 @@ import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.StringChannelIdentifierParser; import net.ornithemc.osl.networking.impl.access.CustomPayloadPacketAccess; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; public class CustomPayloadPacket extends Packet implements CustomPayloadPacketAccess { @@ -52,8 +52,8 @@ public void write(DataOutputStream output) throws IOException { @Override public void handle(PacketHandler handler) { - if (handler instanceof INetworkHandler) { - ((INetworkHandler)handler).osl$networking$handleCustomPayload(this); + if (handler instanceof PacketHandlerAccess) { + ((PacketHandlerAccess) handler).osl$networking$handleCustomPayload(this); } } diff --git a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/Networking.java b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/Networking.java index 85d0270a1..cc0bc48a7 100644 --- a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/Networking.java +++ b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/Networking.java @@ -7,9 +7,12 @@ import net.ornithemc.osl.lifecycle.api.server.MinecraftServerEvents; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; import net.ornithemc.osl.networking.impl.mixin.common.PacketAccessor; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; public class Networking implements ModInitializer, ClientModInitializer, ServerModInitializer { @@ -32,8 +35,11 @@ public void initClient() { // send channel registration data as a response to receiving server channel registration data ClientPlayNetworkingImpl.sendNoCheck(HandshakePayload.CHANNEL, HandshakePayload.client()); - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ClientConnectionEvents.PLAY_READY.invoker().accept(context.minecraft()); + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) context.networkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ClientConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } @@ -43,8 +49,11 @@ public void initServer() { MinecraftServerEvents.STOP.register(ServerPlayNetworkingImpl::destroy); ServerPlayNetworkingImpl.setUpPacketFactory(CustomPayloadPacket::new); ServerPlayNetworkingImpl.registerListener(HandshakePayload.CHANNEL, HandshakePayload::new, (context, payload) -> { - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ServerConnectionEvents.PLAY_READY.invoker().accept(context.server(), context.player()); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) context.networkHandler(); + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ServerConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } } diff --git a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..e067a1831 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +public interface ClientNetworkHandlerAccess extends NetworkHandlerAccess { + + ClientConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java similarity index 59% rename from libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java rename to libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java index 283c296dd..d5dc849d4 100644 --- a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java +++ b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java @@ -1,8 +1,8 @@ -package net.ornithemc.osl.networking.impl.interfaces.mixin; +package net.ornithemc.osl.networking.impl.access; import net.ornithemc.osl.networking.impl.CustomPayloadPacket; -public interface INetworkHandler { +public interface PacketHandlerAccess { boolean osl$networking$handleCustomPayload(CustomPayloadPacket packet); diff --git a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java new file mode 100644 index 000000000..1d596400b --- /dev/null +++ b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +public interface ServerNetworkHandlerAccess extends NetworkHandlerAccess { + + ServerConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java index c48e552f6..a660862df 100644 --- a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java @@ -1,8 +1,10 @@ package net.ornithemc.osl.networking.impl.mixin.client; +import java.net.SocketAddress; import java.util.LinkedHashSet; import java.util.Set; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -13,24 +15,36 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.network.handler.ClientNetworkHandler; import net.minecraft.client.world.MultiplayerWorld; +import net.minecraft.network.Connection; +import net.minecraft.network.packet.DisconnectPacket; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.AddressParser; import net.ornithemc.osl.networking.impl.CustomPayloadPacket; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ClientNetworkHandler.class) -public class ClientNetworkHandlerMixin implements NetworkHandlerAccess, INetworkHandler { +public class ClientNetworkHandlerMixin implements ClientNetworkHandlerAccess, PacketHandlerAccess { - @Shadow private Minecraft minecraft; - @Shadow private MultiplayerWorld world; + @Shadow @Final + private Minecraft minecraft; + @Shadow @Final + private MultiplayerWorld world; + @Shadow @Final + private Connection connection; + @Unique + private ClientConnectionContext connectionContext; /** * Channels that the server is listening to. */ - @Unique private Set serverChannels; + @Unique + private Set serverChannels; @Inject( method = "handleLogin", @@ -39,7 +53,26 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess, INetwork ) ) private void osl$networking$handleLogin(CallbackInfo ci) { - ClientConnectionEvents.LOGIN.invoker().accept(minecraft); + { + SocketAddress address = connection.socket.getRemoteSocketAddress(); + + String serverAddress = AddressParser.getAddress(address); + int serverPort = AddressParser.getPort(address); + + connectionContext = new ClientConnectionContext(minecraft, serverAddress, serverPort); + } + + ClientConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "handleDisconnect", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(DisconnectPacket packet, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(packet.reason)); } @Inject( @@ -48,9 +81,15 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess, INetwork value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ClientConnectionEvents.DISCONNECT.invoker().accept(minecraft); - serverChannels = null; + private void osl$networking$handleDisconnect(String reason, Object[] args, CallbackInfo ci) { + connectionContext.offerDisconnectReason(args == null + ? TextComponents.translatable(reason) + : TextComponents.translatable(reason, args)); + } + + @Override + public ClientConnectionContext osl$networking$connectionContext() { + return connectionContext; } @Override diff --git a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java new file mode 100644 index 000000000..6600fd992 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java @@ -0,0 +1,41 @@ +package net.ornithemc.osl.networking.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.handler.ClientNetworkHandler; +import net.minecraft.client.world.MultiplayerWorld; +import net.minecraft.world.World; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +@Mixin(Minecraft.class) +public class MinecraftMixin { + + @Shadow + private World world; + + @Shadow + private ClientNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "setWorld(Lnet/minecraft/world/World;Ljava/lang/String;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(World world, String title, CallbackInfo ci) { + if (this.world != null && this.world instanceof MultiplayerWorld && world == null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/PlayerManagerMixin.java b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/PlayerManagerMixin.java new file mode 100644 index 000000000..445e1c415 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/PlayerManagerMixin.java @@ -0,0 +1,37 @@ +package net.ornithemc.osl.networking.impl.mixin.server; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.mob.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final private MinecraftServer server; + + @Inject( + method = "remove", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } +} diff --git a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java index 15b8f09f4..6b80b7e9a 100644 --- a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java @@ -18,6 +18,8 @@ import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; import net.ornithemc.osl.networking.impl.Constants; import net.ornithemc.osl.networking.impl.HandshakePayload; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; @Mixin(ServerLoginNetworkHandler.class) @@ -28,7 +30,8 @@ public class ServerLoginNetworkHandlerMixin { /** * is the client also running OSL? */ - @Unique private boolean ornithe; + @Unique + private boolean ornithe; @Inject( method = "handleHandshake", @@ -55,7 +58,10 @@ public class ServerLoginNetworkHandlerMixin { ServerPlayNetworkingImpl.sendNoCheck(player, HandshakePayload.CHANNEL, HandshakePayload.server()); } - ServerConnectionEvents.LOGIN.invoker().accept(server, player); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.LOGIN.invoker().accept(connectionContext); } } } diff --git a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java index 381c06974..45a75421e 100644 --- a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java @@ -3,6 +3,7 @@ import java.util.LinkedHashSet; import java.util.Set; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -15,22 +16,39 @@ import net.minecraft.server.network.handler.ServerPlayNetworkHandler; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; -import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; import net.ornithemc.osl.networking.impl.CustomPayloadPacket; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ServerPlayNetworkHandler.class) -public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess, INetworkHandler { +public class ServerPlayNetworkHandlerMixin implements ServerNetworkHandlerAccess, PacketHandlerAccess { - @Shadow private MinecraftServer server; - @Shadow private ServerPlayerEntity player; + @Shadow @Final + private MinecraftServer server; + @Shadow + private ServerPlayerEntity player; + + @Unique + private ServerConnectionContext connectionContext; /** * Channels that the client is listening to. */ - @Unique private Set clientChannels; + @Unique + private Set clientChannels; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$initConnectionContext(CallbackInfo ci) { + connectionContext = new ServerConnectionContext(server, (ServerPlayNetworkHandler) (Object) this); + } @Inject( method = "onDisconnect", @@ -38,9 +56,15 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess, INet value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ServerConnectionEvents.DISCONNECT.invoker().accept(server, player); - clientChannels = null; + private void osl$networking$handleDisconnect(String reason, Object[] args, CallbackInfo ci) { + connectionContext.offerDisconnectReason(args == null + ? TextComponents.translatable(reason) + : TextComponents.translatable(reason, args)); + } + + @Override + public ServerConnectionContext osl$networking$connectionContext() { + return connectionContext; } @Override diff --git a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/resources/fabric.mod.json b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/resources/fabric.mod.json index f89c12ae4..fd4148eb9 100644 --- a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/resources/fabric.mod.json +++ b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/resources/fabric.mod.json @@ -23,6 +23,8 @@ "osl-core": "\u003e\u003d0.7.0", "osl-entrypoints": "\u003e\u003d0.5.0", "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", "osl-networking": "\u003e\u003d0.9.0" }, "name": "OSL Networking Implementation", diff --git a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/resources/osl.networking-impl.classtweaker b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/resources/osl.networking-impl.classtweaker new file mode 100644 index 000000000..938816a7d --- /dev/null +++ b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/resources/osl.networking-impl.classtweaker @@ -0,0 +1,3 @@ +classTweaker v1 named + +accessible field net/minecraft/network/Connection socket Ljava/net/Socket; \ No newline at end of file diff --git a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/resources/osl.networking-impl.mixins.json b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/resources/osl.networking-impl.mixins.json index 95fccaf71..4c07c796d 100644 --- a/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/resources/osl.networking-impl.mixins.json +++ b/libraries/networking-impl/networking-impl-mcb1.0-mcb1.4_01/src/main/resources/osl.networking-impl.mixins.json @@ -9,9 +9,11 @@ ], "client": [ "client.ClientNetworkHandlerMixin", - "client.HandshakePacketMixin" + "client.HandshakePacketMixin", + "client.MinecraftMixin" ], "server": [ + "server.PlayerManagerMixin", "server.ServerLoginNetworkHandlerMixin", "server.ServerPlayNetworkHandlerMixin" ], diff --git a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java index fd63fa5a8..43bb1345f 100644 --- a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java +++ b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/CustomPayloadPacket.java @@ -11,7 +11,7 @@ import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.StringChannelIdentifierParser; import net.ornithemc.osl.networking.impl.access.CustomPayloadPacketAccess; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; public class CustomPayloadPacket extends Packet implements CustomPayloadPacketAccess { @@ -65,8 +65,8 @@ public void write(DataOutputStream output) { @Override public void handle(PacketHandler handler) { - if (handler instanceof INetworkHandler) { - ((INetworkHandler)handler).osl$networking$handleCustomPayload(this); + if (handler instanceof PacketHandlerAccess) { + ((PacketHandlerAccess) handler).osl$networking$handleCustomPayload(this); } } diff --git a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java index 2bb2cf193..f5b0a2cb0 100644 --- a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java +++ b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/Networking.java @@ -7,9 +7,12 @@ import net.ornithemc.osl.lifecycle.api.server.MinecraftServerEvents; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; import net.ornithemc.osl.networking.impl.mixin.common.PacketAccessor; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; public class Networking implements ModInitializer, ClientModInitializer, ServerModInitializer { @@ -32,8 +35,11 @@ public void initClient() { // send channel registration data as a response to receiving server channel registration data ClientPlayNetworkingImpl.sendNoCheck(HandshakePayload.CHANNEL, HandshakePayload.client()); - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ClientConnectionEvents.PLAY_READY.invoker().accept(context.minecraft()); + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) context.networkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ClientConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } @@ -43,8 +49,11 @@ public void initServer() { MinecraftServerEvents.STOP.register(ServerPlayNetworkingImpl::destroy); ServerPlayNetworkingImpl.setUpPacketFactory(CustomPayloadPacket::new); ServerPlayNetworkingImpl.registerListener(HandshakePayload.CHANNEL, HandshakePayload::new, (context, payload) -> { - ((NetworkHandlerAccess)context.networkHandler()).osl$networking$registerChannels(payload.channels); - ServerConnectionEvents.PLAY_READY.invoker().accept(context.server(), context.player()); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) context.networkHandler(); + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + networkHandler.osl$networking$registerChannels(payload.channels); + ServerConnectionEvents.PLAY_READY.invoker().accept(connectionContext); }); } } diff --git a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..e067a1831 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +public interface ClientNetworkHandlerAccess extends NetworkHandlerAccess { + + ClientConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java similarity index 59% rename from libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java rename to libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java index 283c296dd..d5dc849d4 100644 --- a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/interfaces/mixin/INetworkHandler.java +++ b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/access/PacketHandlerAccess.java @@ -1,8 +1,8 @@ -package net.ornithemc.osl.networking.impl.interfaces.mixin; +package net.ornithemc.osl.networking.impl.access; import net.ornithemc.osl.networking.impl.CustomPayloadPacket; -public interface INetworkHandler { +public interface PacketHandlerAccess { boolean osl$networking$handleCustomPayload(CustomPayloadPacket packet); diff --git a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java new file mode 100644 index 000000000..1d596400b --- /dev/null +++ b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +public interface ServerNetworkHandlerAccess extends NetworkHandlerAccess { + + ServerConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java index c48e552f6..a660862df 100644 --- a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/ClientNetworkHandlerMixin.java @@ -1,8 +1,10 @@ package net.ornithemc.osl.networking.impl.mixin.client; +import java.net.SocketAddress; import java.util.LinkedHashSet; import java.util.Set; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -13,24 +15,36 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.network.handler.ClientNetworkHandler; import net.minecraft.client.world.MultiplayerWorld; +import net.minecraft.network.Connection; +import net.minecraft.network.packet.DisconnectPacket; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.AddressParser; import net.ornithemc.osl.networking.impl.CustomPayloadPacket; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; import net.ornithemc.osl.networking.impl.client.ClientPlayNetworkingImpl; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ClientNetworkHandler.class) -public class ClientNetworkHandlerMixin implements NetworkHandlerAccess, INetworkHandler { +public class ClientNetworkHandlerMixin implements ClientNetworkHandlerAccess, PacketHandlerAccess { - @Shadow private Minecraft minecraft; - @Shadow private MultiplayerWorld world; + @Shadow @Final + private Minecraft minecraft; + @Shadow @Final + private MultiplayerWorld world; + @Shadow @Final + private Connection connection; + @Unique + private ClientConnectionContext connectionContext; /** * Channels that the server is listening to. */ - @Unique private Set serverChannels; + @Unique + private Set serverChannels; @Inject( method = "handleLogin", @@ -39,7 +53,26 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess, INetwork ) ) private void osl$networking$handleLogin(CallbackInfo ci) { - ClientConnectionEvents.LOGIN.invoker().accept(minecraft); + { + SocketAddress address = connection.socket.getRemoteSocketAddress(); + + String serverAddress = AddressParser.getAddress(address); + int serverPort = AddressParser.getPort(address); + + connectionContext = new ClientConnectionContext(minecraft, serverAddress, serverPort); + } + + ClientConnectionEvents.LOGIN.invoker().accept(connectionContext); + } + + @Inject( + method = "handleDisconnect", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(DisconnectPacket packet, CallbackInfo ci) { + connectionContext.offerDisconnectReason(TextComponents.resolve(packet.reason)); } @Inject( @@ -48,9 +81,15 @@ public class ClientNetworkHandlerMixin implements NetworkHandlerAccess, INetwork value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ClientConnectionEvents.DISCONNECT.invoker().accept(minecraft); - serverChannels = null; + private void osl$networking$handleDisconnect(String reason, Object[] args, CallbackInfo ci) { + connectionContext.offerDisconnectReason(args == null + ? TextComponents.translatable(reason) + : TextComponents.translatable(reason, args)); + } + + @Override + public ClientConnectionContext osl$networking$connectionContext() { + return connectionContext; } @Override diff --git a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java new file mode 100644 index 000000000..6600fd992 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/client/MinecraftMixin.java @@ -0,0 +1,41 @@ +package net.ornithemc.osl.networking.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.handler.ClientNetworkHandler; +import net.minecraft.client.world.MultiplayerWorld; +import net.minecraft.world.World; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ClientNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +@Mixin(Minecraft.class) +public class MinecraftMixin { + + @Shadow + private World world; + + @Shadow + private ClientNetworkHandler getNetworkHandler() { return null; } + + @Inject( + method = "setWorld(Lnet/minecraft/world/World;Ljava/lang/String;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$disconnect(World world, String title, CallbackInfo ci) { + if (this.world != null && this.world instanceof MultiplayerWorld && world == null) { + ClientNetworkHandlerAccess networkHandler = (ClientNetworkHandlerAccess) getNetworkHandler(); + ClientConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ClientConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } + } +} diff --git a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/PlayerManagerMixin.java b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/PlayerManagerMixin.java new file mode 100644 index 000000000..445e1c415 --- /dev/null +++ b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/PlayerManagerMixin.java @@ -0,0 +1,37 @@ +package net.ornithemc.osl.networking.impl.mixin.server; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.mob.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final private MinecraftServer server; + + @Inject( + method = "remove", + at = @At( + value = "HEAD" + ) + ) + private void osl$networking$handleDisconnect(CallbackInfo ci, @Local ServerPlayerEntity player) { + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.DISCONNECT.invoker().accept(connectionContext); + } +} diff --git a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java index 15b8f09f4..6b80b7e9a 100644 --- a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerLoginNetworkHandlerMixin.java @@ -18,6 +18,8 @@ import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; import net.ornithemc.osl.networking.impl.Constants; import net.ornithemc.osl.networking.impl.HandshakePayload; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; @Mixin(ServerLoginNetworkHandler.class) @@ -28,7 +30,8 @@ public class ServerLoginNetworkHandlerMixin { /** * is the client also running OSL? */ - @Unique private boolean ornithe; + @Unique + private boolean ornithe; @Inject( method = "handleHandshake", @@ -55,7 +58,10 @@ public class ServerLoginNetworkHandlerMixin { ServerPlayNetworkingImpl.sendNoCheck(player, HandshakePayload.CHANNEL, HandshakePayload.server()); } - ServerConnectionEvents.LOGIN.invoker().accept(server, player); + ServerNetworkHandlerAccess networkHandler = (ServerNetworkHandlerAccess) player.networkHandler; + ServerConnectionContext connectionContext = networkHandler.osl$networking$connectionContext(); + + ServerConnectionEvents.LOGIN.invoker().accept(connectionContext); } } } diff --git a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java index 381c06974..45a75421e 100644 --- a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java +++ b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/java/net/ornithemc/osl/networking/impl/mixin/server/ServerPlayNetworkHandlerMixin.java @@ -3,6 +3,7 @@ import java.util.LinkedHashSet; import java.util.Set; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -15,22 +16,39 @@ import net.minecraft.server.network.handler.ServerPlayNetworkHandler; import net.ornithemc.osl.core.api.util.NamespacedIdentifier; -import net.ornithemc.osl.networking.api.server.ServerConnectionEvents; import net.ornithemc.osl.networking.impl.CustomPayloadPacket; -import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; -import net.ornithemc.osl.networking.impl.interfaces.mixin.INetworkHandler; +import net.ornithemc.osl.networking.impl.access.PacketHandlerAccess; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; import net.ornithemc.osl.networking.impl.server.ServerPlayNetworkingImpl; +import net.ornithemc.osl.text.api.TextComponents; @Mixin(ServerPlayNetworkHandler.class) -public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess, INetworkHandler { +public class ServerPlayNetworkHandlerMixin implements ServerNetworkHandlerAccess, PacketHandlerAccess { - @Shadow private MinecraftServer server; - @Shadow private ServerPlayerEntity player; + @Shadow @Final + private MinecraftServer server; + @Shadow + private ServerPlayerEntity player; + + @Unique + private ServerConnectionContext connectionContext; /** * Channels that the client is listening to. */ - @Unique private Set clientChannels; + @Unique + private Set clientChannels; + + @Inject( + method = "", + at = @At( + value = "TAIL" + ) + ) + private void osl$networking$initConnectionContext(CallbackInfo ci) { + connectionContext = new ServerConnectionContext(server, (ServerPlayNetworkHandler) (Object) this); + } @Inject( method = "onDisconnect", @@ -38,9 +56,15 @@ public class ServerPlayNetworkHandlerMixin implements NetworkHandlerAccess, INet value = "HEAD" ) ) - private void osl$networking$handleDisconnect(CallbackInfo ci) { - ServerConnectionEvents.DISCONNECT.invoker().accept(server, player); - clientChannels = null; + private void osl$networking$handleDisconnect(String reason, Object[] args, CallbackInfo ci) { + connectionContext.offerDisconnectReason(args == null + ? TextComponents.translatable(reason) + : TextComponents.translatable(reason, args)); + } + + @Override + public ServerConnectionContext osl$networking$connectionContext() { + return connectionContext; } @Override diff --git a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/resources/fabric.mod.json b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/resources/fabric.mod.json index 76c0421ad..fc81a5628 100644 --- a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/resources/fabric.mod.json +++ b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/resources/fabric.mod.json @@ -23,6 +23,8 @@ "osl-core": "\u003e\u003d0.7.0", "osl-entrypoints": "\u003e\u003d0.5.0", "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", "osl-networking": "\u003e\u003d0.9.0" }, "name": "OSL Networking Implementation", diff --git a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/resources/osl.networking-impl.classtweaker b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/resources/osl.networking-impl.classtweaker new file mode 100644 index 000000000..938816a7d --- /dev/null +++ b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/resources/osl.networking-impl.classtweaker @@ -0,0 +1,3 @@ +classTweaker v1 named + +accessible field net/minecraft/network/Connection socket Ljava/net/Socket; \ No newline at end of file diff --git a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/resources/osl.networking-impl.mixins.json b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/resources/osl.networking-impl.mixins.json index 95fccaf71..4c07c796d 100644 --- a/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/resources/osl.networking-impl.mixins.json +++ b/libraries/networking-impl/networking-impl-mcb1.5-mc11w48a/src/main/resources/osl.networking-impl.mixins.json @@ -9,9 +9,11 @@ ], "client": [ "client.ClientNetworkHandlerMixin", - "client.HandshakePacketMixin" + "client.HandshakePacketMixin", + "client.MinecraftMixin" ], "server": [ + "server.PlayerManagerMixin", "server.ServerLoginNetworkHandlerMixin", "server.ServerPlayNetworkHandlerMixin" ], diff --git a/libraries/networking/gradle.properties b/libraries/networking/gradle.properties index 4ea198e6d..436ca4a1d 100644 --- a/libraries/networking/gradle.properties +++ b/libraries/networking/gradle.properties @@ -3,4 +3,4 @@ library_name = Networking library_description = Client-server networking API and events. library_version = 0.9.0 -osl_dependencies = core:>=0.7.0,entrypoints:>=0.5.0,lifecycle-events:>=0.6.0 +osl_dependencies = core:>=0.7.0,executors:>=0.1.0,text-components:>=0.1.0- diff --git a/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java b/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java index d5adcfb8b..c971cb64c 100644 --- a/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java +++ b/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java @@ -5,11 +5,12 @@ import net.minecraft.client.Minecraft; import net.ornithemc.osl.core.api.events.Event; +import net.ornithemc.osl.text.api.TextComponent; /** * Events related to the client side of a client-server connection. */ -public class ClientConnectionEvents { +public final class ClientConnectionEvents { /** * This event is fired after a successful login occurs. @@ -28,13 +29,13 @@ public class ClientConnectionEvents { * *
 	 * {@code
-	 * ClientConnectionEvents.LOGIN.register(minecraft -> {
+	 * ClientConnectionEvents.LOGIN.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> LOGIN = Event.consumer(); + public static final Event> LOGIN = Event.consumer(); /** * This event is fired after login, once channel registration is complete. * @@ -51,13 +52,13 @@ public class ClientConnectionEvents { * *
 	 * {@code
-	 * ClientConnectionEvents.PLAY_READY.register(minecraft -> {
+	 * ClientConnectionEvents.PLAY_READY.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> PLAY_READY = Event.consumer(); + public static final Event> PLAY_READY = Event.consumer(); /** * This event is fired when the client disconnects from the server. * @@ -71,12 +72,67 @@ public class ClientConnectionEvents { * *
 	 * {@code
-	 * ClientConnectionEvents.DISCONNECT.register(minecraft -> {
+	 * ClientConnectionEvents.DISCONNECT.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> DISCONNECT = Event.consumer(); + public static final Event> DISCONNECT = Event.consumer(); + /** + * Common interface for connection context classes. + */ + public interface ConnectionContext { + + /** + * @return the current {@linkplain Minecraft} instance. + */ + Minecraft minecraft(); + + /** + * @return the name of the selected singleplayer world, or {@code null} if connected to a remote server. + */ + String worldName(); + + /** + * @return the address of the server logged into, or {@code null} if selected a singleplayer world. + */ + String serverAddress(); + + /** + * @return the port of the server logged into, or {@code -1} if selected a singleplayer world. + */ + int serverPort(); + + /** + * @return whether the server is a local integrated server. + */ + boolean isServerLocal(); + + } + + /** + * Access to relevant context for login events. + */ + public interface LoginContext extends ConnectionContext { + } + + /** + * Access to relevant context for play ready events. + */ + public interface PlayReadyContext extends ConnectionContext { + } + + /** + * Access to relevant context for disconnect events. + */ + public interface DisconnectContext extends ConnectionContext { + + /** + * @return the reason for the disconnect, or {@code null} if disconnected by leaving the server or closing the game. + */ + TextComponent disconnectReason(); + + } } diff --git a/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java b/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java index e248c5243..83c6811c7 100644 --- a/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java +++ b/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java @@ -1,16 +1,17 @@ package net.ornithemc.osl.networking.api.server; -import java.util.function.BiConsumer; +import java.util.function.Consumer; import net.minecraft.server.MinecraftServer; import net.minecraft.server.entity.living.player.ServerPlayerEntity; import net.ornithemc.osl.core.api.events.Event; +import net.ornithemc.osl.text.api.TextComponent; /** * Events related to the server side of a client-server connection. */ -public class ServerConnectionEvents { +public final class ServerConnectionEvents { /** * This event is fired after a successful login occurs. @@ -29,13 +30,13 @@ public class ServerConnectionEvents { * *
 	 * {@code
-	 * ServerConnectionEvents.LOGIN.register((server, player) -> {
+	 * ServerConnectionEvents.LOGIN.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> LOGIN = Event.biConsumer(); + public static final Event> LOGIN = Event.consumer(); /** * This event is fired after login, once channel registration is complete. * @@ -52,13 +53,13 @@ public class ServerConnectionEvents { * *
 	 * {@code
-	 * ServerConnectionEvents.PLAY_READY.register((server, player) -> {
+	 * ServerConnectionEvents.PLAY_READY.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> PLAY_READY = Event.biConsumer(); + public static final Event> PLAY_READY = Event.consumer(); /** * This event is fired when a client disconnects from the server. * @@ -72,12 +73,52 @@ public class ServerConnectionEvents { * *
 	 * {@code
-	 * ServerConnectionEvents.DISCONNECT.register((server, player) -> {
+	 * ServerConnectionEvents.DISCONNECT.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> DISCONNECT = Event.biConsumer(); + public static final Event> DISCONNECT = Event.consumer(); + /** + * Common interface for connection context classes. + */ + public interface ConnectionContext { + + /** + * @return the current {@linkplain MinecraftServer} instance. + */ + MinecraftServer server(); + + /** + * @return the current {@linkplain ServerPlayerEntity} instance. + */ + ServerPlayerEntity player(); + + } + + /** + * Access to relevant context for login events. + */ + public interface LoginContext extends ConnectionContext { + } + + /** + * Access to relevant context for play ready events. + */ + public interface PlayReadyContext extends ConnectionContext { + } + + /** + * Access to relevant context for disconnect events. + */ + public interface DisconnectContext extends ConnectionContext { + + /** + * @return the reason for the disconnect, or {@code null} if disconnected by leaving the server or closing the game. + */ + TextComponent disconnectReason(); + + } } diff --git a/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/access/TaskRunnerAccess.java b/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/access/TaskRunnerAccess.java deleted file mode 100644 index bff1ba392..000000000 --- a/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/access/TaskRunnerAccess.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.ornithemc.osl.networking.impl.access; - -public interface TaskRunnerAccess { - - boolean osl$networking$submit(Runnable task); - -} diff --git a/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/client/ClientConnectionContext.java b/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/client/ClientConnectionContext.java new file mode 100644 index 000000000..9dcbf1936 --- /dev/null +++ b/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/client/ClientConnectionContext.java @@ -0,0 +1,69 @@ +package net.ornithemc.osl.networking.impl.client; + +import net.minecraft.client.Minecraft; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents.DisconnectContext; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents.LoginContext; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents.PlayReadyContext; +import net.ornithemc.osl.text.api.TextComponent; + +public final class ClientConnectionContext implements LoginContext, PlayReadyContext, DisconnectContext { + + private final Minecraft minecraft; + private final String worldName; + private final String serverAddress; + private final int serverPort; + + private TextComponent disconnectReason; + + public ClientConnectionContext(Minecraft minecraft, String worldName) { + this(minecraft, worldName, null, -1); + } + + public ClientConnectionContext(Minecraft minecraft, String serverAddress, int serverPort) { + this(minecraft, null, serverAddress, serverPort); + } + + private ClientConnectionContext(Minecraft minecraft, String worldName, String serverAddress, int serverPort) { + this.minecraft = minecraft; + this.worldName = worldName; + this.serverAddress = serverAddress; + this.serverPort = serverPort; + } + + @Override + public Minecraft minecraft() { + return this.minecraft; + } + + @Override + public String worldName() { + return this.worldName; + } + + @Override + public String serverAddress() { + return this.serverAddress; + } + + @Override + public int serverPort() { + return this.serverPort; + } + + @Override + public TextComponent disconnectReason() { + return this.disconnectReason; + } + + @Override + public boolean isServerLocal() { + return this.worldName != null; + } + + public void offerDisconnectReason(TextComponent disconnectReason) { + if (this.disconnectReason == null) { + this.disconnectReason = disconnectReason; + } + } +} diff --git a/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/client/ClientPlayNetworkingImpl.java b/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/client/ClientPlayNetworkingImpl.java index 429898291..a4350530c 100644 --- a/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/client/ClientPlayNetworkingImpl.java +++ b/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/client/ClientPlayNetworkingImpl.java @@ -14,6 +14,7 @@ import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.core.api.util.function.IOConsumer; +import net.ornithemc.osl.core.impl.util.MinecraftVersion; import net.ornithemc.osl.networking.api.PacketBuffer; import net.ornithemc.osl.networking.api.PacketBuffers; import net.ornithemc.osl.networking.api.PacketPayload; @@ -24,11 +25,11 @@ import net.ornithemc.osl.networking.impl.PacketFactory; import net.ornithemc.osl.networking.impl.access.CustomPayloadPacketAccess; import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; -import net.ornithemc.osl.networking.impl.access.TaskRunnerAccess; public final class ClientPlayNetworkingImpl { private static final Logger LOGGER = LogManager.getLogger("OSL|Client Play Networking"); + private static final boolean USE_EVENT_LOOP_FOR_ASYNC_HANDLING = MinecraftVersion.resolve().compareTo("14w21a") >= 0; private static PacketFactory packetFactory; private static Minecraft minecraft; @@ -117,9 +118,9 @@ public static boolean handlePacket(Minecraft minecraft, ClientPlayNetworkHandler try { handlePayload(channel, listener, ctx, data); } catch (NotOnMainThreadException e) { - if (minecraft instanceof TaskRunnerAccess) { + if (USE_EVENT_LOOP_FOR_ASYNC_HANDLING) { // use built-in task queue like other packets do (14w21a+) - ((TaskRunnerAccess) minecraft).osl$networking$submit(() -> handlePayload(channel, listener, ctx, data)); + minecraft.execute(() -> handlePayload(channel, listener, ctx, data)); } else { // rethrow so packet is added to the read queue (14w20b-) throw e; diff --git a/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/server/ServerConnectionContext.java b/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/server/ServerConnectionContext.java new file mode 100644 index 000000000..11c0dd0a5 --- /dev/null +++ b/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/server/ServerConnectionContext.java @@ -0,0 +1,44 @@ +package net.ornithemc.osl.networking.impl.server; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; +import net.minecraft.server.network.handler.ServerPlayNetworkHandler; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents.DisconnectContext; +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents.LoginContext; +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents.PlayReadyContext; +import net.ornithemc.osl.text.api.TextComponent; + +public final class ServerConnectionContext implements LoginContext, PlayReadyContext, DisconnectContext { + + private final MinecraftServer server; + private final ServerPlayNetworkHandler networkHandler; + + private TextComponent disconnectReason; + + public ServerConnectionContext(MinecraftServer server, ServerPlayNetworkHandler networkHandler) { + this.server = server; + this.networkHandler = networkHandler; + } + + @Override + public MinecraftServer server() { + return this.server; + } + + @Override + public ServerPlayerEntity player() { + return this.networkHandler.player; + } + + @Override + public TextComponent disconnectReason() { + return this.disconnectReason; + } + + public void offerDisconnectReason(TextComponent disconnectReason) { + if (this.disconnectReason == null) { + this.disconnectReason = disconnectReason; + } + } +} diff --git a/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/server/ServerPlayNetworkingImpl.java b/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/server/ServerPlayNetworkingImpl.java index 613dbee78..2bdfebea0 100644 --- a/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/server/ServerPlayNetworkingImpl.java +++ b/libraries/networking/networking-mc13w41a-mc18w30b/src/main/java/net/ornithemc/osl/networking/impl/server/ServerPlayNetworkingImpl.java @@ -18,6 +18,7 @@ import net.ornithemc.osl.core.api.util.NamespacedIdentifier; import net.ornithemc.osl.core.api.util.function.IOConsumer; +import net.ornithemc.osl.core.impl.util.MinecraftVersion; import net.ornithemc.osl.networking.api.PacketBuffer; import net.ornithemc.osl.networking.api.PacketBuffers; import net.ornithemc.osl.networking.api.PacketPayload; @@ -29,11 +30,11 @@ import net.ornithemc.osl.networking.impl.access.CustomPayloadPacketAccess; import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; import net.ornithemc.osl.networking.impl.access.PlayerManagerAccess; -import net.ornithemc.osl.networking.impl.access.TaskRunnerAccess; public final class ServerPlayNetworkingImpl { private static final Logger LOGGER = LogManager.getLogger("OSL|Server Play Networking"); + private static final boolean USE_EVENT_LOOP_FOR_ASYNC_HANDLING = MinecraftVersion.resolve().compareTo("14w21a") >= 0; private static PacketFactory packetFactory; private static MinecraftServer server; @@ -122,9 +123,9 @@ public static boolean handlePacket(MinecraftServer server, ServerPlayNetworkHand try { handlePayload(channel, listener, ctx, data); } catch (NotOnMainThreadException e) { - if (server instanceof TaskRunnerAccess) { + if (USE_EVENT_LOOP_FOR_ASYNC_HANDLING) { // use built-in task queue like other packets do (14w21a+) - ((TaskRunnerAccess) server).osl$networking$submit(() -> handlePayload(channel, listener, ctx, data)); + server.execute(() -> handlePayload(channel, listener, ctx, data)); } else { // rethrow so packet is added to the read queue (14w20b-) throw e; diff --git a/libraries/networking/networking-mc13w41a-mc18w30b/src/main/resources/fabric.mod.json b/libraries/networking/networking-mc13w41a-mc18w30b/src/main/resources/fabric.mod.json index 1d4500168..c881348f7 100644 --- a/libraries/networking/networking-mc13w41a-mc18w30b/src/main/resources/fabric.mod.json +++ b/libraries/networking/networking-mc13w41a-mc18w30b/src/main/resources/fabric.mod.json @@ -10,8 +10,8 @@ "fabricloader": "\u003e\u003d0.18.0", "minecraft": "\u003e\u003d1.7-alpha.13.41.a \u003c\u003d1.13.1-alpha.18.30.b", "osl-core": "\u003e\u003d0.7.0", - "osl-entrypoints": "\u003e\u003d0.5.0", - "osl-lifecycle-events": "\u003e\u003d0.6.0" + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-" }, "name": "OSL Networking", "description": "Client-server networking API and events.", diff --git a/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java b/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java index d5adcfb8b..c971cb64c 100644 --- a/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java +++ b/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java @@ -5,11 +5,12 @@ import net.minecraft.client.Minecraft; import net.ornithemc.osl.core.api.events.Event; +import net.ornithemc.osl.text.api.TextComponent; /** * Events related to the client side of a client-server connection. */ -public class ClientConnectionEvents { +public final class ClientConnectionEvents { /** * This event is fired after a successful login occurs. @@ -28,13 +29,13 @@ public class ClientConnectionEvents { * *
 	 * {@code
-	 * ClientConnectionEvents.LOGIN.register(minecraft -> {
+	 * ClientConnectionEvents.LOGIN.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> LOGIN = Event.consumer(); + public static final Event> LOGIN = Event.consumer(); /** * This event is fired after login, once channel registration is complete. * @@ -51,13 +52,13 @@ public class ClientConnectionEvents { * *
 	 * {@code
-	 * ClientConnectionEvents.PLAY_READY.register(minecraft -> {
+	 * ClientConnectionEvents.PLAY_READY.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> PLAY_READY = Event.consumer(); + public static final Event> PLAY_READY = Event.consumer(); /** * This event is fired when the client disconnects from the server. * @@ -71,12 +72,67 @@ public class ClientConnectionEvents { * *
 	 * {@code
-	 * ClientConnectionEvents.DISCONNECT.register(minecraft -> {
+	 * ClientConnectionEvents.DISCONNECT.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> DISCONNECT = Event.consumer(); + public static final Event> DISCONNECT = Event.consumer(); + /** + * Common interface for connection context classes. + */ + public interface ConnectionContext { + + /** + * @return the current {@linkplain Minecraft} instance. + */ + Minecraft minecraft(); + + /** + * @return the name of the selected singleplayer world, or {@code null} if connected to a remote server. + */ + String worldName(); + + /** + * @return the address of the server logged into, or {@code null} if selected a singleplayer world. + */ + String serverAddress(); + + /** + * @return the port of the server logged into, or {@code -1} if selected a singleplayer world. + */ + int serverPort(); + + /** + * @return whether the server is a local integrated server. + */ + boolean isServerLocal(); + + } + + /** + * Access to relevant context for login events. + */ + public interface LoginContext extends ConnectionContext { + } + + /** + * Access to relevant context for play ready events. + */ + public interface PlayReadyContext extends ConnectionContext { + } + + /** + * Access to relevant context for disconnect events. + */ + public interface DisconnectContext extends ConnectionContext { + + /** + * @return the reason for the disconnect, or {@code null} if disconnected by leaving the server or closing the game. + */ + TextComponent disconnectReason(); + + } } diff --git a/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java b/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java index e248c5243..83c6811c7 100644 --- a/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java +++ b/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java @@ -1,16 +1,17 @@ package net.ornithemc.osl.networking.api.server; -import java.util.function.BiConsumer; +import java.util.function.Consumer; import net.minecraft.server.MinecraftServer; import net.minecraft.server.entity.living.player.ServerPlayerEntity; import net.ornithemc.osl.core.api.events.Event; +import net.ornithemc.osl.text.api.TextComponent; /** * Events related to the server side of a client-server connection. */ -public class ServerConnectionEvents { +public final class ServerConnectionEvents { /** * This event is fired after a successful login occurs. @@ -29,13 +30,13 @@ public class ServerConnectionEvents { * *
 	 * {@code
-	 * ServerConnectionEvents.LOGIN.register((server, player) -> {
+	 * ServerConnectionEvents.LOGIN.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> LOGIN = Event.biConsumer(); + public static final Event> LOGIN = Event.consumer(); /** * This event is fired after login, once channel registration is complete. * @@ -52,13 +53,13 @@ public class ServerConnectionEvents { * *
 	 * {@code
-	 * ServerConnectionEvents.PLAY_READY.register((server, player) -> {
+	 * ServerConnectionEvents.PLAY_READY.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> PLAY_READY = Event.biConsumer(); + public static final Event> PLAY_READY = Event.consumer(); /** * This event is fired when a client disconnects from the server. * @@ -72,12 +73,52 @@ public class ServerConnectionEvents { * *
 	 * {@code
-	 * ServerConnectionEvents.DISCONNECT.register((server, player) -> {
+	 * ServerConnectionEvents.DISCONNECT.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> DISCONNECT = Event.biConsumer(); + public static final Event> DISCONNECT = Event.consumer(); + /** + * Common interface for connection context classes. + */ + public interface ConnectionContext { + + /** + * @return the current {@linkplain MinecraftServer} instance. + */ + MinecraftServer server(); + + /** + * @return the current {@linkplain ServerPlayerEntity} instance. + */ + ServerPlayerEntity player(); + + } + + /** + * Access to relevant context for login events. + */ + public interface LoginContext extends ConnectionContext { + } + + /** + * Access to relevant context for play ready events. + */ + public interface PlayReadyContext extends ConnectionContext { + } + + /** + * Access to relevant context for disconnect events. + */ + public interface DisconnectContext extends ConnectionContext { + + /** + * @return the reason for the disconnect, or {@code null} if disconnected by leaving the server or closing the game. + */ + TextComponent disconnectReason(); + + } } diff --git a/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/access/TaskRunnerAccess.java b/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/access/TaskRunnerAccess.java deleted file mode 100644 index bff1ba392..000000000 --- a/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/access/TaskRunnerAccess.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.ornithemc.osl.networking.impl.access; - -public interface TaskRunnerAccess { - - boolean osl$networking$submit(Runnable task); - -} diff --git a/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/client/ClientConnectionContext.java b/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/client/ClientConnectionContext.java new file mode 100644 index 000000000..9dcbf1936 --- /dev/null +++ b/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/client/ClientConnectionContext.java @@ -0,0 +1,69 @@ +package net.ornithemc.osl.networking.impl.client; + +import net.minecraft.client.Minecraft; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents.DisconnectContext; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents.LoginContext; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents.PlayReadyContext; +import net.ornithemc.osl.text.api.TextComponent; + +public final class ClientConnectionContext implements LoginContext, PlayReadyContext, DisconnectContext { + + private final Minecraft minecraft; + private final String worldName; + private final String serverAddress; + private final int serverPort; + + private TextComponent disconnectReason; + + public ClientConnectionContext(Minecraft minecraft, String worldName) { + this(minecraft, worldName, null, -1); + } + + public ClientConnectionContext(Minecraft minecraft, String serverAddress, int serverPort) { + this(minecraft, null, serverAddress, serverPort); + } + + private ClientConnectionContext(Minecraft minecraft, String worldName, String serverAddress, int serverPort) { + this.minecraft = minecraft; + this.worldName = worldName; + this.serverAddress = serverAddress; + this.serverPort = serverPort; + } + + @Override + public Minecraft minecraft() { + return this.minecraft; + } + + @Override + public String worldName() { + return this.worldName; + } + + @Override + public String serverAddress() { + return this.serverAddress; + } + + @Override + public int serverPort() { + return this.serverPort; + } + + @Override + public TextComponent disconnectReason() { + return this.disconnectReason; + } + + @Override + public boolean isServerLocal() { + return this.worldName != null; + } + + public void offerDisconnectReason(TextComponent disconnectReason) { + if (this.disconnectReason == null) { + this.disconnectReason = disconnectReason; + } + } +} diff --git a/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/client/ClientPlayNetworkingImpl.java b/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/client/ClientPlayNetworkingImpl.java index e9ba1661b..42e00b838 100644 --- a/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/client/ClientPlayNetworkingImpl.java +++ b/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/client/ClientPlayNetworkingImpl.java @@ -24,7 +24,6 @@ import net.ornithemc.osl.networking.impl.PacketFactory; import net.ornithemc.osl.networking.impl.access.CustomPayloadPacketAccess; import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; -import net.ornithemc.osl.networking.impl.access.TaskRunnerAccess; public final class ClientPlayNetworkingImpl { @@ -115,7 +114,7 @@ public static boolean handlePacket(Minecraft minecraft, ClientPlayNetworkHandler try { handlePayload(channel, listener, ctx, data); } catch (NotOnMainThreadException e) { - ((TaskRunnerAccess) minecraft).osl$networking$submit(() -> handlePayload(channel, listener, ctx, data)); + minecraft.execute(() -> handlePayload(channel, listener, ctx, data)); } return true; diff --git a/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/server/ServerConnectionContext.java b/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/server/ServerConnectionContext.java new file mode 100644 index 000000000..11c0dd0a5 --- /dev/null +++ b/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/server/ServerConnectionContext.java @@ -0,0 +1,44 @@ +package net.ornithemc.osl.networking.impl.server; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; +import net.minecraft.server.network.handler.ServerPlayNetworkHandler; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents.DisconnectContext; +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents.LoginContext; +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents.PlayReadyContext; +import net.ornithemc.osl.text.api.TextComponent; + +public final class ServerConnectionContext implements LoginContext, PlayReadyContext, DisconnectContext { + + private final MinecraftServer server; + private final ServerPlayNetworkHandler networkHandler; + + private TextComponent disconnectReason; + + public ServerConnectionContext(MinecraftServer server, ServerPlayNetworkHandler networkHandler) { + this.server = server; + this.networkHandler = networkHandler; + } + + @Override + public MinecraftServer server() { + return this.server; + } + + @Override + public ServerPlayerEntity player() { + return this.networkHandler.player; + } + + @Override + public TextComponent disconnectReason() { + return this.disconnectReason; + } + + public void offerDisconnectReason(TextComponent disconnectReason) { + if (this.disconnectReason == null) { + this.disconnectReason = disconnectReason; + } + } +} diff --git a/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/server/ServerPlayNetworkingImpl.java b/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/server/ServerPlayNetworkingImpl.java index 647c0c11e..2dc0cd7be 100644 --- a/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/server/ServerPlayNetworkingImpl.java +++ b/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/java/net/ornithemc/osl/networking/impl/server/ServerPlayNetworkingImpl.java @@ -29,7 +29,6 @@ import net.ornithemc.osl.networking.impl.PacketFactory; import net.ornithemc.osl.networking.impl.access.CustomPayloadPacketAccess; import net.ornithemc.osl.networking.impl.access.NetworkHandlerAccess; -import net.ornithemc.osl.networking.impl.access.TaskRunnerAccess; public final class ServerPlayNetworkingImpl { @@ -120,7 +119,7 @@ public static boolean handlePacket(MinecraftServer server, ServerPlayNetworkHand try { handlePayload(channel, listener, ctx, data); } catch (NotOnMainThreadException e) { - ((TaskRunnerAccess) server).osl$networking$submit(() -> handlePayload(channel, listener, ctx, data)); + server.execute(() -> handlePayload(channel, listener, ctx, data)); } return true; diff --git a/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/resources/fabric.mod.json b/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/resources/fabric.mod.json index 883a357e2..1ec6f7eea 100644 --- a/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/resources/fabric.mod.json +++ b/libraries/networking/networking-mc18w31a-mc1.14.4/src/main/resources/fabric.mod.json @@ -10,8 +10,8 @@ "fabricloader": "\u003e\u003d0.18.0", "minecraft": "\u003e\u003d1.13.1-alpha.18.31.a \u003c\u003d1.14.4", "osl-core": "\u003e\u003d0.7.0", - "osl-entrypoints": "\u003e\u003d0.5.0", - "osl-lifecycle-events": "\u003e\u003d0.6.0" + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-" }, "name": "OSL Networking", "description": "Client-server networking API and events.", diff --git a/libraries/networking/networking-mca0.1.0-mca0.2.1/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java b/libraries/networking/networking-mca0.1.0-mca0.2.1/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java index 9d33bccfd..f7c894fd7 100644 --- a/libraries/networking/networking-mca0.1.0-mca0.2.1/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java +++ b/libraries/networking/networking-mca0.1.0-mca0.2.1/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java @@ -1,16 +1,17 @@ package net.ornithemc.osl.networking.api.server; -import java.util.function.BiConsumer; +import java.util.function.Consumer; import net.minecraft.server.MinecraftServer; import net.minecraft.server.entity.mob.player.ServerPlayerEntity; import net.ornithemc.osl.core.api.events.Event; +import net.ornithemc.osl.text.api.TextComponent; /** * Events related to the server side of a client-server connection. */ -public class ServerConnectionEvents { +public final class ServerConnectionEvents { /** * This event is fired after a successful login occurs. @@ -29,13 +30,13 @@ public class ServerConnectionEvents { * *
 	 * {@code
-	 * ServerConnectionEvents.LOGIN.register((server, player) -> {
+	 * ServerConnectionEvents.LOGIN.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> LOGIN = Event.biConsumer(); + public static final Event> LOGIN = Event.consumer(); /** * This event is fired after login, once channel registration is complete. * @@ -52,13 +53,13 @@ public class ServerConnectionEvents { * *
 	 * {@code
-	 * ServerConnectionEvents.PLAY_READY.register((server, player) -> {
+	 * ServerConnectionEvents.PLAY_READY.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> PLAY_READY = Event.biConsumer(); + public static final Event> PLAY_READY = Event.consumer(); /** * This event is fired when a client disconnects from the server. * @@ -72,12 +73,52 @@ public class ServerConnectionEvents { * *
 	 * {@code
-	 * ServerConnectionEvents.DISCONNECT.register((server, player) -> {
+	 * ServerConnectionEvents.DISCONNECT.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> DISCONNECT = Event.biConsumer(); + public static final Event> DISCONNECT = Event.consumer(); + /** + * Common interface for connection context classes. + */ + public interface ConnectionContext { + + /** + * @return the current {@linkplain MinecraftServer} instance. + */ + MinecraftServer server(); + + /** + * @return the current {@linkplain ServerPlayerEntity} instance. + */ + ServerPlayerEntity player(); + + } + + /** + * Access to relevant context for login events. + */ + public interface LoginContext extends ConnectionContext { + } + + /** + * Access to relevant context for play ready events. + */ + public interface PlayReadyContext extends ConnectionContext { + } + + /** + * Access to relevant context for disconnect events. + */ + public interface DisconnectContext extends ConnectionContext { + + /** + * @return the reason for the disconnect, or {@code null} if disconnected by leaving the server or closing the game. + */ + TextComponent disconnectReason(); + + } } diff --git a/libraries/networking/networking-mca0.1.0-mca0.2.1/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java b/libraries/networking/networking-mca0.1.0-mca0.2.1/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java new file mode 100644 index 000000000..95d035429 --- /dev/null +++ b/libraries/networking/networking-mca0.1.0-mca0.2.1/src/main/java/net/ornithemc/osl/networking/impl/access/ServerNetworkHandlerAccess.java @@ -0,0 +1,13 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.minecraft.server.entity.mob.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.impl.server.ServerConnectionContext; + +public interface ServerNetworkHandlerAccess extends NetworkHandlerAccess { + + ServerPlayerEntity osl$networkin$player(); + + ServerConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking/networking-mca0.1.0-mca0.2.1/src/main/java/net/ornithemc/osl/networking/impl/server/ServerConnectionContext.java b/libraries/networking/networking-mca0.1.0-mca0.2.1/src/main/java/net/ornithemc/osl/networking/impl/server/ServerConnectionContext.java new file mode 100644 index 000000000..9e0c10f64 --- /dev/null +++ b/libraries/networking/networking-mca0.1.0-mca0.2.1/src/main/java/net/ornithemc/osl/networking/impl/server/ServerConnectionContext.java @@ -0,0 +1,45 @@ +package net.ornithemc.osl.networking.impl.server; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.entity.mob.player.ServerPlayerEntity; +import net.minecraft.server.network.handler.ServerPlayNetworkHandler; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents.DisconnectContext; +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents.LoginContext; +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents.PlayReadyContext; +import net.ornithemc.osl.networking.impl.access.ServerNetworkHandlerAccess; +import net.ornithemc.osl.text.api.TextComponent; + +public final class ServerConnectionContext implements LoginContext, PlayReadyContext, DisconnectContext { + + private final MinecraftServer server; + private final ServerPlayNetworkHandler networkHandler; + + private TextComponent disconnectReason; + + public ServerConnectionContext(MinecraftServer server, ServerPlayNetworkHandler networkHandler) { + this.server = server; + this.networkHandler = networkHandler; + } + + @Override + public MinecraftServer server() { + return this.server; + } + + @Override + public ServerPlayerEntity player() { + return ((ServerNetworkHandlerAccess) this.networkHandler).osl$networkin$player(); + } + + @Override + public TextComponent disconnectReason() { + return this.disconnectReason; + } + + public void offerDisconnectReason(TextComponent disconnectReason) { + if (this.disconnectReason == null) { + this.disconnectReason = disconnectReason; + } + } +} diff --git a/libraries/networking/networking-mca0.1.0-mca0.2.1/src/main/resources/fabric.mod.json b/libraries/networking/networking-mca0.1.0-mca0.2.1/src/main/resources/fabric.mod.json index 98004bf7a..7ecbb4d1d 100644 --- a/libraries/networking/networking-mca0.1.0-mca0.2.1/src/main/resources/fabric.mod.json +++ b/libraries/networking/networking-mca0.1.0-mca0.2.1/src/main/resources/fabric.mod.json @@ -10,8 +10,8 @@ "fabricloader": "\u003e\u003d0.18.0", "minecraft": "\u003e\u003d1.0.0-alpha.1.0 \u003c\u003d1.0.0-alpha.2.1", "osl-core": "\u003e\u003d0.7.0", - "osl-entrypoints": "\u003e\u003d0.5.0", - "osl-lifecycle-events": "\u003e\u003d0.6.0" + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-" }, "name": "OSL Networking", "description": "Client-server networking API and events.", diff --git a/libraries/networking/networking-mca0.2.2-mca0.2.8/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java b/libraries/networking/networking-mca0.2.2-mca0.2.8/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java index 9d33bccfd..f7c894fd7 100644 --- a/libraries/networking/networking-mca0.2.2-mca0.2.8/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java +++ b/libraries/networking/networking-mca0.2.2-mca0.2.8/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java @@ -1,16 +1,17 @@ package net.ornithemc.osl.networking.api.server; -import java.util.function.BiConsumer; +import java.util.function.Consumer; import net.minecraft.server.MinecraftServer; import net.minecraft.server.entity.mob.player.ServerPlayerEntity; import net.ornithemc.osl.core.api.events.Event; +import net.ornithemc.osl.text.api.TextComponent; /** * Events related to the server side of a client-server connection. */ -public class ServerConnectionEvents { +public final class ServerConnectionEvents { /** * This event is fired after a successful login occurs. @@ -29,13 +30,13 @@ public class ServerConnectionEvents { * *
 	 * {@code
-	 * ServerConnectionEvents.LOGIN.register((server, player) -> {
+	 * ServerConnectionEvents.LOGIN.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> LOGIN = Event.biConsumer(); + public static final Event> LOGIN = Event.consumer(); /** * This event is fired after login, once channel registration is complete. * @@ -52,13 +53,13 @@ public class ServerConnectionEvents { * *
 	 * {@code
-	 * ServerConnectionEvents.PLAY_READY.register((server, player) -> {
+	 * ServerConnectionEvents.PLAY_READY.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> PLAY_READY = Event.biConsumer(); + public static final Event> PLAY_READY = Event.consumer(); /** * This event is fired when a client disconnects from the server. * @@ -72,12 +73,52 @@ public class ServerConnectionEvents { * *
 	 * {@code
-	 * ServerConnectionEvents.DISCONNECT.register((server, player) -> {
+	 * ServerConnectionEvents.DISCONNECT.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> DISCONNECT = Event.biConsumer(); + public static final Event> DISCONNECT = Event.consumer(); + /** + * Common interface for connection context classes. + */ + public interface ConnectionContext { + + /** + * @return the current {@linkplain MinecraftServer} instance. + */ + MinecraftServer server(); + + /** + * @return the current {@linkplain ServerPlayerEntity} instance. + */ + ServerPlayerEntity player(); + + } + + /** + * Access to relevant context for login events. + */ + public interface LoginContext extends ConnectionContext { + } + + /** + * Access to relevant context for play ready events. + */ + public interface PlayReadyContext extends ConnectionContext { + } + + /** + * Access to relevant context for disconnect events. + */ + public interface DisconnectContext extends ConnectionContext { + + /** + * @return the reason for the disconnect, or {@code null} if disconnected by leaving the server or closing the game. + */ + TextComponent disconnectReason(); + + } } diff --git a/libraries/networking/networking-mca0.2.2-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/server/ServerConnectionContext.java b/libraries/networking/networking-mca0.2.2-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/server/ServerConnectionContext.java new file mode 100644 index 000000000..867694056 --- /dev/null +++ b/libraries/networking/networking-mca0.2.2-mca0.2.8/src/main/java/net/ornithemc/osl/networking/impl/server/ServerConnectionContext.java @@ -0,0 +1,44 @@ +package net.ornithemc.osl.networking.impl.server; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.entity.mob.player.ServerPlayerEntity; +import net.minecraft.server.network.handler.ServerPlayNetworkHandler; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents.DisconnectContext; +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents.LoginContext; +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents.PlayReadyContext; +import net.ornithemc.osl.text.api.TextComponent; + +public final class ServerConnectionContext implements LoginContext, PlayReadyContext, DisconnectContext { + + private final MinecraftServer server; + private final ServerPlayNetworkHandler networkHandler; + + private TextComponent disconnectReason; + + public ServerConnectionContext(MinecraftServer server, ServerPlayNetworkHandler networkHandler) { + this.server = server; + this.networkHandler = networkHandler; + } + + @Override + public MinecraftServer server() { + return this.server; + } + + @Override + public ServerPlayerEntity player() { + return this.networkHandler.player; + } + + @Override + public TextComponent disconnectReason() { + return this.disconnectReason; + } + + public void offerDisconnectReason(TextComponent disconnectReason) { + if (this.disconnectReason == null) { + this.disconnectReason = disconnectReason; + } + } +} diff --git a/libraries/networking/networking-mca0.2.2-mca0.2.8/src/main/resources/fabric.mod.json b/libraries/networking/networking-mca0.2.2-mca0.2.8/src/main/resources/fabric.mod.json index 501017a42..37ab456f9 100644 --- a/libraries/networking/networking-mca0.2.2-mca0.2.8/src/main/resources/fabric.mod.json +++ b/libraries/networking/networking-mca0.2.2-mca0.2.8/src/main/resources/fabric.mod.json @@ -10,8 +10,8 @@ "fabricloader": "\u003e\u003d0.18.0", "minecraft": "\u003e\u003d1.0.0-alpha.2.2 \u003c\u003d1.0.0-alpha.2.8", "osl-core": "\u003e\u003d0.7.0", - "osl-entrypoints": "\u003e\u003d0.5.0", - "osl-lifecycle-events": "\u003e\u003d0.6.0" + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-" }, "name": "OSL Networking", "description": "Client-server networking API and events.", diff --git a/libraries/networking/networking-mca0.2.2-mca0.2.8/src/main/resources/osl.networking.classtweaker b/libraries/networking/networking-mca0.2.2-mca0.2.8/src/main/resources/osl.networking.classtweaker new file mode 100644 index 000000000..9972f8833 --- /dev/null +++ b/libraries/networking/networking-mca0.2.2-mca0.2.8/src/main/resources/osl.networking.classtweaker @@ -0,0 +1,3 @@ +classTweaker v1 named + +accessible field net/minecraft/server/network/handler/ServerPlayNetworkHandler player Lnet/minecraft/server/entity/mob/player/ServerPlayerEntity; \ No newline at end of file diff --git a/libraries/networking/networking-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java b/libraries/networking/networking-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java index d5adcfb8b..c971cb64c 100644 --- a/libraries/networking/networking-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java +++ b/libraries/networking/networking-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java @@ -5,11 +5,12 @@ import net.minecraft.client.Minecraft; import net.ornithemc.osl.core.api.events.Event; +import net.ornithemc.osl.text.api.TextComponent; /** * Events related to the client side of a client-server connection. */ -public class ClientConnectionEvents { +public final class ClientConnectionEvents { /** * This event is fired after a successful login occurs. @@ -28,13 +29,13 @@ public class ClientConnectionEvents { * *
 	 * {@code
-	 * ClientConnectionEvents.LOGIN.register(minecraft -> {
+	 * ClientConnectionEvents.LOGIN.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> LOGIN = Event.consumer(); + public static final Event> LOGIN = Event.consumer(); /** * This event is fired after login, once channel registration is complete. * @@ -51,13 +52,13 @@ public class ClientConnectionEvents { * *
 	 * {@code
-	 * ClientConnectionEvents.PLAY_READY.register(minecraft -> {
+	 * ClientConnectionEvents.PLAY_READY.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> PLAY_READY = Event.consumer(); + public static final Event> PLAY_READY = Event.consumer(); /** * This event is fired when the client disconnects from the server. * @@ -71,12 +72,67 @@ public class ClientConnectionEvents { * *
 	 * {@code
-	 * ClientConnectionEvents.DISCONNECT.register(minecraft -> {
+	 * ClientConnectionEvents.DISCONNECT.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> DISCONNECT = Event.consumer(); + public static final Event> DISCONNECT = Event.consumer(); + /** + * Common interface for connection context classes. + */ + public interface ConnectionContext { + + /** + * @return the current {@linkplain Minecraft} instance. + */ + Minecraft minecraft(); + + /** + * @return the name of the selected singleplayer world, or {@code null} if connected to a remote server. + */ + String worldName(); + + /** + * @return the address of the server logged into, or {@code null} if selected a singleplayer world. + */ + String serverAddress(); + + /** + * @return the port of the server logged into, or {@code -1} if selected a singleplayer world. + */ + int serverPort(); + + /** + * @return whether the server is a local integrated server. + */ + boolean isServerLocal(); + + } + + /** + * Access to relevant context for login events. + */ + public interface LoginContext extends ConnectionContext { + } + + /** + * Access to relevant context for play ready events. + */ + public interface PlayReadyContext extends ConnectionContext { + } + + /** + * Access to relevant context for disconnect events. + */ + public interface DisconnectContext extends ConnectionContext { + + /** + * @return the reason for the disconnect, or {@code null} if disconnected by leaving the server or closing the game. + */ + TextComponent disconnectReason(); + + } } diff --git a/libraries/networking/networking-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java b/libraries/networking/networking-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..e067a1831 --- /dev/null +++ b/libraries/networking/networking-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/access/ClientNetworkHandlerAccess.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.networking.impl.access; + +import net.ornithemc.osl.networking.impl.client.ClientConnectionContext; + +public interface ClientNetworkHandlerAccess extends NetworkHandlerAccess { + + ClientConnectionContext osl$networking$connectionContext(); + +} diff --git a/libraries/networking/networking-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/client/ClientConnectionContext.java b/libraries/networking/networking-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/client/ClientConnectionContext.java new file mode 100644 index 000000000..9dcbf1936 --- /dev/null +++ b/libraries/networking/networking-mca1.0.16-mca1.2.6/src/main/java/net/ornithemc/osl/networking/impl/client/ClientConnectionContext.java @@ -0,0 +1,69 @@ +package net.ornithemc.osl.networking.impl.client; + +import net.minecraft.client.Minecraft; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents.DisconnectContext; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents.LoginContext; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents.PlayReadyContext; +import net.ornithemc.osl.text.api.TextComponent; + +public final class ClientConnectionContext implements LoginContext, PlayReadyContext, DisconnectContext { + + private final Minecraft minecraft; + private final String worldName; + private final String serverAddress; + private final int serverPort; + + private TextComponent disconnectReason; + + public ClientConnectionContext(Minecraft minecraft, String worldName) { + this(minecraft, worldName, null, -1); + } + + public ClientConnectionContext(Minecraft minecraft, String serverAddress, int serverPort) { + this(minecraft, null, serverAddress, serverPort); + } + + private ClientConnectionContext(Minecraft minecraft, String worldName, String serverAddress, int serverPort) { + this.minecraft = minecraft; + this.worldName = worldName; + this.serverAddress = serverAddress; + this.serverPort = serverPort; + } + + @Override + public Minecraft minecraft() { + return this.minecraft; + } + + @Override + public String worldName() { + return this.worldName; + } + + @Override + public String serverAddress() { + return this.serverAddress; + } + + @Override + public int serverPort() { + return this.serverPort; + } + + @Override + public TextComponent disconnectReason() { + return this.disconnectReason; + } + + @Override + public boolean isServerLocal() { + return this.worldName != null; + } + + public void offerDisconnectReason(TextComponent disconnectReason) { + if (this.disconnectReason == null) { + this.disconnectReason = disconnectReason; + } + } +} diff --git a/libraries/networking/networking-mca1.0.16-mca1.2.6/src/main/resources/fabric.mod.json b/libraries/networking/networking-mca1.0.16-mca1.2.6/src/main/resources/fabric.mod.json index 9ead78666..dd6007ea9 100644 --- a/libraries/networking/networking-mca1.0.16-mca1.2.6/src/main/resources/fabric.mod.json +++ b/libraries/networking/networking-mca1.0.16-mca1.2.6/src/main/resources/fabric.mod.json @@ -10,8 +10,8 @@ "fabricloader": "\u003e\u003d0.18.0", "minecraft": "\u003e\u003d1.0.0-alpha.0.16 \u003c\u003d1.0.0-alpha.2.6", "osl-core": "\u003e\u003d0.7.0", - "osl-entrypoints": "\u003e\u003d0.5.0", - "osl-lifecycle-events": "\u003e\u003d0.6.0" + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-" }, "name": "OSL Networking", "description": "Client-server networking API and events.", diff --git a/libraries/networking/networking-mcb1.0-mc13w39b/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java b/libraries/networking/networking-mcb1.0-mc13w39b/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java index d5adcfb8b..c971cb64c 100644 --- a/libraries/networking/networking-mcb1.0-mc13w39b/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java +++ b/libraries/networking/networking-mcb1.0-mc13w39b/src/main/java/net/ornithemc/osl/networking/api/client/ClientConnectionEvents.java @@ -5,11 +5,12 @@ import net.minecraft.client.Minecraft; import net.ornithemc.osl.core.api.events.Event; +import net.ornithemc.osl.text.api.TextComponent; /** * Events related to the client side of a client-server connection. */ -public class ClientConnectionEvents { +public final class ClientConnectionEvents { /** * This event is fired after a successful login occurs. @@ -28,13 +29,13 @@ public class ClientConnectionEvents { * *
 	 * {@code
-	 * ClientConnectionEvents.LOGIN.register(minecraft -> {
+	 * ClientConnectionEvents.LOGIN.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> LOGIN = Event.consumer(); + public static final Event> LOGIN = Event.consumer(); /** * This event is fired after login, once channel registration is complete. * @@ -51,13 +52,13 @@ public class ClientConnectionEvents { * *
 	 * {@code
-	 * ClientConnectionEvents.PLAY_READY.register(minecraft -> {
+	 * ClientConnectionEvents.PLAY_READY.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> PLAY_READY = Event.consumer(); + public static final Event> PLAY_READY = Event.consumer(); /** * This event is fired when the client disconnects from the server. * @@ -71,12 +72,67 @@ public class ClientConnectionEvents { * *
 	 * {@code
-	 * ClientConnectionEvents.DISCONNECT.register(minecraft -> {
+	 * ClientConnectionEvents.DISCONNECT.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> DISCONNECT = Event.consumer(); + public static final Event> DISCONNECT = Event.consumer(); + /** + * Common interface for connection context classes. + */ + public interface ConnectionContext { + + /** + * @return the current {@linkplain Minecraft} instance. + */ + Minecraft minecraft(); + + /** + * @return the name of the selected singleplayer world, or {@code null} if connected to a remote server. + */ + String worldName(); + + /** + * @return the address of the server logged into, or {@code null} if selected a singleplayer world. + */ + String serverAddress(); + + /** + * @return the port of the server logged into, or {@code -1} if selected a singleplayer world. + */ + int serverPort(); + + /** + * @return whether the server is a local integrated server. + */ + boolean isServerLocal(); + + } + + /** + * Access to relevant context for login events. + */ + public interface LoginContext extends ConnectionContext { + } + + /** + * Access to relevant context for play ready events. + */ + public interface PlayReadyContext extends ConnectionContext { + } + + /** + * Access to relevant context for disconnect events. + */ + public interface DisconnectContext extends ConnectionContext { + + /** + * @return the reason for the disconnect, or {@code null} if disconnected by leaving the server or closing the game. + */ + TextComponent disconnectReason(); + + } } diff --git a/libraries/networking/networking-mcb1.0-mc13w39b/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java b/libraries/networking/networking-mcb1.0-mc13w39b/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java index 9d33bccfd..f7c894fd7 100644 --- a/libraries/networking/networking-mcb1.0-mc13w39b/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java +++ b/libraries/networking/networking-mcb1.0-mc13w39b/src/main/java/net/ornithemc/osl/networking/api/server/ServerConnectionEvents.java @@ -1,16 +1,17 @@ package net.ornithemc.osl.networking.api.server; -import java.util.function.BiConsumer; +import java.util.function.Consumer; import net.minecraft.server.MinecraftServer; import net.minecraft.server.entity.mob.player.ServerPlayerEntity; import net.ornithemc.osl.core.api.events.Event; +import net.ornithemc.osl.text.api.TextComponent; /** * Events related to the server side of a client-server connection. */ -public class ServerConnectionEvents { +public final class ServerConnectionEvents { /** * This event is fired after a successful login occurs. @@ -29,13 +30,13 @@ public class ServerConnectionEvents { * *
 	 * {@code
-	 * ServerConnectionEvents.LOGIN.register((server, player) -> {
+	 * ServerConnectionEvents.LOGIN.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> LOGIN = Event.biConsumer(); + public static final Event> LOGIN = Event.consumer(); /** * This event is fired after login, once channel registration is complete. * @@ -52,13 +53,13 @@ public class ServerConnectionEvents { * *
 	 * {@code
-	 * ServerConnectionEvents.PLAY_READY.register((server, player) -> {
+	 * ServerConnectionEvents.PLAY_READY.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> PLAY_READY = Event.biConsumer(); + public static final Event> PLAY_READY = Event.consumer(); /** * This event is fired when a client disconnects from the server. * @@ -72,12 +73,52 @@ public class ServerConnectionEvents { * *
 	 * {@code
-	 * ServerConnectionEvents.DISCONNECT.register((server, player) -> {
+	 * ServerConnectionEvents.DISCONNECT.register(context -> {
 	 * 	...
 	 * });
 	 * }
 	 * 
*/ - public static final Event> DISCONNECT = Event.biConsumer(); + public static final Event> DISCONNECT = Event.consumer(); + /** + * Common interface for connection context classes. + */ + public interface ConnectionContext { + + /** + * @return the current {@linkplain MinecraftServer} instance. + */ + MinecraftServer server(); + + /** + * @return the current {@linkplain ServerPlayerEntity} instance. + */ + ServerPlayerEntity player(); + + } + + /** + * Access to relevant context for login events. + */ + public interface LoginContext extends ConnectionContext { + } + + /** + * Access to relevant context for play ready events. + */ + public interface PlayReadyContext extends ConnectionContext { + } + + /** + * Access to relevant context for disconnect events. + */ + public interface DisconnectContext extends ConnectionContext { + + /** + * @return the reason for the disconnect, or {@code null} if disconnected by leaving the server or closing the game. + */ + TextComponent disconnectReason(); + + } } diff --git a/libraries/networking/networking-mcb1.0-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/client/ClientConnectionContext.java b/libraries/networking/networking-mcb1.0-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/client/ClientConnectionContext.java new file mode 100644 index 000000000..9dcbf1936 --- /dev/null +++ b/libraries/networking/networking-mcb1.0-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/client/ClientConnectionContext.java @@ -0,0 +1,69 @@ +package net.ornithemc.osl.networking.impl.client; + +import net.minecraft.client.Minecraft; + +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents.DisconnectContext; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents.LoginContext; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents.PlayReadyContext; +import net.ornithemc.osl.text.api.TextComponent; + +public final class ClientConnectionContext implements LoginContext, PlayReadyContext, DisconnectContext { + + private final Minecraft minecraft; + private final String worldName; + private final String serverAddress; + private final int serverPort; + + private TextComponent disconnectReason; + + public ClientConnectionContext(Minecraft minecraft, String worldName) { + this(minecraft, worldName, null, -1); + } + + public ClientConnectionContext(Minecraft minecraft, String serverAddress, int serverPort) { + this(minecraft, null, serverAddress, serverPort); + } + + private ClientConnectionContext(Minecraft minecraft, String worldName, String serverAddress, int serverPort) { + this.minecraft = minecraft; + this.worldName = worldName; + this.serverAddress = serverAddress; + this.serverPort = serverPort; + } + + @Override + public Minecraft minecraft() { + return this.minecraft; + } + + @Override + public String worldName() { + return this.worldName; + } + + @Override + public String serverAddress() { + return this.serverAddress; + } + + @Override + public int serverPort() { + return this.serverPort; + } + + @Override + public TextComponent disconnectReason() { + return this.disconnectReason; + } + + @Override + public boolean isServerLocal() { + return this.worldName != null; + } + + public void offerDisconnectReason(TextComponent disconnectReason) { + if (this.disconnectReason == null) { + this.disconnectReason = disconnectReason; + } + } +} diff --git a/libraries/networking/networking-mcb1.0-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/server/ServerConnectionContext.java b/libraries/networking/networking-mcb1.0-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/server/ServerConnectionContext.java new file mode 100644 index 000000000..867694056 --- /dev/null +++ b/libraries/networking/networking-mcb1.0-mc13w39b/src/main/java/net/ornithemc/osl/networking/impl/server/ServerConnectionContext.java @@ -0,0 +1,44 @@ +package net.ornithemc.osl.networking.impl.server; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.entity.mob.player.ServerPlayerEntity; +import net.minecraft.server.network.handler.ServerPlayNetworkHandler; + +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents.DisconnectContext; +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents.LoginContext; +import net.ornithemc.osl.networking.api.server.ServerConnectionEvents.PlayReadyContext; +import net.ornithemc.osl.text.api.TextComponent; + +public final class ServerConnectionContext implements LoginContext, PlayReadyContext, DisconnectContext { + + private final MinecraftServer server; + private final ServerPlayNetworkHandler networkHandler; + + private TextComponent disconnectReason; + + public ServerConnectionContext(MinecraftServer server, ServerPlayNetworkHandler networkHandler) { + this.server = server; + this.networkHandler = networkHandler; + } + + @Override + public MinecraftServer server() { + return this.server; + } + + @Override + public ServerPlayerEntity player() { + return this.networkHandler.player; + } + + @Override + public TextComponent disconnectReason() { + return this.disconnectReason; + } + + public void offerDisconnectReason(TextComponent disconnectReason) { + if (this.disconnectReason == null) { + this.disconnectReason = disconnectReason; + } + } +} diff --git a/libraries/networking/networking-mcb1.0-mc13w39b/src/main/resources/fabric.mod.json b/libraries/networking/networking-mcb1.0-mc13w39b/src/main/resources/fabric.mod.json index 7569828e6..e2103655c 100644 --- a/libraries/networking/networking-mcb1.0-mc13w39b/src/main/resources/fabric.mod.json +++ b/libraries/networking/networking-mcb1.0-mc13w39b/src/main/resources/fabric.mod.json @@ -10,8 +10,8 @@ "fabricloader": "\u003e\u003d0.18.0", "minecraft": "\u003e\u003d1.0.0-beta.0 \u003c\u003d1.7-alpha.13.39.b", "osl-core": "\u003e\u003d0.7.0", - "osl-entrypoints": "\u003e\u003d0.5.0", - "osl-lifecycle-events": "\u003e\u003d0.6.0" + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-" }, "name": "OSL Networking", "description": "Client-server networking API and events.", diff --git a/libraries/networking/networking-mcb1.0-mc13w39b/src/main/resources/osl.networking.classtweaker b/libraries/networking/networking-mcb1.0-mc13w39b/src/main/resources/osl.networking.classtweaker new file mode 100644 index 000000000..9972f8833 --- /dev/null +++ b/libraries/networking/networking-mcb1.0-mc13w39b/src/main/resources/osl.networking.classtweaker @@ -0,0 +1,3 @@ +classTweaker v1 named + +accessible field net/minecraft/server/network/handler/ServerPlayNetworkHandler player Lnet/minecraft/server/entity/mob/player/ServerPlayerEntity; \ No newline at end of file diff --git a/libraries/networking/src/main/java/net/ornithemc/osl/networking/impl/AddressParser.java b/libraries/networking/src/main/java/net/ornithemc/osl/networking/impl/AddressParser.java new file mode 100644 index 000000000..0d026b872 --- /dev/null +++ b/libraries/networking/src/main/java/net/ornithemc/osl/networking/impl/AddressParser.java @@ -0,0 +1,36 @@ +package net.ornithemc.osl.networking.impl; + +import java.net.SocketAddress; + +public final class AddressParser { + + public static final int DEFAULT_PORT = 25565; + + public static String getAddress(SocketAddress socketAddress) { + String address = socketAddress.toString(); + + if (address.contains("/")) { + address = address.substring(address.indexOf('/') + 1); + } + if (address.contains(":")) { + address = address.substring(0, address.indexOf(':')); + } + + return address; + } + + public static int getPort(SocketAddress socketAddress) { + String address = socketAddress.toString(); + + if (address.contains(":")) { + String port = address.substring(address.indexOf(':') + 1); + + try { + return Integer.parseInt(port); + } catch (NumberFormatException ignored) { + } + } + + return -1; + } +} diff --git a/libraries/registries/README.md b/libraries/registries/README.md new file mode 100644 index 000000000..6400d88f1 --- /dev/null +++ b/libraries/registries/README.md @@ -0,0 +1,114 @@ +# Registries API + +The Registries API provides an alternative to Vanilla's registry system, with a more modern feature set and available for all Minecraft versions. It also provides an API for synchronizing numerical IDs between the server and client and across sessions, to help avoid desync and world corruption bugs. + +## Resource Keys + +Registries are in essence fancy `Map`s. The keys used in registries are `ResourceKey`s. A resource key consists of two components, a `registry` identifier that uniquely identifies the registry it's a part of, and an `identifier` that uniquely identifies a resource within that registry. Thus, a resource key can uniquely identity any registered resource. + +The `ResourceKeys` class provides factory methods for creating resource keys: + +```java +ResourceKey COOKIE_KEY = ResourceKeys.from(RegistryKeys.BLOCK, NamespacedIdentifiers.from("example", "cookie")); +``` + +## Registering Resources + +The `Registry` class provides helper methods for registering resources to a registry: + +```java +Block COOKIE = Registry.register(BlockRegistry.REGISTRY, COOKIE_KEY, new CookieBlock()); +``` + +## Creating Registries + +Just like with other resources, you must create a `ResourceKey` that uniquely identifies your registry. The `RegistryKeys` class provides some factory methods for creating basic resource keys for registries. + +```java +ResourceKey> COOKIE_RECIPE_REGISTRY = RegistryKeys.from(NamespacedIdentifiers.from("example", "cookie_recipe")); +``` + +Registries should be loaded in your mod's entrypoint. The `Registries` class provides helper methods for registering simple and defaulted registries. You can pass along a bootstrap for generating your registry's contents. + +```java +Registry COOKIE_RECIPE = Registries.registerSimple(COOKIE_RECIPE_REGISTRY, CookieRecipes::init); +``` + +An example setup is shown below. + +```java +package com.example; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registries; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public class ExampleRegistries { + + public static final ResourceKey> COOKIE_RECIPE_REGISTRY = RegistryKeys.from(NamespacedIdentifiers.from("example", "cookie_recipe")); + + public static final Registry COOKIE_RECIPE = Registries.registerSimple(COOKIE_RECIPE_REGISTRY, CookieRecipes::init); + + public static void init() { + } +} +``` + +```java +package com.example; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; + +public class CookieRecipes { + + public static final CookieRecipe CHOCOLATE_CHIP = Registry.register(ExampleRegistries.COOKIE_RECIPE, NamespacedIdentifiers.from("example", "chocolate_chip"), new ChocolateChipCookieRecipe()); + + public static void init() { + } +} +``` + +```java +package com.example; + +import net.ornithemc.osl.entrypoints.api.ModInitializer; + +public class ExampleInitializer implements ModInitializer { + + @Override + public void init() { + ExampleRegistries.init(); + } +} +``` + +## Registry Sync + +To ensure numerical IDs are consistent between the server and client and across sessions, you can register registry your registry through the `SyncedRegistries` class. This should also be done in your mod's entrypoint. An update to the above example is shown below. + +```java +package com.example; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registries; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.SyncedRegistries; + +public class ExampleRegistries { + + public static final ResourceKey> COOKIE_RECIPE_REGISTRY = RegistryKeys.from(NamespacedIdentifiers.from("example", "cookie_recipe")); + + public static final Registry COOKIE_RECIPE = Registries.registerSimple(COOKIE_RECIPE_REGISTRY, CookieRecipes::init); + + public static void init() { + SyncedRegistries.register(COOKIE_RECIPE_REGISTRY); + } +} +``` + +If the numerical IDs of your registry are used in any way that is persistent across game sessions (think of Vanilla's item model registry, for example), you must register an ID mapper or fixer for those. This API provides implementations for remapping fastutils' `Int2ObjectMap` and Vanilla's `Id2ObjectBiMap` in `Int2ObjectMapMapper` and `Id2ObjectBiMapMapper` respectively. diff --git a/libraries/registries/build.gradle b/libraries/registries/build.gradle new file mode 100644 index 000000000..dddbc1fec --- /dev/null +++ b/libraries/registries/build.gradle @@ -0,0 +1,5 @@ +setUpLibrary(project) + +dependencies { + implementation 'it.unimi.dsi:fastutil:8.5.9' +} diff --git a/libraries/registries/gradle.properties b/libraries/registries/gradle.properties new file mode 100644 index 000000000..403bf484a --- /dev/null +++ b/libraries/registries/gradle.properties @@ -0,0 +1,7 @@ +library_id = registries +library_name = Registries +library_description = Registries API and numerical ID synchronization. +library_version = 0.1.0-alpha.1 + +entrypoint_client_init = net.ornithemc.osl.registries.impl.RegistriesEntrypoint +osl_dependencies = core:>=0.8.0,entrypoints:>=0.5.0,lifecycle-events:>=0.6.0,executors:>=0.1.0,text-components:>=0.1.0-,networking:>=0.9.0,networking-impl:>=0.1.0 diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/build.gradle b/libraries/registries/registries-mc13w36a-mc14w26c/build.gradle new file mode 100644 index 000000000..0a350fdb3 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/build.gradle @@ -0,0 +1 @@ +setUpModule(project) diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/gradle.properties b/libraries/registries/registries-mc13w36a-mc14w26c/gradle.properties new file mode 100644 index 000000000..1cad83f51 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/gradle.properties @@ -0,0 +1,8 @@ +min_mc_version = 13w36a +max_mc_version = 14w26c +minecraft_dependency = >=1.7-alpha.13.36.a <=1.8-alpha.14.26.c + +minecraft_version = 1.7.2 +raven_build = 1 +sparrow_build = 1 +nests_build = 3 diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java new file mode 100644 index 000000000..68100e620 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java @@ -0,0 +1,22 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; + +public final class RegistryKeys { + + // commonly used registry keys, for use in other APIs + public static final ResourceKey> BLOCK = from("block"); + public static final ResourceKey> ITEM = from("item"); + + public static ResourceKey> from(String identifier) { + return from(NamespacedIdentifiers.from(identifier)); + } + + public static ResourceKey> from(NamespacedIdentifier identifier) { + return ResourceKeys.from(identifier); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java new file mode 100644 index 000000000..f6896b0bd --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,43 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.api.client.ClientPlayNetworking; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +public final class RegistriesEntrypoint implements ClientModInitializer { + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(Constants.OSL_REGISTRY_SYNC_CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesPacketSerializer.deserialize(buffer, RegistryMappingSource.REMOTE_SERVER); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.applyMappings(); + }); + } catch (RegistryMappingException e) { + RegistriesImpl.LOGGER.error("Unable to remap registries!", e); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.resetMappings(); + + if (context.networkHandler().getConnection().isConnected()) { + context.networkHandler().getConnection().disconnect(new LiteralText("Failed to remap registries: " + e.getMessage())); + } + }); + } + }); + ClientConnectionEvents.DISCONNECT.register(context -> { + if (!context.isServerLocal()) { + SyncedRegistriesImpl.undoMappings(); + } + }); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java new file mode 100644 index 000000000..02c3c9582 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java @@ -0,0 +1,24 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.server.integrated.IntegratedServer; + +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(IntegratedServer.class) +public class IntegratedServerMixin { + + @Inject( + method = "shutdown", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$unmapRegistries(CallbackInfo ci) { + SyncedRegistriesImpl.undoMappings(); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java new file mode 100644 index 000000000..93002021e --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,130 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.WorldData; +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesNbtSerializer; + +@Mixin(AlphaWorldStorage.class) +public class AlphaWorldStorageMixin { + + @Shadow @Final + private String name; + + @Shadow + private File getDirectory() { return null; } + + @Inject( + method = "loadData", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfoReturnable cir) { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + + if (!this.readRegistryMappings(file, false)) { + file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + if (!this.readRegistryMappings(file, true)) { + RegistriesImpl.LOGGER.debug("no registry mappings read for '" + this.name + "'"); + } + } + } + + @Unique + private boolean readRegistryMappings(File file, boolean throwOnException) { + if (file.exists()) { + try (InputStream is = new FileInputStream(file)) { + NbtCompound nbt = NbtIo.readCompressed(is); + + SyncedRegistriesNbtSerializer.deserialize(nbt, RegistryMappingSource.WORLD_SAVE); + SyncedRegistriesImpl.applyMappings(); + + return true; + } catch (IOException e) { + if (throwOnException) { + throw new RuntimeException("Unable to read registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("error while reading registry mappings for '" + this.name + "'", e); + } + } catch (RegistryMappingException e) { + if (throwOnException) { + throw new RuntimeException("Invalid registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("invalid registry mappings for '" + this.name + "'", e); + } + } + } + + return false; + } + + @Inject( + method = "saveData(Lnet/minecraft/world/WorldData;Lnet/minecraft/nbt/NbtCompound;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(CallbackInfo ci) { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + File tmp = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_tmp"); + File backup = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + this.writeRegistryMappings(file, tmp, backup); + } + + @Unique + private void writeRegistryMappings(File file, File newFile, File oldFile) { + NbtCompound nbt = new NbtCompound(); + + try { + SyncedRegistriesNbtSerializer.serialize(nbt); + + try (OutputStream os = new FileOutputStream(newFile)) { + NbtIo.writeCompressed(nbt, os); + } + + if (oldFile.exists()) { + oldFile.delete(); + } + + file.renameTo(oldFile); + if (file.exists()) { + file.delete(); + } + + newFile.renameTo(file); + if (newFile.exists()) { + newFile.delete(); + } + } catch (IOException e) { + RegistriesImpl.LOGGER.warn("error while writing registry mappings for '" + this.name + "'", e); + } + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java new file mode 100644 index 000000000..4b2aa2822 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.Bootstrap; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(Bootstrap.class) +public class BootstrapMixin { + + @Inject( + method = "init", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/stat/Stats;init()V" + ) + ) + private static void osl$registries$initAndLockRegistries(CallbackInfo ci) { + RegistriesImpl.init(); + SyncedRegistriesImpl.init(); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java new file mode 100644 index 000000000..e83acb15e --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import gnu.trove.map.hash.TIntIntHashMap; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; + +import net.ornithemc.osl.registries.impl.registry.Clearable; + +@Mixin(CrudeIncrementalIntIdentityHashMap.class) +public class CrudeIncrementalIntIdentityHashMapMixin implements Clearable { + + @Shadow + private TIntIntHashMap ids; + @Shadow + private List values; + + @Override + public void osl$registries$clear() { + this.ids.clear(); + this.values.clear(); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java new file mode 100644 index 000000000..ea2c60afe --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.util.registry.DefaultedIdRegistry; + +@Mixin(DefaultedIdRegistry.class) +public interface DefaultedIdRegistryAccess { + + @Accessor("defaultKey") + String accessDefaultKey(); + +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java new file mode 100644 index 000000000..d7da0d282 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java @@ -0,0 +1,60 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Map; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; +import net.minecraft.util.registry.IdRegistry; +import net.minecraft.util.registry.MappedRegistry; + +import net.ornithemc.osl.registries.impl.registry.Clearable; +import net.ornithemc.osl.registries.impl.registry.IdRegistryAccess; +import net.ornithemc.osl.registries.impl.registry.WrappedIdRegistry.RegisterCallback; + +@Mixin(IdRegistry.class) +public class IdRegistryMixin extends MappedRegistry implements IdRegistryAccess, Clearable { + + @Shadow @Final + private CrudeIncrementalIntIdentityHashMap ids; + @Shadow @Final + private Map keys; + + @Unique + private RegisterCallback callback; + + @Inject( + method = "register", + at = @At( + value = "RETURN" + ) + ) + private void osl$registries$register(int id, String key, T value, CallbackInfo ci) { + if (this.callback != null) { + this.callback.valueRegistered(id, key, value); + } + } + + @Override + public void osl$registries$setCallback(RegisterCallback callback) { + this.callback = callback; + } + + @Override + public boolean osl$registries$has(Object value) { + return this.keys.containsKey(value); + } + + @Override + public void osl$registries$clear() { + this.entries.clear(); + this.keys.clear(); + Clearable.clear(this.ids); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java new file mode 100644 index 000000000..37a827c2d --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerPlayNetworking; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final + private MinecraftServer server; + + @Inject( + method = "onLogin", + at = @At( + value = "NEW", + target = "net/minecraft/network/packet/s2c/play/LoginS2CPacket" + ) + ) + private void osl$idsync$syncRegistries(CallbackInfo ci, @Local ServerPlayerEntity player) { + if (this.server.isDedicated() || !this.server.getUsername().equals(player.getName())) { + ServerPlayNetworking.sendNoCheck(player, Constants.OSL_REGISTRY_SYNC_CHANNEL, SyncedRegistriesPacketSerializer::serialize); + } + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/Clearable.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/Clearable.java new file mode 100644 index 000000000..662971ffd --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/Clearable.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.registries.impl.registry; + +public interface Clearable { + + static void clear(Object o) { + if (o instanceof Clearable) { + ((Clearable) o).osl$registries$clear(); + } else { + throw new IllegalArgumentException("not clearable: " + o); + } + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/IdRegistryAccess.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/IdRegistryAccess.java new file mode 100644 index 000000000..e6535ddcb --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/IdRegistryAccess.java @@ -0,0 +1,18 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.ornithemc.osl.registries.impl.registry.WrappedIdRegistry.RegisterCallback; + +public interface IdRegistryAccess { + + default void osl$registries$setCallback(RegisterCallback callback) { + throw new AbstractMethodError(); + } + + default boolean osl$registries$has(Object value) { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java new file mode 100644 index 000000000..7d2fa4d67 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,19 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.DefaultedIdRegistry; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public final class VanillaRegistries { + + public static Registry registerSimple(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedIdRegistry.of(key, (IdRegistry) registry), () -> { }); + } + + public static DefaultedRegistry registerDefaulted(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedDefaultedIdRegistry.of(key, (DefaultedIdRegistry) registry), () -> { }); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java new file mode 100644 index 000000000..2c6ff3324 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java @@ -0,0 +1,25 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.DefaultedIdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.impl.mixin.common.DefaultedIdRegistryAccess; + +public class WrappedDefaultedIdRegistry extends WrappedIdRegistry implements DefaultedRegistry { + + public static WrappedDefaultedIdRegistry of(ResourceKey> key, DefaultedIdRegistry registry) { + return new WrappedDefaultedIdRegistry<>(key.identifier(), registry); + } + + private WrappedDefaultedIdRegistry(NamespacedIdentifier identifier, DefaultedIdRegistry registry) { + super(identifier, registry); + } + + @Override + public NamespacedIdentifier getDefaultIdentifier() { + return this.serializeKey(((DefaultedIdRegistryAccess) this.registry).accessDefaultKey()); + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java new file mode 100644 index 000000000..1876ef88b --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java @@ -0,0 +1,142 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.Iterator; +import java.util.Set; +import java.util.stream.Collectors; + +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.ResourceKeys; + +public class WrappedIdRegistry implements ClearableRegistry { + + public static WrappedIdRegistry of(ResourceKey> key, IdRegistry registry) { + return new WrappedIdRegistry<>(key.identifier(), registry); + } + + final NamespacedIdentifier identifier; + final IdRegistry registry; + + private int nextId; + private boolean frozen; + + WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + NamespacedIdentifier serializeKey(String key) { + return key == null ? null : NamespacedIdentifiers.parse(key); + } + + String deserializeKey(NamespacedIdentifier identifier) { + return identifier == null ? null : identifier.toString(); + } + + ResourceKey resourceKey(NamespacedIdentifier identifier) { + return identifier == null ? null : ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, String key, Object value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public V register(ResourceKey key, V value) { + return this.register(this.nextId, key, value); + } + + @Override + public V register(int id, ResourceKey key, V value) { + this.registry.register(id, this.deserializeKey(key.identifier()), value); + return value; + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } + + @Override + public T get(int id) { + return this.registry.get(id); + } + + @Override + public T get(ResourceKey key) { + return this.registry.get(this.deserializeKey(key.identifier())); + } + + @Override + public T get(NamespacedIdentifier identifier) { + return this.registry.get(this.deserializeKey(identifier)); + } + + @Override + public boolean has(T value) { + return this.registry.osl$registries$has(value); + } + + @Override + public int getId(T value) { + return this.registry.getId(value); + } + + @Override + public ResourceKey getKey(T value) { + return this.resourceKey(this.serializeKey(this.registry.getKey(value))); + } + + @Override + public NamespacedIdentifier getIdentifier(T value) { + return this.serializeKey(this.registry.getKey(value)); + } + + @Override + public Set> keySet() { + return this.registry.keySet().stream().map(this::serializeKey).map(this::resourceKey).collect(Collectors.toSet()); + } + + @Override + public Set identifierSet() { + return this.registry.keySet().stream().map(this::serializeKey).collect(Collectors.toSet()); + } + + @Override + public Iterator iterator() { + return this.registry.iterator(); + } + + @Override + public Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public void clear() { + this.registry.osl$registries$clear(); + + this.nextId = 0; + this.frozen = false; + } + + public interface RegisterCallback { + + void valueRegistered(int id, String key, Object value); + + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java new file mode 100644 index 000000000..e24782755 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java @@ -0,0 +1,79 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.minecraft.nbt.NbtCompound; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesNbtSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(NbtCompound nbt) throws IOException { + NbtCompound registriesNbt = new NbtCompound(); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt, SyncedRegistriesNbtSerializer::serialize); + registriesNbt.put(identifier.toString(), mappingsNbt); + } + + nbt.putInt(Constants.FORMAT_NBT_KEY, Constants.REGISTRY_MAPPINGS_FORMAT); + nbt.put(Constants.REGISTRIES_NBT_KEY, registriesNbt); + } + + public static void deserialize(NbtCompound nbt, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = nbt.getInt(Constants.FORMAT_NBT_KEY); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + NbtCompound registriesNbt = nbt.getCompound(Constants.REGISTRIES_NBT_KEY); + + for (String key : registriesNbt.getKeys()) { + NbtCompound mappingsNbt = registriesNbt.getCompound(key); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(key); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(mappingsNbt, SyncedRegistriesNbtSerializer::deserialize, source); + mappings.build(source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(NbtCompound nbt, Object2IntMap mappings) throws IOException { + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } + + public static void deserialize(NbtCompound nbt, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + for (String key : nbt.getKeys()) { + mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java new file mode 100644 index 000000000..f1fc0a2e3 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java @@ -0,0 +1,82 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesPacketSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(Constants.REGISTRY_MAPPINGS_FORMAT); + buffer.writeVarInt(REGISTRIES.keySet().size()); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer, SyncedRegistriesPacketSerializer::serialize); + } + } + + public static void deserialize(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(buffer, SyncedRegistriesPacketSerializer::deserialize, source); + mappings.build(source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(PacketBuffer buffer, Object2IntMap mappings) throws IOException { + buffer.writeVarInt(mappings.size()); + + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public static void deserialize(PacketBuffer buffer, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + mappings.put(identifier, id); + } + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/fabric.mod.json b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..faa20f931 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/fabric.mod.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc13w36a-mc14w26c", + "environment": "*", + "entrypoints": { + "client-init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ] + }, + "mixins": [ + "osl.registries.mixins.json" + ], + "accessWidener": "osl.registries.classtweaker", + "depends": { + "fabricloader": "\u003e\u003d0.18.0", + "minecraft": "\u003e\u003d1.7-alpha.13.36.a \u003c\u003d1.8-alpha.14.26.c", + "osl-core": "\u003e\u003d0.8.0", + "osl-entrypoints": "\u003e\u003d0.5.0", + "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", + "osl-networking": "\u003e\u003d0.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0" + }, + "name": "OSL Registries", + "description": "Registries API and numerical ID synchronization.", + "authors": [ + "OrnitheMC" + ], + "contact": { + "homepage": "https://ornithemc.net/", + "issues": "https://github.com/OrnitheMC/ornithe-standard-libraries/issues", + "sources": "https://github.com/OrnitheMC/ornithe-standard-libraries" + }, + "license": "Apache-2.0" +} \ No newline at end of file diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/osl.registries.classtweaker b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/osl.registries.classtweaker new file mode 100644 index 000000000..5a5a61e9c --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/osl.registries.classtweaker @@ -0,0 +1,3 @@ +classTweaker v1 named + +inject-interface net/minecraft/util/registry/IdRegistry net/ornithemc/osl/registries/impl/registry/IdRegistryAccess diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/osl.registries.mixins.json b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/osl.registries.mixins.json new file mode 100644 index 000000000..127fc8935 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,22 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.BootstrapMixin", + "common.CrudeIncrementalIntIdentityHashMapMixin", + "common.DefaultedIdRegistryAccess", + "common.IdRegistryMixin", + "common.PlayerManagerMixin" + ], + "client": [ + "client.IntegratedServerMixin" + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/build.gradle b/libraries/registries/registries-mc14w27a-mc17w46a/build.gradle new file mode 100644 index 000000000..0a350fdb3 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/build.gradle @@ -0,0 +1 @@ +setUpModule(project) diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/gradle.properties b/libraries/registries/registries-mc14w27a-mc17w46a/gradle.properties new file mode 100644 index 000000000..6b9ea8e51 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/gradle.properties @@ -0,0 +1,7 @@ +min_mc_version = 14w27a +max_mc_version = 17w46a +minecraft_dependency = >=1.8-alpha.14.27.a <=1.13-alpha.17.46.a + +minecraft_version = 1.12.2 +raven_build = 1 +sparrow_build = 1 diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java new file mode 100644 index 000000000..68100e620 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java @@ -0,0 +1,22 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; + +public final class RegistryKeys { + + // commonly used registry keys, for use in other APIs + public static final ResourceKey> BLOCK = from("block"); + public static final ResourceKey> ITEM = from("item"); + + public static ResourceKey> from(String identifier) { + return from(NamespacedIdentifiers.from(identifier)); + } + + public static ResourceKey> from(NamespacedIdentifier identifier) { + return ResourceKeys.from(identifier); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java new file mode 100644 index 000000000..17a3c64a5 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java @@ -0,0 +1,53 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import net.minecraft.util.Id2ObjectBiMap; + +public class Id2ObjectBiMapMapper implements IdMapper { + + public static Id2ObjectBiMapMapper of(Id2ObjectBiMap registry) { + return new Id2ObjectBiMapMapper(registry); + } + + private final Id2ObjectBiMap registry; + private final Id2ObjectBiMap backup; + + @SuppressWarnings("unchecked") + private Id2ObjectBiMapMapper(Id2ObjectBiMap registry) { + this.registry = (Id2ObjectBiMap) registry; + this.backup = new Id2ObjectBiMap<>(registry.size()); + } + + /* + * unlike Registry, Id2ObjectBiMap allows duplicate values + * thus iterating over all values will not give you all id-value pairs! + */ + + @Override + public void apply(RegistryMappings mappings) { + this.backup.osl$registries$clear();; + + for (int id : this.registry.osl$registries$idSet()) { + this.backup.put(this.registry.get(id), id); + } + + this.registry.osl$registries$clear();; + + for (int oldId : this.backup.osl$registries$idSet()) { + Object value = this.backup.get(oldId); + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry.put(value, newId); + } + } + } + + @Override + public void undo(RegistryMappings mappings) { + this.registry.osl$registries$clear();; + + for (int id : this.backup.osl$registries$idSet()) { + this.registry.put(this.backup.get(id), id); + } + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java new file mode 100644 index 000000000..f6896b0bd --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,43 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.api.client.ClientPlayNetworking; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +public final class RegistriesEntrypoint implements ClientModInitializer { + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(Constants.OSL_REGISTRY_SYNC_CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesPacketSerializer.deserialize(buffer, RegistryMappingSource.REMOTE_SERVER); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.applyMappings(); + }); + } catch (RegistryMappingException e) { + RegistriesImpl.LOGGER.error("Unable to remap registries!", e); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.resetMappings(); + + if (context.networkHandler().getConnection().isConnected()) { + context.networkHandler().getConnection().disconnect(new LiteralText("Failed to remap registries: " + e.getMessage())); + } + }); + } + }); + ClientConnectionEvents.DISCONNECT.register(context -> { + if (!context.isServerLocal()) { + SyncedRegistriesImpl.undoMappings(); + } + }); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java new file mode 100644 index 000000000..89d9cc768 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java @@ -0,0 +1,54 @@ +package net.ornithemc.osl.registries.impl; + +import java.util.List; +import java.util.Set; + +import org.objectweb.asm.tree.ClassNode; + +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import net.ornithemc.osl.core.impl.util.MinecraftVersion; + +public class RegistriesMixinPlugin implements IMixinConfigPlugin { + + public static final boolean NEW_CRUDE_INCREMENTAL_INT_IDENTITY_HASH_MAP_IMPLEMENTATION = MinecraftVersion.resolve().compareTo("15w35a") >= 0; + + @Override + public void onLoad(String mixinPackage) { + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if ("net.ornithemc.osl.registries.impl.mixin.common.CrudeIncrementalIntIdentityHashMapMixinNew".equals(mixinClassName)) { + return NEW_CRUDE_INCREMENTAL_INT_IDENTITY_HASH_MAP_IMPLEMENTATION; + } + if ("net.ornithemc.osl.registries.impl.mixin.common.CrudeIncrementalIntIdentityHashMapMixinOld".equals(mixinClassName)) { + return !NEW_CRUDE_INCREMENTAL_INT_IDENTITY_HASH_MAP_IMPLEMENTATION; + } + + return true; + } + + @Override + public void acceptTargets(Set myTargets, Set otherTargets) { + } + + @Override + public List getMixins() { + return null; + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java new file mode 100644 index 000000000..02c3c9582 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java @@ -0,0 +1,24 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.server.integrated.IntegratedServer; + +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(IntegratedServer.class) +public class IntegratedServerMixin { + + @Inject( + method = "shutdown", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$unmapRegistries(CallbackInfo ci) { + SyncedRegistriesImpl.undoMappings(); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java new file mode 100644 index 000000000..93002021e --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,130 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.WorldData; +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesNbtSerializer; + +@Mixin(AlphaWorldStorage.class) +public class AlphaWorldStorageMixin { + + @Shadow @Final + private String name; + + @Shadow + private File getDirectory() { return null; } + + @Inject( + method = "loadData", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfoReturnable cir) { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + + if (!this.readRegistryMappings(file, false)) { + file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + if (!this.readRegistryMappings(file, true)) { + RegistriesImpl.LOGGER.debug("no registry mappings read for '" + this.name + "'"); + } + } + } + + @Unique + private boolean readRegistryMappings(File file, boolean throwOnException) { + if (file.exists()) { + try (InputStream is = new FileInputStream(file)) { + NbtCompound nbt = NbtIo.readCompressed(is); + + SyncedRegistriesNbtSerializer.deserialize(nbt, RegistryMappingSource.WORLD_SAVE); + SyncedRegistriesImpl.applyMappings(); + + return true; + } catch (IOException e) { + if (throwOnException) { + throw new RuntimeException("Unable to read registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("error while reading registry mappings for '" + this.name + "'", e); + } + } catch (RegistryMappingException e) { + if (throwOnException) { + throw new RuntimeException("Invalid registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("invalid registry mappings for '" + this.name + "'", e); + } + } + } + + return false; + } + + @Inject( + method = "saveData(Lnet/minecraft/world/WorldData;Lnet/minecraft/nbt/NbtCompound;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(CallbackInfo ci) { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + File tmp = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_tmp"); + File backup = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + this.writeRegistryMappings(file, tmp, backup); + } + + @Unique + private void writeRegistryMappings(File file, File newFile, File oldFile) { + NbtCompound nbt = new NbtCompound(); + + try { + SyncedRegistriesNbtSerializer.serialize(nbt); + + try (OutputStream os = new FileOutputStream(newFile)) { + NbtIo.writeCompressed(nbt, os); + } + + if (oldFile.exists()) { + oldFile.delete(); + } + + file.renameTo(oldFile); + if (file.exists()) { + file.delete(); + } + + newFile.renameTo(file); + if (newFile.exists()) { + newFile.delete(); + } + } catch (IOException e) { + RegistriesImpl.LOGGER.warn("error while writing registry mappings for '" + this.name + "'", e); + } + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java new file mode 100644 index 000000000..9c720b26f --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.Bootstrap; + +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(Bootstrap.class) +public class BootstrapMixin { + + @Inject( + method = "init", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/stat/Stats;init()V" + ) + ) + private static void osl$registries$initAndLockRegistries(CallbackInfo ci) { + RegistriesImpl.init(); + SyncedRegistriesImpl.init(); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixinNew.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixinNew.java new file mode 100644 index 000000000..1cabc407f --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixinNew.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Arrays; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; + +import net.ornithemc.osl.registries.impl.registry.Clearable; + +@Mixin(CrudeIncrementalIntIdentityHashMap.class) +public class CrudeIncrementalIntIdentityHashMapMixinNew implements Clearable { + + @Shadow + private Object[] keys; + @Shadow + private Object[] byId; + + @Shadow + private int nextId; + @Shadow + private int size; + + @Override + public void osl$registries$clear() { + Arrays.fill(this.keys, null); + Arrays.fill(this.byId, null); + + this.nextId = 0; + this.size = 0; + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixinOld.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixinOld.java new file mode 100644 index 000000000..2fee3cc2e --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixinOld.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.IdentityHashMap; +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; + +import net.ornithemc.osl.registries.impl.registry.Clearable; + +@Mixin(CrudeIncrementalIntIdentityHashMap.class) +public class CrudeIncrementalIntIdentityHashMapMixinOld implements Clearable { + + @Shadow + private IdentityHashMap f_29800171; // ids + @Shadow + private List f_87828088; // values + + @Override + public void osl$registries$clear() { + this.f_29800171.clear(); + this.f_87828088.clear(); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java new file mode 100644 index 000000000..cc07e9aa0 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.util.registry.DefaultedIdRegistry; + +@Mixin(DefaultedIdRegistry.class) +public interface DefaultedIdRegistryAccess { + + @Accessor("defaultKey") + Object accessDefaultKey(); + +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java new file mode 100644 index 000000000..3e5c3bc3e --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java @@ -0,0 +1,54 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.IdentityHashMap; +import java.util.List; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; + +import net.minecraft.util.Id2ObjectBiMap; + +import net.ornithemc.osl.registries.impl.registry.Clearable; +import net.ornithemc.osl.registries.impl.registry.Id2ObjectBiMapAccess; + +@Mixin(Id2ObjectBiMap.class) +public class Id2ObjectBiMapMixin implements Id2ObjectBiMapAccess, Clearable { + + @Shadow @Final + private List values; + @Shadow @Final + private IdentityHashMap ids; + + @Unique + private final IntSet idSet = new IntOpenHashSet(); + + @Inject( + method = "put(Ljava/lang/Object;I)V", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$put(T value, int id, CallbackInfo ci) { + this.idSet.add(id); + } + + @Override + public IntSet osl$registries$idSet() { + return this.idSet; + } + + @Override + public void osl$registries$clear() { + this.values.clear(); + this.ids.clear(); + this.idSet.clear(); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java new file mode 100644 index 000000000..40d72e4c8 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java @@ -0,0 +1,60 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Map; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; +import net.minecraft.util.registry.IdRegistry; +import net.minecraft.util.registry.MappedRegistry; + +import net.ornithemc.osl.registries.impl.registry.Clearable; +import net.ornithemc.osl.registries.impl.registry.IdRegistryAccess; +import net.ornithemc.osl.registries.impl.registry.WrappedIdRegistry.RegisterCallback; + +@Mixin(IdRegistry.class) +public class IdRegistryMixin extends MappedRegistry implements IdRegistryAccess, Clearable { + + @Shadow @Final + private CrudeIncrementalIntIdentityHashMap ids; + @Shadow @Final + private Map keys; + + @Unique + private RegisterCallback callback; + + @Inject( + method = "register", + at = @At( + value = "RETURN" + ) + ) + private void osl$registries$register(int id, K key, V value, CallbackInfo ci) { + if (this.callback != null) { + this.callback.valueRegistered(id, key, value); + } + } + + @Override + public void osl$registries$setCallback(RegisterCallback callback) { + this.callback = callback; + } + + @Override + public boolean osl$registries$has(Object value) { + return this.keys.containsKey(value); + } + + @Override + public void osl$registries$clear() { + this.entries.clear(); + this.keys.clear(); + Clearable.clear(this.ids); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java new file mode 100644 index 000000000..37a827c2d --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerPlayNetworking; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final + private MinecraftServer server; + + @Inject( + method = "onLogin", + at = @At( + value = "NEW", + target = "net/minecraft/network/packet/s2c/play/LoginS2CPacket" + ) + ) + private void osl$idsync$syncRegistries(CallbackInfo ci, @Local ServerPlayerEntity player) { + if (this.server.isDedicated() || !this.server.getUsername().equals(player.getName())) { + ServerPlayNetworking.sendNoCheck(player, Constants.OSL_REGISTRY_SYNC_CHANNEL, SyncedRegistriesPacketSerializer::serialize); + } + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/Clearable.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/Clearable.java new file mode 100644 index 000000000..662971ffd --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/Clearable.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.registries.impl.registry; + +public interface Clearable { + + static void clear(Object o) { + if (o instanceof Clearable) { + ((Clearable) o).osl$registries$clear(); + } else { + throw new IllegalArgumentException("not clearable: " + o); + } + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess.java new file mode 100644 index 000000000..7789e2a09 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.registry; + +import it.unimi.dsi.fastutil.ints.IntSet; + +public interface Id2ObjectBiMapAccess { + + default IntSet osl$registries$idSet() { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/IdRegistryAccess.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/IdRegistryAccess.java new file mode 100644 index 000000000..e6535ddcb --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/IdRegistryAccess.java @@ -0,0 +1,18 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.ornithemc.osl.registries.impl.registry.WrappedIdRegistry.RegisterCallback; + +public interface IdRegistryAccess { + + default void osl$registries$setCallback(RegisterCallback callback) { + throw new AbstractMethodError(); + } + + default boolean osl$registries$has(Object value) { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java new file mode 100644 index 000000000..10f5ea4cf --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,20 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.DefaultedIdRegistry; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public final class VanillaRegistries { + + public static Registry registerSimple(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedIdRegistry.of(key, (IdRegistry) registry), () -> { }); + } + + public static DefaultedRegistry registerDefaulted(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedDefaultedIdRegistry.of(key, (DefaultedIdRegistry) registry), () -> { }); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java new file mode 100644 index 000000000..ae769c9c0 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.DefaultedIdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.impl.mixin.common.DefaultedIdRegistryAccess; + +public class WrappedDefaultedIdRegistry extends WrappedIdRegistry implements DefaultedRegistry { + + public static WrappedDefaultedIdRegistry of(ResourceKey> key, DefaultedIdRegistry registry) { + return new WrappedDefaultedIdRegistry<>(key.identifier(), registry); + } + + private WrappedDefaultedIdRegistry(NamespacedIdentifier identifier, DefaultedIdRegistry registry) { + super(identifier, registry); + } + + @Override + public NamespacedIdentifier getDefaultIdentifier() { + return this.serializeKey((Identifier) ((DefaultedIdRegistryAccess) this.registry).accessDefaultKey()); + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java new file mode 100644 index 000000000..c51a71cd6 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java @@ -0,0 +1,142 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.Iterator; +import java.util.Set; +import java.util.stream.Collectors; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.ResourceKeys; + +public class WrappedIdRegistry implements ClearableRegistry { + + public static WrappedIdRegistry of(ResourceKey> key, IdRegistry registry) { + return new WrappedIdRegistry<>(key.identifier(), registry); + } + + final NamespacedIdentifier identifier; + final IdRegistry registry; + + private int nextId; + private boolean frozen; + + WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + NamespacedIdentifier serializeKey(Identifier key) { + return key; + } + + Identifier deserializeKey(NamespacedIdentifier identifier) { + return identifier == null ? null : (identifier instanceof Identifier ? (Identifier) identifier : new Identifier(identifier.namespace(), identifier.identifier())); + } + + ResourceKey resourceKey(NamespacedIdentifier identifier) { + return identifier == null ? null : ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, Object key, Object value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public V register(ResourceKey key, V value) { + return this.register(this.nextId, key, value); + } + + @Override + public V register(int id, ResourceKey key, V value) { + this.registry.register(id, this.deserializeKey(key.identifier()), value); + return value; + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } + + @Override + public T get(int id) { + return this.registry.get(id); + } + + @Override + public T get(ResourceKey key) { + return this.registry.get(this.deserializeKey(key.identifier())); + } + + @Override + public T get(NamespacedIdentifier identifier) { + return this.registry.get(this.deserializeKey(identifier)); + } + + @Override + public boolean has(T value) { + return this.registry.osl$registries$has(value); + } + + @Override + public int getId(T value) { + return this.registry.getId(value); + } + + @Override + public ResourceKey getKey(T value) { + return this.resourceKey(this.serializeKey(this.registry.getKey(value))); + } + + @Override + public NamespacedIdentifier getIdentifier(T value) { + return this.serializeKey(this.registry.getKey(value)); + } + + @Override + public Set> keySet() { + return this.registry.keySet().stream().map(this::serializeKey).map(this::resourceKey).collect(Collectors.toSet()); + } + + @Override + public Set identifierSet() { + return this.registry.keySet().stream().map(this::serializeKey).collect(Collectors.toSet()); + } + + @Override + public Iterator iterator() { + return this.registry.iterator(); + } + + @Override + public Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public void clear() { + this.registry.osl$registries$clear(); + + this.nextId = 0; + this.frozen = false; + } + + public interface RegisterCallback { + + void valueRegistered(int id, Object key, Object value); + + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java new file mode 100644 index 000000000..e24782755 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java @@ -0,0 +1,79 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.minecraft.nbt.NbtCompound; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesNbtSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(NbtCompound nbt) throws IOException { + NbtCompound registriesNbt = new NbtCompound(); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt, SyncedRegistriesNbtSerializer::serialize); + registriesNbt.put(identifier.toString(), mappingsNbt); + } + + nbt.putInt(Constants.FORMAT_NBT_KEY, Constants.REGISTRY_MAPPINGS_FORMAT); + nbt.put(Constants.REGISTRIES_NBT_KEY, registriesNbt); + } + + public static void deserialize(NbtCompound nbt, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = nbt.getInt(Constants.FORMAT_NBT_KEY); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + NbtCompound registriesNbt = nbt.getCompound(Constants.REGISTRIES_NBT_KEY); + + for (String key : registriesNbt.getKeys()) { + NbtCompound mappingsNbt = registriesNbt.getCompound(key); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(key); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(mappingsNbt, SyncedRegistriesNbtSerializer::deserialize, source); + mappings.build(source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(NbtCompound nbt, Object2IntMap mappings) throws IOException { + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } + + public static void deserialize(NbtCompound nbt, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + for (String key : nbt.getKeys()) { + mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java new file mode 100644 index 000000000..f1fc0a2e3 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java @@ -0,0 +1,82 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesPacketSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(Constants.REGISTRY_MAPPINGS_FORMAT); + buffer.writeVarInt(REGISTRIES.keySet().size()); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer, SyncedRegistriesPacketSerializer::serialize); + } + } + + public static void deserialize(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(buffer, SyncedRegistriesPacketSerializer::deserialize, source); + mappings.build(source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(PacketBuffer buffer, Object2IntMap mappings) throws IOException { + buffer.writeVarInt(mappings.size()); + + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public static void deserialize(PacketBuffer buffer, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + mappings.put(identifier, id); + } + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/fabric.mod.json b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..b5628aeb6 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/fabric.mod.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc14w27a-mc17w46a", + "environment": "*", + "entrypoints": { + "client-init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ] + }, + "mixins": [ + "osl.registries.mixins.json" + ], + "accessWidener": "osl.registries.classtweaker", + "depends": { + "fabricloader": "\u003e\u003d0.18.0", + "minecraft": "\u003e\u003d1.8-alpha.14.27.a \u003c\u003d1.13-alpha.17.46.a", + "osl-core": "\u003e\u003d0.8.0", + "osl-entrypoints": "\u003e\u003d0.5.0", + "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", + "osl-networking": "\u003e\u003d0.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0" + }, + "name": "OSL Registries", + "description": "Registries API and numerical ID synchronization.", + "authors": [ + "OrnitheMC" + ], + "contact": { + "homepage": "https://ornithemc.net/", + "issues": "https://github.com/OrnitheMC/ornithe-standard-libraries/issues", + "sources": "https://github.com/OrnitheMC/ornithe-standard-libraries" + }, + "license": "Apache-2.0" +} \ No newline at end of file diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/osl.registries.classtweaker b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/osl.registries.classtweaker new file mode 100644 index 000000000..2382db14c --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/osl.registries.classtweaker @@ -0,0 +1,4 @@ +classTweaker v1 named + +inject-interface net/minecraft/util/Id2ObjectBiMap net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess +inject-interface net/minecraft/util/registry/IdRegistry net/ornithemc/osl/registries/impl/registry/IdRegistryAccess \ No newline at end of file diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/osl.registries.mixins.json b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/osl.registries.mixins.json new file mode 100644 index 000000000..90ccd501f --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,25 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "plugin": "net.ornithemc.osl.registries.impl.RegistriesMixinPlugin", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.BootstrapMixin", + "common.CrudeIncrementalIntIdentityHashMapMixinNew", + "common.CrudeIncrementalIntIdentityHashMapMixinOld", + "common.DefaultedIdRegistryAccess", + "common.Id2ObjectBiMapMixin", + "common.IdRegistryMixin", + "common.PlayerManagerMixin" + ], + "client": [ + "client.IntegratedServerMixin" + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/build.gradle b/libraries/registries/registries-mc17w47a-mc18w31a/build.gradle new file mode 100644 index 000000000..0a350fdb3 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/build.gradle @@ -0,0 +1 @@ +setUpModule(project) diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/gradle.properties b/libraries/registries/registries-mc17w47a-mc18w31a/gradle.properties new file mode 100644 index 000000000..214f5d68e --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/gradle.properties @@ -0,0 +1,5 @@ +min_mc_version = 17w47a +max_mc_version = 18w31a +minecraft_dependency = >=1.13-alpha.17.47.a <=1.13.1-alpha.18.31.a + +minecraft_version = 1.13 diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java new file mode 100644 index 000000000..68100e620 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java @@ -0,0 +1,22 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; + +public final class RegistryKeys { + + // commonly used registry keys, for use in other APIs + public static final ResourceKey> BLOCK = from("block"); + public static final ResourceKey> ITEM = from("item"); + + public static ResourceKey> from(String identifier) { + return from(NamespacedIdentifiers.from(identifier)); + } + + public static ResourceKey> from(NamespacedIdentifier identifier) { + return ResourceKeys.from(identifier); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java new file mode 100644 index 000000000..17a3c64a5 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java @@ -0,0 +1,53 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import net.minecraft.util.Id2ObjectBiMap; + +public class Id2ObjectBiMapMapper implements IdMapper { + + public static Id2ObjectBiMapMapper of(Id2ObjectBiMap registry) { + return new Id2ObjectBiMapMapper(registry); + } + + private final Id2ObjectBiMap registry; + private final Id2ObjectBiMap backup; + + @SuppressWarnings("unchecked") + private Id2ObjectBiMapMapper(Id2ObjectBiMap registry) { + this.registry = (Id2ObjectBiMap) registry; + this.backup = new Id2ObjectBiMap<>(registry.size()); + } + + /* + * unlike Registry, Id2ObjectBiMap allows duplicate values + * thus iterating over all values will not give you all id-value pairs! + */ + + @Override + public void apply(RegistryMappings mappings) { + this.backup.osl$registries$clear();; + + for (int id : this.registry.osl$registries$idSet()) { + this.backup.put(this.registry.get(id), id); + } + + this.registry.osl$registries$clear();; + + for (int oldId : this.backup.osl$registries$idSet()) { + Object value = this.backup.get(oldId); + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry.put(value, newId); + } + } + } + + @Override + public void undo(RegistryMappings mappings) { + this.registry.osl$registries$clear();; + + for (int id : this.backup.osl$registries$idSet()) { + this.registry.put(this.backup.get(id), id); + } + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java new file mode 100644 index 000000000..f6896b0bd --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,43 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.api.client.ClientPlayNetworking; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +public final class RegistriesEntrypoint implements ClientModInitializer { + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(Constants.OSL_REGISTRY_SYNC_CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesPacketSerializer.deserialize(buffer, RegistryMappingSource.REMOTE_SERVER); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.applyMappings(); + }); + } catch (RegistryMappingException e) { + RegistriesImpl.LOGGER.error("Unable to remap registries!", e); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.resetMappings(); + + if (context.networkHandler().getConnection().isConnected()) { + context.networkHandler().getConnection().disconnect(new LiteralText("Failed to remap registries: " + e.getMessage())); + } + }); + } + }); + ClientConnectionEvents.DISCONNECT.register(context -> { + if (!context.isServerLocal()) { + SyncedRegistriesImpl.undoMappings(); + } + }); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java new file mode 100644 index 000000000..02c3c9582 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java @@ -0,0 +1,24 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.server.integrated.IntegratedServer; + +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(IntegratedServer.class) +public class IntegratedServerMixin { + + @Inject( + method = "shutdown", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$unmapRegistries(CallbackInfo ci) { + SyncedRegistriesImpl.undoMappings(); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java new file mode 100644 index 000000000..93002021e --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,130 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.WorldData; +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesNbtSerializer; + +@Mixin(AlphaWorldStorage.class) +public class AlphaWorldStorageMixin { + + @Shadow @Final + private String name; + + @Shadow + private File getDirectory() { return null; } + + @Inject( + method = "loadData", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfoReturnable cir) { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + + if (!this.readRegistryMappings(file, false)) { + file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + if (!this.readRegistryMappings(file, true)) { + RegistriesImpl.LOGGER.debug("no registry mappings read for '" + this.name + "'"); + } + } + } + + @Unique + private boolean readRegistryMappings(File file, boolean throwOnException) { + if (file.exists()) { + try (InputStream is = new FileInputStream(file)) { + NbtCompound nbt = NbtIo.readCompressed(is); + + SyncedRegistriesNbtSerializer.deserialize(nbt, RegistryMappingSource.WORLD_SAVE); + SyncedRegistriesImpl.applyMappings(); + + return true; + } catch (IOException e) { + if (throwOnException) { + throw new RuntimeException("Unable to read registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("error while reading registry mappings for '" + this.name + "'", e); + } + } catch (RegistryMappingException e) { + if (throwOnException) { + throw new RuntimeException("Invalid registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("invalid registry mappings for '" + this.name + "'", e); + } + } + } + + return false; + } + + @Inject( + method = "saveData(Lnet/minecraft/world/WorldData;Lnet/minecraft/nbt/NbtCompound;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(CallbackInfo ci) { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + File tmp = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_tmp"); + File backup = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + this.writeRegistryMappings(file, tmp, backup); + } + + @Unique + private void writeRegistryMappings(File file, File newFile, File oldFile) { + NbtCompound nbt = new NbtCompound(); + + try { + SyncedRegistriesNbtSerializer.serialize(nbt); + + try (OutputStream os = new FileOutputStream(newFile)) { + NbtIo.writeCompressed(nbt, os); + } + + if (oldFile.exists()) { + oldFile.delete(); + } + + file.renameTo(oldFile); + if (file.exists()) { + file.delete(); + } + + newFile.renameTo(file); + if (newFile.exists()) { + newFile.delete(); + } + } catch (IOException e) { + RegistriesImpl.LOGGER.warn("error while writing registry mappings for '" + this.name + "'", e); + } + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java new file mode 100644 index 000000000..9c720b26f --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.Bootstrap; + +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(Bootstrap.class) +public class BootstrapMixin { + + @Inject( + method = "init", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/stat/Stats;init()V" + ) + ) + private static void osl$registries$initAndLockRegistries(CallbackInfo ci) { + RegistriesImpl.init(); + SyncedRegistriesImpl.init(); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java new file mode 100644 index 000000000..3dcf24cc0 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Arrays; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; + +import net.ornithemc.osl.registries.impl.registry.Clearable; + +@Mixin(CrudeIncrementalIntIdentityHashMap.class) +public class CrudeIncrementalIntIdentityHashMapMixin implements Clearable { + + @Shadow + private Object[] keys; + @Shadow + private Object[] byId; + + @Shadow + private int nextId; + @Shadow + private int size; + + @Override + public void osl$registries$clear() { + Arrays.fill(this.keys, null); + Arrays.fill(this.byId, null); + + this.nextId = 0; + this.size = 0; + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java new file mode 100644 index 000000000..cc07e9aa0 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.util.registry.DefaultedIdRegistry; + +@Mixin(DefaultedIdRegistry.class) +public interface DefaultedIdRegistryAccess { + + @Accessor("defaultKey") + Object accessDefaultKey(); + +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java new file mode 100644 index 000000000..03edfe3f7 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java @@ -0,0 +1,59 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.IdentityHashMap; +import java.util.List; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; + +import net.minecraft.util.Id2ObjectBiMap; + +import net.ornithemc.osl.registries.impl.registry.Clearable; +import net.ornithemc.osl.registries.impl.registry.Id2ObjectBiMapAccess; + +@Mixin(Id2ObjectBiMap.class) +public class Id2ObjectBiMapMixin implements Id2ObjectBiMapAccess, Clearable { + + @Shadow @Final + private List values; + @Shadow @Final + private IdentityHashMap ids; + + @Shadow + private int nextId; + + @Unique + private final IntSet idSet = new IntOpenHashSet(); + + @Inject( + method = "put(Ljava/lang/Object;I)V", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$put(T value, int id, CallbackInfo ci) { + this.idSet.add(id); + } + + @Override + public IntSet osl$registries$idSet() { + return this.idSet; + } + + @Override + public void osl$registries$clear() { + this.values.clear(); + this.ids.clear(); + this.idSet.clear(); + + this.nextId = 0; + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java new file mode 100644 index 000000000..40d72e4c8 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java @@ -0,0 +1,60 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Map; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; +import net.minecraft.util.registry.IdRegistry; +import net.minecraft.util.registry.MappedRegistry; + +import net.ornithemc.osl.registries.impl.registry.Clearable; +import net.ornithemc.osl.registries.impl.registry.IdRegistryAccess; +import net.ornithemc.osl.registries.impl.registry.WrappedIdRegistry.RegisterCallback; + +@Mixin(IdRegistry.class) +public class IdRegistryMixin extends MappedRegistry implements IdRegistryAccess, Clearable { + + @Shadow @Final + private CrudeIncrementalIntIdentityHashMap ids; + @Shadow @Final + private Map keys; + + @Unique + private RegisterCallback callback; + + @Inject( + method = "register", + at = @At( + value = "RETURN" + ) + ) + private void osl$registries$register(int id, K key, V value, CallbackInfo ci) { + if (this.callback != null) { + this.callback.valueRegistered(id, key, value); + } + } + + @Override + public void osl$registries$setCallback(RegisterCallback callback) { + this.callback = callback; + } + + @Override + public boolean osl$registries$has(Object value) { + return this.keys.containsKey(value); + } + + @Override + public void osl$registries$clear() { + this.entries.clear(); + this.keys.clear(); + Clearable.clear(this.ids); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java new file mode 100644 index 000000000..01174aa6b --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerPlayNetworking; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final + private MinecraftServer server; + + @Inject( + method = "onLogin", + at = @At( + value = "NEW", + target = "net/minecraft/network/packet/s2c/play/LoginS2CPacket" + ) + ) + private void osl$idsync$syncRegistries(CallbackInfo ci, @Local ServerPlayerEntity player) { + if (this.server.isDedicated() || !this.server.getUsername().equals(player.getGameProfile().getName())) { + ServerPlayNetworking.sendNoCheck(player, Constants.OSL_REGISTRY_SYNC_CHANNEL, SyncedRegistriesPacketSerializer::serialize); + } + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/Clearable.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/Clearable.java new file mode 100644 index 000000000..662971ffd --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/Clearable.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.registries.impl.registry; + +public interface Clearable { + + static void clear(Object o) { + if (o instanceof Clearable) { + ((Clearable) o).osl$registries$clear(); + } else { + throw new IllegalArgumentException("not clearable: " + o); + } + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess.java new file mode 100644 index 000000000..7789e2a09 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.registry; + +import it.unimi.dsi.fastutil.ints.IntSet; + +public interface Id2ObjectBiMapAccess { + + default IntSet osl$registries$idSet() { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/IdRegistryAccess.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/IdRegistryAccess.java new file mode 100644 index 000000000..e6535ddcb --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/IdRegistryAccess.java @@ -0,0 +1,18 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.ornithemc.osl.registries.impl.registry.WrappedIdRegistry.RegisterCallback; + +public interface IdRegistryAccess { + + default void osl$registries$setCallback(RegisterCallback callback) { + throw new AbstractMethodError(); + } + + default boolean osl$registries$has(Object value) { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java new file mode 100644 index 000000000..10f5ea4cf --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,20 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.DefaultedIdRegistry; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public final class VanillaRegistries { + + public static Registry registerSimple(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedIdRegistry.of(key, (IdRegistry) registry), () -> { }); + } + + public static DefaultedRegistry registerDefaulted(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedDefaultedIdRegistry.of(key, (DefaultedIdRegistry) registry), () -> { }); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java new file mode 100644 index 000000000..ae769c9c0 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.DefaultedIdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.impl.mixin.common.DefaultedIdRegistryAccess; + +public class WrappedDefaultedIdRegistry extends WrappedIdRegistry implements DefaultedRegistry { + + public static WrappedDefaultedIdRegistry of(ResourceKey> key, DefaultedIdRegistry registry) { + return new WrappedDefaultedIdRegistry<>(key.identifier(), registry); + } + + private WrappedDefaultedIdRegistry(NamespacedIdentifier identifier, DefaultedIdRegistry registry) { + super(identifier, registry); + } + + @Override + public NamespacedIdentifier getDefaultIdentifier() { + return this.serializeKey((Identifier) ((DefaultedIdRegistryAccess) this.registry).accessDefaultKey()); + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java new file mode 100644 index 000000000..f5ba9338f --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java @@ -0,0 +1,142 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.Iterator; +import java.util.Set; +import java.util.stream.Collectors; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.ResourceKeys; + +public class WrappedIdRegistry implements ClearableRegistry { + + public static WrappedIdRegistry of(ResourceKey> key, IdRegistry registry) { + return new WrappedIdRegistry<>(key.identifier(), registry); + } + + final NamespacedIdentifier identifier; + final IdRegistry registry; + + private int nextId; + private boolean frozen; + + WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + NamespacedIdentifier serializeKey(Identifier key) { + return key; + } + + Identifier deserializeKey(NamespacedIdentifier identifier) { + return identifier == null ? null : (identifier instanceof Identifier ? (Identifier) identifier : new Identifier(identifier.namespace(), identifier.identifier())); + } + + ResourceKey resourceKey(NamespacedIdentifier identifier) { + return identifier == null ? null : ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, Object key, Object value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public V register(ResourceKey key, V value) { + return this.register(this.nextId, key, value); + } + + @Override + public V register(int id, ResourceKey key, V value) { + this.registry.register(id, this.deserializeKey(key.identifier()), value); + return value; + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } + + @Override + public T get(int id) { + return this.registry.get(id); + } + + @Override + public T get(ResourceKey key) { + return this.registry.get(this.deserializeKey(key.identifier())); + } + + @Override + public T get(NamespacedIdentifier identifier) { + return this.registry.get(this.deserializeKey(identifier)); + } + + @Override + public boolean has(T value) { + return this.registry.osl$registries$has(value); + } + + @Override + public int getId(T value) { + return this.registry.getId(value); + } + + @Override + public ResourceKey getKey(T value) { + return this.resourceKey(this.serializeKey(this.registry.getKey(value))); + } + + @Override + public NamespacedIdentifier getIdentifier(T value) { + return this.serializeKey(this.registry.getKey(value)); + } + + @Override + public Set> keySet() { + return this.registry.entrySet().stream().map(this::serializeKey).map(this::resourceKey).collect(Collectors.toSet()); + } + + @Override + public Set identifierSet() { + return this.registry.entrySet().stream().map(this::serializeKey).collect(Collectors.toSet()); + } + + @Override + public Iterator iterator() { + return this.registry.iterator(); + } + + @Override + public Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public void clear() { + this.registry.osl$registries$clear(); + + this.nextId = 0; + this.frozen = false; + } + + public interface RegisterCallback { + + void valueRegistered(int id, Object key, Object value); + + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java new file mode 100644 index 000000000..e24782755 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java @@ -0,0 +1,79 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.minecraft.nbt.NbtCompound; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesNbtSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(NbtCompound nbt) throws IOException { + NbtCompound registriesNbt = new NbtCompound(); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt, SyncedRegistriesNbtSerializer::serialize); + registriesNbt.put(identifier.toString(), mappingsNbt); + } + + nbt.putInt(Constants.FORMAT_NBT_KEY, Constants.REGISTRY_MAPPINGS_FORMAT); + nbt.put(Constants.REGISTRIES_NBT_KEY, registriesNbt); + } + + public static void deserialize(NbtCompound nbt, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = nbt.getInt(Constants.FORMAT_NBT_KEY); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + NbtCompound registriesNbt = nbt.getCompound(Constants.REGISTRIES_NBT_KEY); + + for (String key : registriesNbt.getKeys()) { + NbtCompound mappingsNbt = registriesNbt.getCompound(key); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(key); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(mappingsNbt, SyncedRegistriesNbtSerializer::deserialize, source); + mappings.build(source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(NbtCompound nbt, Object2IntMap mappings) throws IOException { + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } + + public static void deserialize(NbtCompound nbt, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + for (String key : nbt.getKeys()) { + mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java new file mode 100644 index 000000000..f1fc0a2e3 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java @@ -0,0 +1,82 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesPacketSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(Constants.REGISTRY_MAPPINGS_FORMAT); + buffer.writeVarInt(REGISTRIES.keySet().size()); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer, SyncedRegistriesPacketSerializer::serialize); + } + } + + public static void deserialize(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(buffer, SyncedRegistriesPacketSerializer::deserialize, source); + mappings.build(source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(PacketBuffer buffer, Object2IntMap mappings) throws IOException { + buffer.writeVarInt(mappings.size()); + + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public static void deserialize(PacketBuffer buffer, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + mappings.put(identifier, id); + } + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/fabric.mod.json b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..712d82669 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/fabric.mod.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc17w47a-mc18w31a", + "environment": "*", + "entrypoints": { + "client-init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ] + }, + "mixins": [ + "osl.registries.mixins.json" + ], + "accessWidener": "osl.registries.classtweaker", + "depends": { + "fabricloader": "\u003e\u003d0.18.0", + "minecraft": "\u003e\u003d1.13-alpha.17.47.a \u003c\u003d1.13.1-alpha.18.31.a", + "osl-core": "\u003e\u003d0.8.0", + "osl-entrypoints": "\u003e\u003d0.5.0", + "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", + "osl-networking": "\u003e\u003d0.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0" + }, + "name": "OSL Registries", + "description": "Registries API and numerical ID synchronization.", + "authors": [ + "OrnitheMC" + ], + "contact": { + "homepage": "https://ornithemc.net/", + "issues": "https://github.com/OrnitheMC/ornithe-standard-libraries/issues", + "sources": "https://github.com/OrnitheMC/ornithe-standard-libraries" + }, + "license": "Apache-2.0" +} \ No newline at end of file diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/osl.registries.classtweaker b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/osl.registries.classtweaker new file mode 100644 index 000000000..2382db14c --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/osl.registries.classtweaker @@ -0,0 +1,4 @@ +classTweaker v1 named + +inject-interface net/minecraft/util/Id2ObjectBiMap net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess +inject-interface net/minecraft/util/registry/IdRegistry net/ornithemc/osl/registries/impl/registry/IdRegistryAccess \ No newline at end of file diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/osl.registries.mixins.json b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/osl.registries.mixins.json new file mode 100644 index 000000000..21c84ee37 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,23 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.BootstrapMixin", + "common.CrudeIncrementalIntIdentityHashMapMixin", + "common.DefaultedIdRegistryAccess", + "common.Id2ObjectBiMapMixin", + "common.IdRegistryMixin", + "common.PlayerManagerMixin" + ], + "client": [ + "client.IntegratedServerMixin" + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/build.gradle b/libraries/registries/registries-mc18w32a-mc1.13.2/build.gradle new file mode 100644 index 000000000..0a350fdb3 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/build.gradle @@ -0,0 +1 @@ +setUpModule(project) diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/gradle.properties b/libraries/registries/registries-mc18w32a-mc1.13.2/gradle.properties new file mode 100644 index 000000000..4c9c26193 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/gradle.properties @@ -0,0 +1,5 @@ +min_mc_version = 18w32a +max_mc_version = 1.13.2 +minecraft_dependency = >=1.13.1-alpha.18.32.a <=1.13.2 + +minecraft_version = 1.13.2 diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java new file mode 100644 index 000000000..68100e620 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java @@ -0,0 +1,22 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; + +public final class RegistryKeys { + + // commonly used registry keys, for use in other APIs + public static final ResourceKey> BLOCK = from("block"); + public static final ResourceKey> ITEM = from("item"); + + public static ResourceKey> from(String identifier) { + return from(NamespacedIdentifiers.from(identifier)); + } + + public static ResourceKey> from(NamespacedIdentifier identifier) { + return ResourceKeys.from(identifier); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java new file mode 100644 index 000000000..17a3c64a5 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java @@ -0,0 +1,53 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import net.minecraft.util.Id2ObjectBiMap; + +public class Id2ObjectBiMapMapper implements IdMapper { + + public static Id2ObjectBiMapMapper of(Id2ObjectBiMap registry) { + return new Id2ObjectBiMapMapper(registry); + } + + private final Id2ObjectBiMap registry; + private final Id2ObjectBiMap backup; + + @SuppressWarnings("unchecked") + private Id2ObjectBiMapMapper(Id2ObjectBiMap registry) { + this.registry = (Id2ObjectBiMap) registry; + this.backup = new Id2ObjectBiMap<>(registry.size()); + } + + /* + * unlike Registry, Id2ObjectBiMap allows duplicate values + * thus iterating over all values will not give you all id-value pairs! + */ + + @Override + public void apply(RegistryMappings mappings) { + this.backup.osl$registries$clear();; + + for (int id : this.registry.osl$registries$idSet()) { + this.backup.put(this.registry.get(id), id); + } + + this.registry.osl$registries$clear();; + + for (int oldId : this.backup.osl$registries$idSet()) { + Object value = this.backup.get(oldId); + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry.put(value, newId); + } + } + } + + @Override + public void undo(RegistryMappings mappings) { + this.registry.osl$registries$clear();; + + for (int id : this.backup.osl$registries$idSet()) { + this.registry.put(this.backup.get(id), id); + } + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java new file mode 100644 index 000000000..f6896b0bd --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,43 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.api.client.ClientPlayNetworking; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +public final class RegistriesEntrypoint implements ClientModInitializer { + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(Constants.OSL_REGISTRY_SYNC_CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesPacketSerializer.deserialize(buffer, RegistryMappingSource.REMOTE_SERVER); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.applyMappings(); + }); + } catch (RegistryMappingException e) { + RegistriesImpl.LOGGER.error("Unable to remap registries!", e); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.resetMappings(); + + if (context.networkHandler().getConnection().isConnected()) { + context.networkHandler().getConnection().disconnect(new LiteralText("Failed to remap registries: " + e.getMessage())); + } + }); + } + }); + ClientConnectionEvents.DISCONNECT.register(context -> { + if (!context.isServerLocal()) { + SyncedRegistriesImpl.undoMappings(); + } + }); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java new file mode 100644 index 000000000..02c3c9582 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java @@ -0,0 +1,24 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.server.integrated.IntegratedServer; + +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(IntegratedServer.class) +public class IntegratedServerMixin { + + @Inject( + method = "shutdown", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$unmapRegistries(CallbackInfo ci) { + SyncedRegistriesImpl.undoMappings(); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java new file mode 100644 index 000000000..93002021e --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,130 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.WorldData; +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesNbtSerializer; + +@Mixin(AlphaWorldStorage.class) +public class AlphaWorldStorageMixin { + + @Shadow @Final + private String name; + + @Shadow + private File getDirectory() { return null; } + + @Inject( + method = "loadData", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfoReturnable cir) { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + + if (!this.readRegistryMappings(file, false)) { + file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + if (!this.readRegistryMappings(file, true)) { + RegistriesImpl.LOGGER.debug("no registry mappings read for '" + this.name + "'"); + } + } + } + + @Unique + private boolean readRegistryMappings(File file, boolean throwOnException) { + if (file.exists()) { + try (InputStream is = new FileInputStream(file)) { + NbtCompound nbt = NbtIo.readCompressed(is); + + SyncedRegistriesNbtSerializer.deserialize(nbt, RegistryMappingSource.WORLD_SAVE); + SyncedRegistriesImpl.applyMappings(); + + return true; + } catch (IOException e) { + if (throwOnException) { + throw new RuntimeException("Unable to read registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("error while reading registry mappings for '" + this.name + "'", e); + } + } catch (RegistryMappingException e) { + if (throwOnException) { + throw new RuntimeException("Invalid registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("invalid registry mappings for '" + this.name + "'", e); + } + } + } + + return false; + } + + @Inject( + method = "saveData(Lnet/minecraft/world/WorldData;Lnet/minecraft/nbt/NbtCompound;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(CallbackInfo ci) { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + File tmp = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_tmp"); + File backup = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + this.writeRegistryMappings(file, tmp, backup); + } + + @Unique + private void writeRegistryMappings(File file, File newFile, File oldFile) { + NbtCompound nbt = new NbtCompound(); + + try { + SyncedRegistriesNbtSerializer.serialize(nbt); + + try (OutputStream os = new FileOutputStream(newFile)) { + NbtIo.writeCompressed(nbt, os); + } + + if (oldFile.exists()) { + oldFile.delete(); + } + + file.renameTo(oldFile); + if (file.exists()) { + file.delete(); + } + + newFile.renameTo(file); + if (newFile.exists()) { + newFile.delete(); + } + } catch (IOException e) { + RegistriesImpl.LOGGER.warn("error while writing registry mappings for '" + this.name + "'", e); + } + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java new file mode 100644 index 000000000..3dcf24cc0 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Arrays; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; + +import net.ornithemc.osl.registries.impl.registry.Clearable; + +@Mixin(CrudeIncrementalIntIdentityHashMap.class) +public class CrudeIncrementalIntIdentityHashMapMixin implements Clearable { + + @Shadow + private Object[] keys; + @Shadow + private Object[] byId; + + @Shadow + private int nextId; + @Shadow + private int size; + + @Override + public void osl$registries$clear() { + Arrays.fill(this.keys, null); + Arrays.fill(this.byId, null); + + this.nextId = 0; + this.size = 0; + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java new file mode 100644 index 000000000..79f753e2f --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java @@ -0,0 +1,15 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.DefaultedIdRegistry; + +@Mixin(DefaultedIdRegistry.class) +public interface DefaultedIdRegistryAccess { + + @Accessor("defaultId") + Identifier accessDefaultId(); + +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java new file mode 100644 index 000000000..03edfe3f7 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java @@ -0,0 +1,59 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.IdentityHashMap; +import java.util.List; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; + +import net.minecraft.util.Id2ObjectBiMap; + +import net.ornithemc.osl.registries.impl.registry.Clearable; +import net.ornithemc.osl.registries.impl.registry.Id2ObjectBiMapAccess; + +@Mixin(Id2ObjectBiMap.class) +public class Id2ObjectBiMapMixin implements Id2ObjectBiMapAccess, Clearable { + + @Shadow @Final + private List values; + @Shadow @Final + private IdentityHashMap ids; + + @Shadow + private int nextId; + + @Unique + private final IntSet idSet = new IntOpenHashSet(); + + @Inject( + method = "put(Ljava/lang/Object;I)V", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$put(T value, int id, CallbackInfo ci) { + this.idSet.add(id); + } + + @Override + public IntSet osl$registries$idSet() { + return this.idSet; + } + + @Override + public void osl$registries$clear() { + this.values.clear(); + this.ids.clear(); + this.idSet.clear(); + + this.nextId = 0; + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java new file mode 100644 index 000000000..7accbaae3 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java @@ -0,0 +1,59 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.google.common.collect.BiMap; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.impl.registry.Clearable; +import net.ornithemc.osl.registries.impl.registry.IdRegistryAccess; +import net.ornithemc.osl.registries.impl.registry.WrappedIdRegistry.RegisterCallback; + +@Mixin(IdRegistry.class) +public class IdRegistryMixin implements IdRegistryAccess, Clearable { + + @Shadow @Final + private CrudeIncrementalIntIdentityHashMap ids; + @Shadow @Final + private BiMap values; + + @Unique + private RegisterCallback callback; + + @Inject( + method = "register", + at = @At( + value = "RETURN" + ) + ) + private void osl$registries$register(int id, Identifier key, T value, CallbackInfo ci) { + if (this.callback != null) { + this.callback.valueRegistered(id, key, value); + } + } + + @Override + public void osl$registries$setCallback(RegisterCallback callback) { + this.callback = callback; + } + + @Override + public boolean osl$registries$has(Object value) { + return this.values.containsValue(value); + } + + @Override + public void osl$registries$clear() { + this.values.clear(); + Clearable.clear(this.ids); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java new file mode 100644 index 000000000..01174aa6b --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerPlayNetworking; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final + private MinecraftServer server; + + @Inject( + method = "onLogin", + at = @At( + value = "NEW", + target = "net/minecraft/network/packet/s2c/play/LoginS2CPacket" + ) + ) + private void osl$idsync$syncRegistries(CallbackInfo ci, @Local ServerPlayerEntity player) { + if (this.server.isDedicated() || !this.server.getUsername().equals(player.getGameProfile().getName())) { + ServerPlayNetworking.sendNoCheck(player, Constants.OSL_REGISTRY_SYNC_CHANNEL, SyncedRegistriesPacketSerializer::serialize); + } + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/RegistryMixin.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/RegistryMixin.java new file mode 100644 index 000000000..3ec07e28b --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/RegistryMixin.java @@ -0,0 +1,26 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.util.registry.Registry; + +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(Registry.class) +public interface RegistryMixin { + + @Inject( + method = "init", + at = @At( + value = "HEAD" + ) + ) + static void osl$registries$initRegistries(CallbackInfo ci) { + RegistriesImpl.init(); + SyncedRegistriesImpl.init(); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/Clearable.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/Clearable.java new file mode 100644 index 000000000..662971ffd --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/Clearable.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.registries.impl.registry; + +public interface Clearable { + + static void clear(Object o) { + if (o instanceof Clearable) { + ((Clearable) o).osl$registries$clear(); + } else { + throw new IllegalArgumentException("not clearable: " + o); + } + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess.java new file mode 100644 index 000000000..7789e2a09 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.registry; + +import it.unimi.dsi.fastutil.ints.IntSet; + +public interface Id2ObjectBiMapAccess { + + default IntSet osl$registries$idSet() { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/IdRegistryAccess.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/IdRegistryAccess.java new file mode 100644 index 000000000..e6535ddcb --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/IdRegistryAccess.java @@ -0,0 +1,18 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.ornithemc.osl.registries.impl.registry.WrappedIdRegistry.RegisterCallback; + +public interface IdRegistryAccess { + + default void osl$registries$setCallback(RegisterCallback callback) { + throw new AbstractMethodError(); + } + + default boolean osl$registries$has(Object value) { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java new file mode 100644 index 000000000..9cdf561fc --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,19 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.DefaultedIdRegistry; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public final class VanillaRegistries { + + public static Registry registerSimple(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedIdRegistry.of(key, (IdRegistry) registry), () -> { }); + } + + public static DefaultedRegistry registerDefaulted(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedDefaultedIdRegistry.of(key, (DefaultedIdRegistry) registry), () -> { }); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java new file mode 100644 index 000000000..d1cf93ce7 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java @@ -0,0 +1,25 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.DefaultedIdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.impl.mixin.common.DefaultedIdRegistryAccess; + +public class WrappedDefaultedIdRegistry extends WrappedIdRegistry implements DefaultedRegistry { + + public static WrappedDefaultedIdRegistry of(ResourceKey> key, DefaultedIdRegistry registry) { + return new WrappedDefaultedIdRegistry<>(key.identifier(), registry); + } + + private WrappedDefaultedIdRegistry(NamespacedIdentifier identifier, DefaultedIdRegistry registry) { + super(identifier, registry); + } + + @Override + public NamespacedIdentifier getDefaultIdentifier() { + return this.serializeKey(((DefaultedIdRegistryAccess) this.registry).accessDefaultId()); + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java new file mode 100644 index 000000000..f8cf9d4ca --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java @@ -0,0 +1,142 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.Iterator; +import java.util.Set; +import java.util.stream.Collectors; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.ResourceKeys; + +public class WrappedIdRegistry implements ClearableRegistry { + + public static WrappedIdRegistry of(ResourceKey> key, IdRegistry registry) { + return new WrappedIdRegistry<>(key.identifier(), registry); + } + + final NamespacedIdentifier identifier; + final IdRegistry registry; + + private int nextId; + private boolean frozen; + + WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + NamespacedIdentifier serializeKey(Identifier key) { + return key; + } + + Identifier deserializeKey(NamespacedIdentifier identifier) { + return identifier == null ? null : (identifier instanceof Identifier ? (Identifier) identifier : new Identifier(identifier.namespace(), identifier.identifier())); + } + + ResourceKey resourceKey(NamespacedIdentifier identifier) { + return identifier == null ? null : ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, Identifier key, Object value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public V register(ResourceKey key, V value) { + return this.register(this.nextId, key, value); + } + + @Override + public V register(int id, ResourceKey key, V value) { + this.registry.register(id, this.deserializeKey(key.identifier()), value); + return value; + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } + + @Override + public T get(int id) { + return this.registry.get(id); + } + + @Override + public T get(ResourceKey key) { + return this.registry.get(this.deserializeKey(key.identifier())); + } + + @Override + public T get(NamespacedIdentifier identifier) { + return this.registry.get(this.deserializeKey(identifier)); + } + + @Override + public boolean has(T value) { + return this.registry.osl$registries$has(value); + } + + @Override + public int getId(T value) { + return this.registry.getId(value); + } + + @Override + public ResourceKey getKey(T value) { + return this.resourceKey(this.serializeKey(this.registry.getKey(value))); + } + + @Override + public NamespacedIdentifier getIdentifier(T value) { + return this.serializeKey(this.registry.getKey(value)); + } + + @Override + public Set> keySet() { + return this.registry.keySet().stream().map(this::serializeKey).map(this::resourceKey).collect(Collectors.toSet()); + } + + @Override + public Set identifierSet() { + return this.registry.keySet().stream().map(this::serializeKey).collect(Collectors.toSet()); + } + + @Override + public Iterator iterator() { + return this.registry.iterator(); + } + + @Override + public Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public void clear() { + this.registry.osl$registries$clear(); + + this.nextId = 0; + this.frozen = false; + } + + public interface RegisterCallback { + + void valueRegistered(int id, Identifier key, Object value); + + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java new file mode 100644 index 000000000..e24782755 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java @@ -0,0 +1,79 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.minecraft.nbt.NbtCompound; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesNbtSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(NbtCompound nbt) throws IOException { + NbtCompound registriesNbt = new NbtCompound(); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt, SyncedRegistriesNbtSerializer::serialize); + registriesNbt.put(identifier.toString(), mappingsNbt); + } + + nbt.putInt(Constants.FORMAT_NBT_KEY, Constants.REGISTRY_MAPPINGS_FORMAT); + nbt.put(Constants.REGISTRIES_NBT_KEY, registriesNbt); + } + + public static void deserialize(NbtCompound nbt, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = nbt.getInt(Constants.FORMAT_NBT_KEY); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + NbtCompound registriesNbt = nbt.getCompound(Constants.REGISTRIES_NBT_KEY); + + for (String key : registriesNbt.getKeys()) { + NbtCompound mappingsNbt = registriesNbt.getCompound(key); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(key); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(mappingsNbt, SyncedRegistriesNbtSerializer::deserialize, source); + mappings.build(source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(NbtCompound nbt, Object2IntMap mappings) throws IOException { + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } + + public static void deserialize(NbtCompound nbt, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + for (String key : nbt.getKeys()) { + mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java new file mode 100644 index 000000000..f1fc0a2e3 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java @@ -0,0 +1,82 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesPacketSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(Constants.REGISTRY_MAPPINGS_FORMAT); + buffer.writeVarInt(REGISTRIES.keySet().size()); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer, SyncedRegistriesPacketSerializer::serialize); + } + } + + public static void deserialize(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(buffer, SyncedRegistriesPacketSerializer::deserialize, source); + mappings.build(source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(PacketBuffer buffer, Object2IntMap mappings) throws IOException { + buffer.writeVarInt(mappings.size()); + + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public static void deserialize(PacketBuffer buffer, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + mappings.put(identifier, id); + } + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..772a1eca8 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc18w32a-mc1.13.2", + "environment": "*", + "entrypoints": { + "client-init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ] + }, + "mixins": [ + "osl.registries.mixins.json" + ], + "accessWidener": "osl.registries.classtweaker", + "depends": { + "fabricloader": "\u003e\u003d0.18.0", + "minecraft": "\u003e\u003d1.13.1-alpha.18.32.a \u003c\u003d1.13.2", + "osl-core": "\u003e\u003d0.8.0", + "osl-entrypoints": "\u003e\u003d0.5.0", + "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", + "osl-networking": "\u003e\u003d0.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0" + }, + "name": "OSL Registries", + "description": "Registries API and numerical ID synchronization.", + "authors": [ + "OrnitheMC" + ], + "contact": { + "homepage": "https://ornithemc.net/", + "issues": "https://github.com/OrnitheMC/ornithe-standard-libraries/issues", + "sources": "https://github.com/OrnitheMC/ornithe-standard-libraries" + }, + "license": "Apache-2.0" +} \ No newline at end of file diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/osl.registries.classtweaker b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/osl.registries.classtweaker new file mode 100644 index 000000000..88c69c01d --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/osl.registries.classtweaker @@ -0,0 +1,4 @@ +classTweaker v1 named + +inject-interface net/minecraft/util/Id2ObjectBiMap net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess +inject-interface net/minecraft/util/registry/IdRegistry net/ornithemc/osl/registries/impl/registry/IdRegistryAccess diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/osl.registries.mixins.json b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/osl.registries.mixins.json new file mode 100644 index 000000000..7e3a3ca5e --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,23 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.CrudeIncrementalIntIdentityHashMapMixin", + "common.DefaultedIdRegistryAccess", + "common.Id2ObjectBiMapMixin", + "common.IdRegistryMixin", + "common.PlayerManagerMixin", + "common.RegistryMixin" + ], + "client": [ + "client.IntegratedServerMixin" + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/build.gradle b/libraries/registries/registries-mc18w43a-mc1.14.4/build.gradle new file mode 100644 index 000000000..0a350fdb3 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/build.gradle @@ -0,0 +1 @@ +setUpModule(project) diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/gradle.properties b/libraries/registries/registries-mc18w43a-mc1.14.4/gradle.properties new file mode 100644 index 000000000..071d210ec --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/gradle.properties @@ -0,0 +1,5 @@ +min_mc_version = 18w43a +max_mc_version = 1.14.4 +minecraft_dependency = >=1.14-alpha.18.43.a <=1.14.4 + +minecraft_version = 1.14.4 diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java new file mode 100644 index 000000000..68100e620 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java @@ -0,0 +1,22 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; + +public final class RegistryKeys { + + // commonly used registry keys, for use in other APIs + public static final ResourceKey> BLOCK = from("block"); + public static final ResourceKey> ITEM = from("item"); + + public static ResourceKey> from(String identifier) { + return from(NamespacedIdentifiers.from(identifier)); + } + + public static ResourceKey> from(NamespacedIdentifier identifier) { + return ResourceKeys.from(identifier); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java new file mode 100644 index 000000000..17a3c64a5 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Id2ObjectBiMapMapper.java @@ -0,0 +1,53 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import net.minecraft.util.Id2ObjectBiMap; + +public class Id2ObjectBiMapMapper implements IdMapper { + + public static Id2ObjectBiMapMapper of(Id2ObjectBiMap registry) { + return new Id2ObjectBiMapMapper(registry); + } + + private final Id2ObjectBiMap registry; + private final Id2ObjectBiMap backup; + + @SuppressWarnings("unchecked") + private Id2ObjectBiMapMapper(Id2ObjectBiMap registry) { + this.registry = (Id2ObjectBiMap) registry; + this.backup = new Id2ObjectBiMap<>(registry.size()); + } + + /* + * unlike Registry, Id2ObjectBiMap allows duplicate values + * thus iterating over all values will not give you all id-value pairs! + */ + + @Override + public void apply(RegistryMappings mappings) { + this.backup.osl$registries$clear();; + + for (int id : this.registry.osl$registries$idSet()) { + this.backup.put(this.registry.get(id), id); + } + + this.registry.osl$registries$clear();; + + for (int oldId : this.backup.osl$registries$idSet()) { + Object value = this.backup.get(oldId); + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry.put(value, newId); + } + } + } + + @Override + public void undo(RegistryMappings mappings) { + this.registry.osl$registries$clear();; + + for (int id : this.backup.osl$registries$idSet()) { + this.registry.put(this.backup.get(id), id); + } + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java new file mode 100644 index 000000000..f6896b0bd --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,43 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.api.client.ClientPlayNetworking; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +public final class RegistriesEntrypoint implements ClientModInitializer { + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(Constants.OSL_REGISTRY_SYNC_CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesPacketSerializer.deserialize(buffer, RegistryMappingSource.REMOTE_SERVER); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.applyMappings(); + }); + } catch (RegistryMappingException e) { + RegistriesImpl.LOGGER.error("Unable to remap registries!", e); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.resetMappings(); + + if (context.networkHandler().getConnection().isConnected()) { + context.networkHandler().getConnection().disconnect(new LiteralText("Failed to remap registries: " + e.getMessage())); + } + }); + } + }); + ClientConnectionEvents.DISCONNECT.register(context -> { + if (!context.isServerLocal()) { + SyncedRegistriesImpl.undoMappings(); + } + }); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java new file mode 100644 index 000000000..02c3c9582 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java @@ -0,0 +1,24 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.server.integrated.IntegratedServer; + +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(IntegratedServer.class) +public class IntegratedServerMixin { + + @Inject( + method = "shutdown", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$unmapRegistries(CallbackInfo ci) { + SyncedRegistriesImpl.undoMappings(); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java new file mode 100644 index 000000000..bfabeb1a1 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,130 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.WorldData; +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesNbtSerializer; + +@Mixin(AlphaWorldStorage.class) +public class AlphaWorldStorageMixin { + + @Shadow @Final + private String name; + + @Shadow + private File m_52081685() { return null; } + + @Inject( + method = "m_16306786", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfoReturnable cir) { + File dir = this.m_52081685(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + + if (!this.readRegistryMappings(file, false)) { + file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + if (!this.readRegistryMappings(file, true)) { + RegistriesImpl.LOGGER.debug("no registry mappings read for '" + this.name + "'"); + } + } + } + + @Unique + private boolean readRegistryMappings(File file, boolean throwOnException) { + if (file.exists()) { + try (InputStream is = new FileInputStream(file)) { + NbtCompound nbt = NbtIo.readCompressed(is); + + SyncedRegistriesNbtSerializer.deserialize(nbt, RegistryMappingSource.WORLD_SAVE); + SyncedRegistriesImpl.applyMappings(); + + return true; + } catch (IOException e) { + if (throwOnException) { + throw new RuntimeException("Unable to read registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("error while reading registry mappings for '" + this.name + "'", e); + } + } catch (RegistryMappingException e) { + if (throwOnException) { + throw new RuntimeException("Invalid registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("invalid registry mappings for '" + this.name + "'", e); + } + } + } + + return false; + } + + @Inject( + method = "m_92317641(Lnet/minecraft/world/WorldData;Lnet/minecraft/nbt/NbtCompound;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(CallbackInfo ci) { + File dir = this.m_52081685(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + File tmp = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_tmp"); + File backup = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + this.writeRegistryMappings(file, tmp, backup); + } + + @Unique + private void writeRegistryMappings(File file, File newFile, File oldFile) { + NbtCompound nbt = new NbtCompound(); + + try { + SyncedRegistriesNbtSerializer.serialize(nbt); + + try (OutputStream os = new FileOutputStream(newFile)) { + NbtIo.writeCompressed(nbt, os); + } + + if (oldFile.exists()) { + oldFile.delete(); + } + + file.renameTo(oldFile); + if (file.exists()) { + file.delete(); + } + + newFile.renameTo(file); + if (newFile.exists()) { + newFile.delete(); + } + } catch (IOException e) { + RegistriesImpl.LOGGER.warn("error while writing registry mappings for '" + this.name + "'", e); + } + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java new file mode 100644 index 000000000..7b6b88a17 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/BootstrapMixin.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.objectweb.asm.Opcodes; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.Bootstrap; +import net.minecraft.util.registry.Registry; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(Bootstrap.class) +public class BootstrapMixin { + + @Inject( + method = "init", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/util/registry/Registry;REGISTRY:Lnet/minecraft/unmapped/C_06803903;", + opcode = Opcodes.GETSTATIC + ) + ) + private static void osl$registries$initRegistries(CallbackInfo ci) { + // force registry loading (the targeted field access does the same) + Registry.REGISTRY.getClass(); + + RegistriesImpl.init(); + SyncedRegistriesImpl.init(); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java new file mode 100644 index 000000000..3dcf24cc0 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.java @@ -0,0 +1,33 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Arrays; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; + +import net.ornithemc.osl.registries.impl.registry.Clearable; + +@Mixin(CrudeIncrementalIntIdentityHashMap.class) +public class CrudeIncrementalIntIdentityHashMapMixin implements Clearable { + + @Shadow + private Object[] keys; + @Shadow + private Object[] byId; + + @Shadow + private int nextId; + @Shadow + private int size; + + @Override + public void osl$registries$clear() { + Arrays.fill(this.keys, null); + Arrays.fill(this.byId, null); + + this.nextId = 0; + this.size = 0; + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java new file mode 100644 index 000000000..79f753e2f --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/DefaultedIdRegistryAccess.java @@ -0,0 +1,15 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.DefaultedIdRegistry; + +@Mixin(DefaultedIdRegistry.class) +public interface DefaultedIdRegistryAccess { + + @Accessor("defaultId") + Identifier accessDefaultId(); + +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java new file mode 100644 index 000000000..03edfe3f7 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java @@ -0,0 +1,59 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.IdentityHashMap; +import java.util.List; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; + +import net.minecraft.util.Id2ObjectBiMap; + +import net.ornithemc.osl.registries.impl.registry.Clearable; +import net.ornithemc.osl.registries.impl.registry.Id2ObjectBiMapAccess; + +@Mixin(Id2ObjectBiMap.class) +public class Id2ObjectBiMapMixin implements Id2ObjectBiMapAccess, Clearable { + + @Shadow @Final + private List values; + @Shadow @Final + private IdentityHashMap ids; + + @Shadow + private int nextId; + + @Unique + private final IntSet idSet = new IntOpenHashSet(); + + @Inject( + method = "put(Ljava/lang/Object;I)V", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$put(T value, int id, CallbackInfo ci) { + this.idSet.add(id); + } + + @Override + public IntSet osl$registries$idSet() { + return this.idSet; + } + + @Override + public void osl$registries$clear() { + this.values.clear(); + this.ids.clear(); + this.idSet.clear(); + + this.nextId = 0; + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java new file mode 100644 index 000000000..46c6e516f --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/IdRegistryMixin.java @@ -0,0 +1,59 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import com.google.common.collect.BiMap; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.CrudeIncrementalIntIdentityHashMap; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.impl.registry.Clearable; +import net.ornithemc.osl.registries.impl.registry.IdRegistryAccess; +import net.ornithemc.osl.registries.impl.registry.WrappedIdRegistry.RegisterCallback; + +@Mixin(IdRegistry.class) +public class IdRegistryMixin implements IdRegistryAccess, Clearable { + + @Shadow @Final + private CrudeIncrementalIntIdentityHashMap ids; + @Shadow @Final + private BiMap values; + + @Unique + private RegisterCallback callback; + + @Inject( + method = "m_26252208", + at = @At( + value = "RETURN" + ) + ) + private void osl$registries$register(int id, Identifier key, T value, CallbackInfoReturnable cir) { + if (this.callback != null) { + this.callback.valueRegistered(id, key, value); + } + } + + @Override + public void osl$registries$setCallback(RegisterCallback callback) { + this.callback = callback; + } + + @Override + public boolean osl$registries$has(Object value) { + return this.values.containsValue(value); + } + + @Override + public void osl$registries$clear() { + this.values.clear(); + Clearable.clear(this.ids); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java new file mode 100644 index 000000000..01174aa6b --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.living.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerPlayNetworking; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final + private MinecraftServer server; + + @Inject( + method = "onLogin", + at = @At( + value = "NEW", + target = "net/minecraft/network/packet/s2c/play/LoginS2CPacket" + ) + ) + private void osl$idsync$syncRegistries(CallbackInfo ci, @Local ServerPlayerEntity player) { + if (this.server.isDedicated() || !this.server.getUsername().equals(player.getGameProfile().getName())) { + ServerPlayNetworking.sendNoCheck(player, Constants.OSL_REGISTRY_SYNC_CHANNEL, SyncedRegistriesPacketSerializer::serialize); + } + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/Clearable.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/Clearable.java new file mode 100644 index 000000000..662971ffd --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/Clearable.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.registries.impl.registry; + +public interface Clearable { + + static void clear(Object o) { + if (o instanceof Clearable) { + ((Clearable) o).osl$registries$clear(); + } else { + throw new IllegalArgumentException("not clearable: " + o); + } + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess.java new file mode 100644 index 000000000..7789e2a09 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.registry; + +import it.unimi.dsi.fastutil.ints.IntSet; + +public interface Id2ObjectBiMapAccess { + + default IntSet osl$registries$idSet() { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/IdRegistryAccess.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/IdRegistryAccess.java new file mode 100644 index 000000000..e6535ddcb --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/IdRegistryAccess.java @@ -0,0 +1,18 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.ornithemc.osl.registries.impl.registry.WrappedIdRegistry.RegisterCallback; + +public interface IdRegistryAccess { + + default void osl$registries$setCallback(RegisterCallback callback) { + throw new AbstractMethodError(); + } + + default boolean osl$registries$has(Object value) { + throw new AbstractMethodError(); + } + + default void osl$registries$clear() { + throw new AbstractMethodError(); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java new file mode 100644 index 000000000..9cdf561fc --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,19 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.DefaultedIdRegistry; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public final class VanillaRegistries { + + public static Registry registerSimple(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedIdRegistry.of(key, (IdRegistry) registry), () -> { }); + } + + public static DefaultedRegistry registerDefaulted(ResourceKey> key, net.minecraft.util.registry.Registry registry) { + return RegistriesImpl.register(key, WrappedDefaultedIdRegistry.of(key, (DefaultedIdRegistry) registry), () -> { }); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java new file mode 100644 index 000000000..d1cf93ce7 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedDefaultedIdRegistry.java @@ -0,0 +1,25 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.DefaultedIdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.impl.mixin.common.DefaultedIdRegistryAccess; + +public class WrappedDefaultedIdRegistry extends WrappedIdRegistry implements DefaultedRegistry { + + public static WrappedDefaultedIdRegistry of(ResourceKey> key, DefaultedIdRegistry registry) { + return new WrappedDefaultedIdRegistry<>(key.identifier(), registry); + } + + private WrappedDefaultedIdRegistry(NamespacedIdentifier identifier, DefaultedIdRegistry registry) { + super(identifier, registry); + } + + @Override + public NamespacedIdentifier getDefaultIdentifier() { + return this.serializeKey(((DefaultedIdRegistryAccess) this.registry).accessDefaultId()); + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java new file mode 100644 index 000000000..67192d999 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java @@ -0,0 +1,144 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.Iterator; +import java.util.Set; +import java.util.stream.Collectors; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.IdRegistry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.ResourceKeys; + +public class WrappedIdRegistry implements ClearableRegistry { + + public static WrappedIdRegistry of(ResourceKey> key, IdRegistry registry) { + return new WrappedIdRegistry<>(key.identifier(), registry); + } + + final NamespacedIdentifier identifier; + final IdRegistry registry; + + private int nextId; + private boolean frozen; + + WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + NamespacedIdentifier serializeKey(Identifier key) { + return key; + } + + Identifier deserializeKey(NamespacedIdentifier identifier) { + return identifier == null ? null : (identifier instanceof Identifier ? (Identifier) identifier : new Identifier(identifier.namespace(), identifier.identifier())); + } + + ResourceKey resourceKey(NamespacedIdentifier identifier) { + return identifier == null ? null : ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, Identifier key, Object value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public V register(ResourceKey key, V value) { + return this.register(this.nextId, key, value); + } + + @Override + public V register(int id, ResourceKey key, V value) { + this.registry.m_26252208(id, this.deserializeKey(key.identifier()), value); + return value; + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } + + @Override + public T get(int id) { + return this.registry.get(id); + } + + @Override + public T get(ResourceKey key) { + Identifier k = this.deserializeKey(key.identifier()); + return this.registry.containsKey(k) ? this.registry.getOrDefault(k) : null; + } + + @Override + public T get(NamespacedIdentifier identifier) { + Identifier k = this.deserializeKey(identifier); + return this.registry.containsKey(k) ? this.registry.getOrDefault(k) : null; + } + + @Override + public boolean has(T value) { + return this.registry.osl$registries$has(value); + } + + @Override + public int getId(T value) { + return this.registry.getId(value); + } + + @Override + public ResourceKey getKey(T value) { + return this.resourceKey(this.serializeKey(this.registry.getKey(value))); + } + + @Override + public NamespacedIdentifier getIdentifier(T value) { + return this.serializeKey(this.registry.getKey(value)); + } + + @Override + public Set> keySet() { + return this.registry.keySet().stream().map(this::serializeKey).map(this::resourceKey).collect(Collectors.toSet()); + } + + @Override + public Set identifierSet() { + return this.registry.keySet().stream().map(this::serializeKey).collect(Collectors.toSet()); + } + + @Override + public Iterator iterator() { + return this.registry.iterator(); + } + + @Override + public Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public void clear() { + this.registry.osl$registries$clear(); + + this.nextId = 0; + this.frozen = false; + } + + public interface RegisterCallback { + + void valueRegistered(int id, Identifier key, Object value); + + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java new file mode 100644 index 000000000..e24782755 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java @@ -0,0 +1,79 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.minecraft.nbt.NbtCompound; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesNbtSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(NbtCompound nbt) throws IOException { + NbtCompound registriesNbt = new NbtCompound(); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt, SyncedRegistriesNbtSerializer::serialize); + registriesNbt.put(identifier.toString(), mappingsNbt); + } + + nbt.putInt(Constants.FORMAT_NBT_KEY, Constants.REGISTRY_MAPPINGS_FORMAT); + nbt.put(Constants.REGISTRIES_NBT_KEY, registriesNbt); + } + + public static void deserialize(NbtCompound nbt, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = nbt.getInt(Constants.FORMAT_NBT_KEY); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + NbtCompound registriesNbt = nbt.getCompound(Constants.REGISTRIES_NBT_KEY); + + for (String key : registriesNbt.getKeys()) { + NbtCompound mappingsNbt = registriesNbt.getCompound(key); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(key); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(mappingsNbt, SyncedRegistriesNbtSerializer::deserialize, source); + mappings.build(source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(NbtCompound nbt, Object2IntMap mappings) throws IOException { + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } + + public static void deserialize(NbtCompound nbt, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + for (String key : nbt.getKeys()) { + mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java new file mode 100644 index 000000000..f1fc0a2e3 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java @@ -0,0 +1,82 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesPacketSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(Constants.REGISTRY_MAPPINGS_FORMAT); + buffer.writeVarInt(REGISTRIES.keySet().size()); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer, SyncedRegistriesPacketSerializer::serialize); + } + } + + public static void deserialize(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(buffer, SyncedRegistriesPacketSerializer::deserialize, source); + mappings.build(source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(PacketBuffer buffer, Object2IntMap mappings) throws IOException { + buffer.writeVarInt(mappings.size()); + + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public static void deserialize(PacketBuffer buffer, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + mappings.put(identifier, id); + } + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..fc44131f8 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc18w43a-mc1.14.4", + "environment": "*", + "entrypoints": { + "client-init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ] + }, + "mixins": [ + "osl.registries.mixins.json" + ], + "accessWidener": "osl.registries.classtweaker", + "depends": { + "fabricloader": "\u003e\u003d0.18.0", + "minecraft": "\u003e\u003d1.14-alpha.18.43.a \u003c\u003d1.14.4", + "osl-core": "\u003e\u003d0.8.0", + "osl-entrypoints": "\u003e\u003d0.5.0", + "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", + "osl-networking": "\u003e\u003d0.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0" + }, + "name": "OSL Registries", + "description": "Registries API and numerical ID synchronization.", + "authors": [ + "OrnitheMC" + ], + "contact": { + "homepage": "https://ornithemc.net/", + "issues": "https://github.com/OrnitheMC/ornithe-standard-libraries/issues", + "sources": "https://github.com/OrnitheMC/ornithe-standard-libraries" + }, + "license": "Apache-2.0" +} \ No newline at end of file diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/resources/osl.registries.classtweaker b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/resources/osl.registries.classtweaker new file mode 100644 index 000000000..88c69c01d --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/resources/osl.registries.classtweaker @@ -0,0 +1,4 @@ +classTweaker v1 named + +inject-interface net/minecraft/util/Id2ObjectBiMap net/ornithemc/osl/registries/impl/registry/Id2ObjectBiMapAccess +inject-interface net/minecraft/util/registry/IdRegistry net/ornithemc/osl/registries/impl/registry/IdRegistryAccess diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/resources/osl.registries.mixins.json b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/resources/osl.registries.mixins.json new file mode 100644 index 000000000..21c84ee37 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,23 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.BootstrapMixin", + "common.CrudeIncrementalIntIdentityHashMapMixin", + "common.DefaultedIdRegistryAccess", + "common.Id2ObjectBiMapMixin", + "common.IdRegistryMixin", + "common.PlayerManagerMixin" + ], + "client": [ + "client.IntegratedServerMixin" + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/build.gradle b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/build.gradle new file mode 100644 index 000000000..0a350fdb3 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/build.gradle @@ -0,0 +1 @@ +setUpModule(project) diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/gradle.properties b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/gradle.properties new file mode 100644 index 000000000..a78fb883e --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/gradle.properties @@ -0,0 +1,7 @@ +min_mc_version = a1.0.1_01 +max_mc_version = 1.6.4 +minecraft_dependency = >=1.0.0-alpha.0.1 <=1.6.4 + +minecraft_version = 1.5.2 +raven_build = 3 +nests_build = 6 diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java new file mode 100644 index 000000000..68100e620 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/api/registry/RegistryKeys.java @@ -0,0 +1,22 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; + +public final class RegistryKeys { + + // commonly used registry keys, for use in other APIs + public static final ResourceKey> BLOCK = from("block"); + public static final ResourceKey> ITEM = from("item"); + + public static ResourceKey> from(String identifier) { + return from(NamespacedIdentifiers.from(identifier)); + } + + public static ResourceKey> from(NamespacedIdentifier identifier) { + return ResourceKeys.from(identifier); + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/Bootstrap.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/Bootstrap.java new file mode 100644 index 000000000..c27f86c9c --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/Bootstrap.java @@ -0,0 +1,18 @@ +package net.ornithemc.osl.registries.impl; + +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +public final class Bootstrap { + + private static boolean initialized; + + public static void init() { + if (!initialized) { + initialized = true; + + RegistriesImpl.init(); + SyncedRegistriesImpl.init(); + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java new file mode 100644 index 000000000..25a4ea674 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,42 @@ +package net.ornithemc.osl.registries.impl; + +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.networking.api.client.ClientConnectionEvents; +import net.ornithemc.osl.networking.api.client.ClientPlayNetworking; +import net.ornithemc.osl.registries.impl.mixin.client.ClientNetworkHandlerAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +public final class RegistriesEntrypoint implements ClientModInitializer { + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(Constants.OSL_REGISTRY_SYNC_CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesPacketSerializer.deserialize(buffer, RegistryMappingSource.REMOTE_SERVER); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.applyMappings(); + }); + } catch (RegistryMappingException e) { + RegistriesImpl.LOGGER.error("Unable to remap registries!", e); + + context.minecraft().execute(() -> { + SyncedRegistriesImpl.resetMappings(); + + if (!((ClientNetworkHandlerAccess) context.networkHandler()).accessDisconnected()) { + context.networkHandler().getConnection().disconnect("Failed to remap registries: " + e.getMessage()); + } + }); + } + }); + ClientConnectionEvents.DISCONNECT.register(context -> { + if (!context.isServerLocal()) { + SyncedRegistriesImpl.undoMappings(); + } + }); + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java new file mode 100644 index 000000000..22ea52172 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesMixinPlugin.java @@ -0,0 +1,49 @@ +package net.ornithemc.osl.registries.impl; + +import java.util.List; +import java.util.Set; + +import org.objectweb.asm.tree.ClassNode; + +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import net.ornithemc.osl.core.impl.util.MinecraftVersion; + +public class RegistriesMixinPlugin implements IMixinConfigPlugin { + + @Override + public void onLoad(String mixinPackage) { + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if ("net.ornithemc.osl.registries.impl.mixin.client.IntegratedServerMixin".equals(mixinClassName)) { + return MinecraftVersion.resolve().compareTo("12w25a") >= 0; + } + + return true; + } + + @Override + public void acceptTargets(Set myTargets, Set otherTargets) { + } + + @Override + public List getMixins() { + return null; + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/ClientNetworkHandlerAccess.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/ClientNetworkHandlerAccess.java new file mode 100644 index 000000000..ffe477a57 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/ClientNetworkHandlerAccess.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.client.network.handler.ClientNetworkHandler; + +@Mixin(ClientNetworkHandler.class) +public interface ClientNetworkHandlerAccess { + + @Accessor("disconnected") + boolean accessDisconnected(); + +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java new file mode 100644 index 000000000..02c3c9582 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/IntegratedServerMixin.java @@ -0,0 +1,24 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.server.integrated.IntegratedServer; + +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +@Mixin(IntegratedServer.class) +public class IntegratedServerMixin { + + @Inject( + method = "shutdown", + at = @At( + value = "TAIL" + ) + ) + private void osl$registries$unmapRegistries(CallbackInfo ci) { + SyncedRegistriesImpl.undoMappings(); + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/MinecraftMixin.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/MinecraftMixin.java new file mode 100644 index 000000000..107f853f6 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/client/MinecraftMixin.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.registries.impl.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; + +import net.ornithemc.osl.registries.impl.Bootstrap; + +@Mixin(Minecraft.class) +public class MinecraftMixin { + + @Inject( + method = "", + at = @At( + value = "INVOKE", + target = "Ljava/lang/Object;()V", + shift = Shift.AFTER + ) + ) + private void osl$registries$bootstrap(CallbackInfo ci) { + Bootstrap.init(); + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java new file mode 100644 index 000000000..93002021e --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,130 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.WorldData; +import net.minecraft.world.storage.AlphaWorldStorage; + +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingException; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMappingSource; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesNbtSerializer; + +@Mixin(AlphaWorldStorage.class) +public class AlphaWorldStorageMixin { + + @Shadow @Final + private String name; + + @Shadow + private File getDirectory() { return null; } + + @Inject( + method = "loadData", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$loadRegistryMappings(CallbackInfoReturnable cir) { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + + if (!this.readRegistryMappings(file, false)) { + file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + if (!this.readRegistryMappings(file, true)) { + RegistriesImpl.LOGGER.debug("no registry mappings read for '" + this.name + "'"); + } + } + } + + @Unique + private boolean readRegistryMappings(File file, boolean throwOnException) { + if (file.exists()) { + try (InputStream is = new FileInputStream(file)) { + NbtCompound nbt = NbtIo.readCompressed(is); + + SyncedRegistriesNbtSerializer.deserialize(nbt, RegistryMappingSource.WORLD_SAVE); + SyncedRegistriesImpl.applyMappings(); + + return true; + } catch (IOException e) { + if (throwOnException) { + throw new RuntimeException("Unable to read registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("error while reading registry mappings for '" + this.name + "'", e); + } + } catch (RegistryMappingException e) { + if (throwOnException) { + throw new RuntimeException("Invalid registry mappings for '" + this.name + "'", e); + } else { + RegistriesImpl.LOGGER.warn("invalid registry mappings for '" + this.name + "'", e); + } + } + } + + return false; + } + + @Inject( + method = "saveData(Lnet/minecraft/world/WorldData;Lnet/minecraft/nbt/NbtCompound;)V", + at = @At( + value = "HEAD" + ) + ) + private void osl$registries$saveRegistryMappings(CallbackInfo ci) { + File dir = this.getDirectory(); + File file = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME); + File tmp = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_tmp"); + File backup = new File(dir, Constants.REGISTRY_MAPPINGS_FILE_NAME + "_old"); + + this.writeRegistryMappings(file, tmp, backup); + } + + @Unique + private void writeRegistryMappings(File file, File newFile, File oldFile) { + NbtCompound nbt = new NbtCompound(); + + try { + SyncedRegistriesNbtSerializer.serialize(nbt); + + try (OutputStream os = new FileOutputStream(newFile)) { + NbtIo.writeCompressed(nbt, os); + } + + if (oldFile.exists()) { + oldFile.delete(); + } + + file.renameTo(oldFile); + if (file.exists()) { + file.delete(); + } + + newFile.renameTo(file); + if (newFile.exists()) { + newFile.delete(); + } + } catch (IOException e) { + RegistriesImpl.LOGGER.warn("error while writing registry mappings for '" + this.name + "'", e); + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/NbtCompoundAccess.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/NbtCompoundAccess.java new file mode 100644 index 000000000..91ac96618 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/NbtCompoundAccess.java @@ -0,0 +1,17 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import java.util.Map; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; + +@Mixin(NbtCompound.class) +public interface NbtCompoundAccess { + + @Accessor("elements") + Map accessElements(); + +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java new file mode 100644 index 000000000..f9fb53d5d --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,38 @@ +package net.ornithemc.osl.registries.impl.mixin.common; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.sugar.Local; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.entity.mob.player.ServerPlayerEntity; + +import net.ornithemc.osl.networking.api.server.ServerPlayNetworking; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.SyncedRegistriesPacketSerializer; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + + @Shadow @Final + private MinecraftServer server; + + @Inject( + method = "onLogin", + at = @At( + value = "NEW", + target = "net/minecraft/network/packet/LoginPacket" + ) + ) + private void osl$idsync$syncRegistries(CallbackInfo ci, @Local ServerPlayerEntity player) { + if (this.server.isDedicated() || !this.server.getUsername().equals(player.getName())) { + ServerPlayNetworking.sendNoCheck(player, Constants.OSL_REGISTRY_SYNC_CHANNEL, SyncedRegistriesPacketSerializer::serialize); + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/MinecraftServerMixin.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/MinecraftServerMixin.java new file mode 100644 index 000000000..90ec0f0b1 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/server/MinecraftServerMixin.java @@ -0,0 +1,27 @@ +package net.ornithemc.osl.registries.impl.mixin.server; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.server.MinecraftServer; + +import net.ornithemc.osl.registries.impl.Bootstrap; + +@Mixin( + value = MinecraftServer.class, + priority = 1 // make sure entrypoints mixin is applied first +) +public class MinecraftServerMixin { + + @Inject( + method = "main", + at = @At( + value = "HEAD" + ) + ) + private static void osl$registries$bootstrap(CallbackInfo ci) { + Bootstrap.init(); + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java new file mode 100644 index 000000000..80e0a0ce6 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesNbtSerializer.java @@ -0,0 +1,80 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.minecraft.nbt.NbtCompound; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.mixin.common.NbtCompoundAccess; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesNbtSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(NbtCompound nbt) throws IOException { + NbtCompound registriesNbt = new NbtCompound(); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt, SyncedRegistriesNbtSerializer::serialize); + registriesNbt.put(identifier.toString(), mappingsNbt); + } + + nbt.putInt(Constants.FORMAT_NBT_KEY, Constants.REGISTRY_MAPPINGS_FORMAT); + nbt.put(Constants.REGISTRIES_NBT_KEY, registriesNbt); + } + + public static void deserialize(NbtCompound nbt, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = nbt.getInt(Constants.FORMAT_NBT_KEY); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + NbtCompound registriesNbt = nbt.getCompound(Constants.REGISTRIES_NBT_KEY); + + for (String key : ((NbtCompoundAccess) registriesNbt).accessElements().keySet()) { + NbtCompound mappingsNbt = registriesNbt.getCompound(key); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(key); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(mappingsNbt, SyncedRegistriesNbtSerializer::deserialize, source); + mappings.build(source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(NbtCompound nbt, Object2IntMap mappings) throws IOException { + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } + + public static void deserialize(NbtCompound nbt, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + for (String key : ((NbtCompoundAccess) nbt).accessElements().keySet()) { + mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java new file mode 100644 index 000000000..f1fc0a2e3 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SyncedRegistriesPacketSerializer.java @@ -0,0 +1,82 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistry; + +public final class SyncedRegistriesPacketSerializer { + + private static final Registry REGISTRIES = SyncedRegistriesImpl.SYNCED_REGISTRIES; + + public static void serialize(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(Constants.REGISTRY_MAPPINGS_FORMAT); + buffer.writeVarInt(REGISTRIES.keySet().size()); + + for (SyncedRegistry registry : REGISTRIES) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = registry.getMappings(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer, SyncedRegistriesPacketSerializer::serialize); + } + } + + public static void deserialize(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > Constants.REGISTRY_MAPPINGS_FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + SyncedRegistry registry = REGISTRIES.get(identifier); + + if (registry != null) { + SerializableRegistryMappings mappings = registry.getMappings(); + + try { + mappings.read(buffer, SyncedRegistriesPacketSerializer::deserialize, source); + mappings.build(source); + } catch (RegistryMappingException e) { + throw new RegistryMappingException("Invalid registry mappings for " + identifier, e); + } + } else { + RegistriesImpl.LOGGER.info("Skipping mappings for missing registry {}", identifier); + } + } + } + + public static void serialize(PacketBuffer buffer, Object2IntMap mappings) throws IOException { + buffer.writeVarInt(mappings.size()); + + for (Object2IntMap.Entry mapping : mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public static void deserialize(PacketBuffer buffer, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + mappings.put(identifier, id); + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/resources/fabric.mod.json b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..bc28184ef --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/resources/fabric.mod.json @@ -0,0 +1,36 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mca1.0.1_01-mc1.6.4", + "environment": "*", + "entrypoints": { + "client-init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ] + }, + "mixins": [ + "osl.registries.mixins.json" + ], + "depends": { + "fabricloader": "\u003e\u003d0.18.0", + "minecraft": "\u003e\u003d1.0.0-alpha.0.1 \u003c\u003d1.6.4", + "osl-core": "\u003e\u003d0.8.0", + "osl-entrypoints": "\u003e\u003d0.5.0", + "osl-lifecycle-events": "\u003e\u003d0.6.0", + "osl-executors": "\u003e\u003d0.1.0", + "osl-text-components": "\u003e\u003d0.1.0-", + "osl-networking": "\u003e\u003d0.9.0", + "osl-networking-impl": "\u003e\u003d0.1.0" + }, + "name": "OSL Registries", + "description": "Registries API and numerical ID synchronization.", + "authors": [ + "OrnitheMC" + ], + "contact": { + "homepage": "https://ornithemc.net/", + "issues": "https://github.com/OrnitheMC/ornithe-standard-libraries/issues", + "sources": "https://github.com/OrnitheMC/ornithe-standard-libraries" + }, + "license": "Apache-2.0" +} \ No newline at end of file diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/resources/osl.registries.mixins.json b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/resources/osl.registries.mixins.json new file mode 100644 index 000000000..c1ca54670 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,23 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "plugin": "net.ornithemc.osl.registries.impl.RegistriesMixinPlugin", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.NbtCompoundAccess", + "common.PlayerManagerMixin" + ], + "client": [ + "client.ClientNetworkHandlerAccess", + "client.IntegratedServerMixin", + "client.MinecraftMixin" + ], + "server": [ + "server.MinecraftServerMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/RegistryEvents.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/RegistryEvents.java new file mode 100644 index 000000000..9d8291886 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/RegistryEvents.java @@ -0,0 +1,31 @@ +package net.ornithemc.osl.registries.api; + +import net.ornithemc.osl.core.api.events.Event; + +/** + * Events related to registries. + */ +public final class RegistryEvents { + + /** + * This event is invoked on game start-up, after registries have been loaded, + * but before the bootstraps are run and the registries are frozen. + * Note that bootstraps may run before this point, if they are triggered by + * class loading. If you wish to hook into a particular registry's bootstrap, + * a Mixin injector is required. + * + *

+ * Callbacks to this event should be registered in your mod's entrypoint, + * and can be done as follows: + * + *

+	 * {@code
+	 * RegistryEvents.BOOTSTRAP_REGISTRIES.register(() -> {
+	 * 	...
+	 * });
+	 * }
+	 * 
+ */ + public static final Event BOOTSTRAP_REGISTRIES = Event.runnable(); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/DefaultedRegistry.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/DefaultedRegistry.java new file mode 100644 index 000000000..16a62be68 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/DefaultedRegistry.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; + +public interface DefaultedRegistry extends Registry { + + NamespacedIdentifier getDefaultIdentifier(); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/IdMap.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/IdMap.java new file mode 100644 index 000000000..9e1bd01f3 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/IdMap.java @@ -0,0 +1,64 @@ +package net.ornithemc.osl.registries.api.registry; + +import java.util.Iterator; + +import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; +import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; +import it.unimi.dsi.fastutil.objects.Reference2IntMap; +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; + +public final class IdMap implements Iterable { + + private final Int2ReferenceMap values; + private final Reference2IntMap ids; + + private int nextId = 0; + + public IdMap() { + this.values = new Int2ReferenceOpenHashMap<>(); + this.ids = new Reference2IntOpenHashMap<>(); + + this.ids.defaultReturnValue(-1); + } + + public T put(T value) { + return this.put(this.nextId, value); + } + + public T put(int id, T value) { + if (id < 0) { + throw new IllegalStateException("invalid ID " + id + " (must be >= 0)"); + } + + this.values.put(id, value); + this.ids.put(value, id); + + this.nextId = Math.max(this.nextId, id + 1); + + return value; + } + + public T get(int id) { + return this.values.get(id); + } + + public boolean has(T value) { + return this.ids.containsKey(value); + } + + public int getId(T value) { + return this.ids.getInt(value); + } + + @Override + public Iterator iterator() { + return this.values.values().iterator(); + } + + public void clear() { + this.values.clear(); + this.ids.clear(); + + this.nextId = 0; + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/Registries.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/Registries.java new file mode 100644 index 000000000..8f6dcc94d --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/Registries.java @@ -0,0 +1,21 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +public final class Registries { + + public static final Registry> REGISTRY = RegistriesImpl.REGISTRY; + + public static Registry get(ResourceKey> key) { + return RegistriesImpl.get(key); + } + + public static Registry registerSimple(ResourceKey> key, Registry.Bootstrap bootstrap) { + return RegistriesImpl.registerSimple(key, bootstrap); + } + + public static DefaultedRegistry registerDefaulted(ResourceKey> key, NamespacedIdentifier defaultIdentifier, Registry.Bootstrap bootstrap) { + return RegistriesImpl.registerDefaulted(key, defaultIdentifier, bootstrap); + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/Registry.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/Registry.java new file mode 100644 index 000000000..006728091 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/Registry.java @@ -0,0 +1,55 @@ +package net.ornithemc.osl.registries.api.registry; + +import java.util.Set; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; + +public interface Registry extends Iterable { + + NamespacedIdentifier identifier(); + + T get(int id); + + T get(ResourceKey key); + + T get(NamespacedIdentifier identifier); + + boolean has(T value); + + int getId(T value); + + ResourceKey getKey(T value); + + NamespacedIdentifier getIdentifier(T value); + + Set> keySet(); + + Set identifierSet(); + + Registry freeze(); + + static V register(Registry registry, NamespacedIdentifier identifier, V value) { + return RegistriesImpl.registerMapping(registry, identifier, value); + } + + static V register(Registry registry, ResourceKey key, V value) { + return RegistriesImpl.registerMapping(registry, key, value); + } + + @Deprecated + static V register(Registry registry, int id, NamespacedIdentifier identifier, V value) { + return RegistriesImpl.registerMapping(registry, id, identifier, value); + } + + @Deprecated + static V register(Registry registry, int id, ResourceKey key, V value) { + return RegistriesImpl.registerMapping(registry, id, key, value); + } + + interface Bootstrap { + + void init(); + + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/ResourceKey.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/ResourceKey.java new file mode 100644 index 000000000..4f3bbeeb5 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/ResourceKey.java @@ -0,0 +1,11 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; + +public interface ResourceKey { + + NamespacedIdentifier registry(); + + NamespacedIdentifier identifier(); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/ResourceKeys.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/ResourceKeys.java new file mode 100644 index 000000000..ca3e5b0c5 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/ResourceKeys.java @@ -0,0 +1,19 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.impl.registry.ResourceKeysImpl; + +public final class ResourceKeys { + + public static ResourceKey from(NamespacedIdentifier identifier) { + return ResourceKeysImpl.from(identifier); + } + + public static ResourceKey from(ResourceKey> registry, NamespacedIdentifier identifier) { + return ResourceKeysImpl.from(registry.identifier(), identifier); + } + + public static ResourceKey from(NamespacedIdentifier registry, NamespacedIdentifier identifier) { + return ResourceKeysImpl.from(registry, identifier); + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/SyncedRegistries.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/SyncedRegistries.java new file mode 100644 index 000000000..98618a753 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/SyncedRegistries.java @@ -0,0 +1,21 @@ +package net.ornithemc.osl.registries.api.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.sync.IdFixer; +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; + +public final class SyncedRegistries { + + public static void register(ResourceKey> registry) { + SyncedRegistriesImpl.register(registry); + } + + public static void registerMapper(ResourceKey> registry, NamespacedIdentifier identifier, IdMapper mapper) { + SyncedRegistriesImpl.registerMapper(registry, identifier, mapper); + } + + public static void registerFixer(ResourceKey> registry, NamespacedIdentifier identifier, IdFixer fixer) { + SyncedRegistriesImpl.registerFixer(registry, identifier, fixer); + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/WritableRegistry.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/WritableRegistry.java new file mode 100644 index 000000000..1fb30012d --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/WritableRegistry.java @@ -0,0 +1,10 @@ +package net.ornithemc.osl.registries.api.registry; + +public interface WritableRegistry extends Registry { + + V register(ResourceKey key, V value); + + @Deprecated + V register(int id, ResourceKey key, V value); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IdFixer.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IdFixer.java new file mode 100644 index 000000000..08ae498f4 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IdFixer.java @@ -0,0 +1,10 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +public interface IdFixer { + + /** + * Fix up IDs for the bound registry or map. + */ + void apply(); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IdMapper.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IdMapper.java new file mode 100644 index 000000000..809ae9768 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/IdMapper.java @@ -0,0 +1,15 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +public interface IdMapper { + + /** + * Apply the given ID mappings to the bound registry or map. + */ + void apply(RegistryMappings mappings); + + /** + * Undo the given ID mappings and reset the bound registry or map. + */ + void undo(RegistryMappings mappings); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Int2ObjectMapMapper.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Int2ObjectMapMapper.java new file mode 100644 index 000000000..2990d7a2c --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/Int2ObjectMapMapper.java @@ -0,0 +1,56 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +public class Int2ObjectMapMapper implements IdMapper { + + public static Int2ObjectMapMapper of(Int2ObjectMap registry) { + return new Int2ObjectMapMapper(registry); + } + + private final Int2ObjectMap registry; + private final Int2ObjectMap backup; + + @SuppressWarnings("unchecked") + private Int2ObjectMapMapper(Int2ObjectMap registry) { + this.registry = (Int2ObjectMap) registry; + this.backup = new Int2ObjectOpenHashMap<>(registry.size()); + } + + @Override + public void apply(RegistryMappings mappings) { + this.backup.clear(); + + for (Int2ObjectMap.Entry e : this.registry.int2ObjectEntrySet()) { + Object value = e.getValue(); + int id = e.getIntKey(); + + this.backup.put(id, value); + } + + this.registry.clear(); + + for (Int2ObjectMap.Entry e : this.backup.int2ObjectEntrySet()) { + Object value = e.getValue(); + int oldId = e.getIntKey(); + int newId = mappings.remap(oldId); + + if (newId >= 0) { + this.registry.put(newId, value); + } + } + } + + @Override + public void undo(RegistryMappings mappings) { + this.registry.clear(); + + for (Int2ObjectMap.Entry e : this.backup.int2ObjectEntrySet()) { + int id = e.getIntKey(); + Object value = e.getValue(); + + this.registry.put(id, value); + } + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/RegistryMappings.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/RegistryMappings.java new file mode 100644 index 000000000..669341b9a --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/sync/RegistryMappings.java @@ -0,0 +1,30 @@ +package net.ornithemc.osl.registries.api.registry.sync; + +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +/** + * These mappings can be used to map old IDs to new IDs. + */ +public interface RegistryMappings { + + /** + * @return the new ID for the given resource key. + */ + int remap(ResourceKey key); + + /** + * @return the new ID for the given resource ID. + */ + int remap(int id); + + /** + * @return the old ID for the given resource key. + */ + int unmap(ResourceKey key); + + /** + * @return the old ID for the given resource ID. + */ + int unmap(int id); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/Constants.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/Constants.java new file mode 100644 index 000000000..909bc52f8 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/Constants.java @@ -0,0 +1,16 @@ +package net.ornithemc.osl.registries.impl; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.networking.api.ChannelIdentifiers; +import net.ornithemc.osl.networking.api.ChannelRegistry; + +public final class Constants { + + public static final int REGISTRY_MAPPINGS_FORMAT = 1; + public static final String REGISTRY_MAPPINGS_FILE_NAME = "registry_mappings.dat"; + public static final String FORMAT_NBT_KEY = "format"; + public static final String REGISTRIES_NBT_KEY = "registries"; + + public static final NamespacedIdentifier OSL_REGISTRY_SYNC_CHANNEL = ChannelRegistry.register(ChannelIdentifiers.from("osl", "registries")); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ClearableRegistry.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ClearableRegistry.java new file mode 100644 index 000000000..a30549293 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ClearableRegistry.java @@ -0,0 +1,9 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.ornithemc.osl.registries.api.registry.WritableRegistry; + +public interface ClearableRegistry extends WritableRegistry { + + void clear(); + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/DefaultedSimpleRegistry.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/DefaultedSimpleRegistry.java new file mode 100644 index 000000000..5b786d358 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/DefaultedSimpleRegistry.java @@ -0,0 +1,75 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.DefaultedRegistry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public class DefaultedSimpleRegistry extends SimpleRegistry implements DefaultedRegistry { + + private final NamespacedIdentifier defaultIdentifier; + + private T defaultValue; + + public DefaultedSimpleRegistry(NamespacedIdentifier identifier, NamespacedIdentifier defaultIdentifier) { + super(identifier); + + this.defaultIdentifier = defaultIdentifier; + } + + @Override + public NamespacedIdentifier getDefaultIdentifier() { + return this.defaultIdentifier; + } + + @Override + public V register(int id, ResourceKey key, V value) { + if (this.defaultIdentifier.equals(key.identifier())) { + this.defaultValue = value; + } + + return super.register(id, key, value); + } + + @Override + public T get(int id) { + T value = super.get(id); + return value == null ? this.defaultValue : value; + } + + @Override + public T get(ResourceKey key) { + T value = super.get(key); + return value == null ? this.defaultValue : value; + } + + @Override + public T get(NamespacedIdentifier identifier) { + T value = super.get(identifier); + return value == null ? this.defaultValue : value; + } + + @Override + public int getId(T value) { + int id = super.getId(value); + return id == -1 ? super.getId(this.defaultValue) : id; + } + + @Override + public ResourceKey getKey(T value) { + ResourceKey key = super.getKey(value); + return key == null ? super.getKey(this.defaultValue) : key; + } + + @Override + public NamespacedIdentifier getIdentifier(T value) { + NamespacedIdentifier identifier = super.getIdentifier(value); + return identifier == null ? this.defaultIdentifier : identifier; + } + + @Override + public void clear() { + super.clear(); + + this.defaultValue = null; + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/RegistriesImpl.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/RegistriesImpl.java new file mode 100644 index 000000000..c1c7e0d45 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/RegistriesImpl.java @@ -0,0 +1,115 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.RegistryEvents; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.ResourceKeys; +import net.ornithemc.osl.registries.api.registry.WritableRegistry; + +public final class RegistriesImpl { + + public static final Logger LOGGER = LogManager.getLogger("OSL|Registries"); + + private static final WritableRegistry> WRITABLE_REGISTRY = new SimpleRegistry<>(NamespacedIdentifiers.from("root")); + private static final Map BOOTSTRAPS = new LinkedHashMap<>(); + + public static final Registry> REGISTRY = WRITABLE_REGISTRY; + + public static WritableRegistry get(ResourceKey> key) { + @SuppressWarnings("unchecked") + ResourceKey> registryKey = (ResourceKey>) (Object) key; + @SuppressWarnings("unchecked") + WritableRegistry registry = (WritableRegistry) WRITABLE_REGISTRY.get(registryKey); + + return registry; + } + + public static SimpleRegistry registerSimple(ResourceKey> key, Registry.Bootstrap bootstrap) { + return register(key, new SimpleRegistry<>(key.identifier()), bootstrap); + } + + public static DefaultedSimpleRegistry registerDefaulted(ResourceKey> key, NamespacedIdentifier defaultIdentifier, Registry.Bootstrap bootstrap) { + return register(key, new DefaultedSimpleRegistry<>(key.identifier(), defaultIdentifier), bootstrap); + } + + public static > R register(ResourceKey> key, R registry, Registry.Bootstrap bootstrap) { + if (!NamespacedIdentifiers.equals(key.identifier(), registry.identifier())) { + throw new IllegalArgumentException("illegal key " + key + " for registry " + registry.identifier()); + } + + @SuppressWarnings("unchecked") + ResourceKey> registryKey = (ResourceKey>) (Object) key; + NamespacedIdentifier identifier = registryKey.identifier(); + + WRITABLE_REGISTRY.register(registryKey, registry); + BOOTSTRAPS.put(identifier, bootstrap); + + return registry; + } + + public static V registerMapping(Registry registry, NamespacedIdentifier identifier, V value) { + return registerMapping(registry, ResourceKeys.from(registry.identifier(), identifier), value); + } + + public static V registerMapping(Registry registry, ResourceKey key, V value) { + return ((WritableRegistry) registry).register(key, value); + } + + @Deprecated + public static V registerMapping(Registry registry, int id, NamespacedIdentifier identifier, V value) { + return registerMapping(registry, id, ResourceKeys.from(registry.identifier(), identifier), value); + } + + @Deprecated + public static V registerMapping(Registry registry, int id, ResourceKey key, V value) { + return ((WritableRegistry) registry).register(id, key, value); + } + + public static void init() { + RegistryEvents.BOOTSTRAP_REGISTRIES.invoker().run(); + + bootstrap(); + freeze(); + validate(); + + LOGGER.info("Bootstrapped {} registries.", BOOTSTRAPS.size()); + } + + private static void bootstrap() { + BOOTSTRAPS.forEach((identifier, bootstrap) -> { + try { + bootstrap.init(); + } catch (Exception e) { + throw new IllegalStateException("error while bootstrapping registry " + identifier, e); + } + }); + } + + private static void freeze() { + WRITABLE_REGISTRY.freeze(); + + for (Registry registry : WRITABLE_REGISTRY) { + registry.freeze(); + } + } + + private static void validate() { + if (REGISTRY.keySet().isEmpty()) { + throw new IllegalStateException("Unable to load registries!"); + } + + for (Registry registry : REGISTRY) { + if (registry.keySet().isEmpty()) { + throw new IllegalStateException("Registry " + registry.identifier() + " is empty after bootstrap!"); + } + } + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ResourceKeyImpl.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ResourceKeyImpl.java new file mode 100644 index 000000000..dcb933b88 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ResourceKeyImpl.java @@ -0,0 +1,30 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public final class ResourceKeyImpl implements ResourceKey { + + private final NamespacedIdentifier registry; + private final NamespacedIdentifier identifier; + + ResourceKeyImpl(NamespacedIdentifier registry, NamespacedIdentifier identifier) { + this.registry = registry; + this.identifier = identifier; + } + + @Override + public String toString() { + return "ResourceKey[" + this.registry + "/" + this.identifier + "]"; + } + + @Override + public NamespacedIdentifier registry() { + return this.registry; + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ResourceKeysImpl.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ResourceKeysImpl.java new file mode 100644 index 000000000..f00a2c192 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/ResourceKeysImpl.java @@ -0,0 +1,42 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; + +public final class ResourceKeysImpl { + + private static final Map> RESOURCE_KEYS = new HashMap<>(); + + public static ResourceKeyImpl from(NamespacedIdentifier identifier) { + return from(RegistriesImpl.REGISTRY.identifier(), identifier); + } + + @SuppressWarnings("unchecked") + public static ResourceKeyImpl from(NamespacedIdentifier registry, NamespacedIdentifier identifier) { + return (ResourceKeyImpl) RESOURCE_KEYS.computeIfAbsent(new Key(registry, identifier), key -> new ResourceKeyImpl<>(registry, identifier)); + } + + private static final class Key { + + private final NamespacedIdentifier registry; + private final NamespacedIdentifier identifier; + + private Key(NamespacedIdentifier registry, NamespacedIdentifier identifier) { + this.registry = registry; + this.identifier = identifier; + } + + @Override + public boolean equals(Object o) { + return this.registry.equals(((Key) o).registry) && this.identifier.equals(((Key) o).identifier); + } + + @Override + public int hashCode() { + return Objects.hash(this.registry, this.identifier); + } + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SimpleRegistry.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SimpleRegistry.java new file mode 100644 index 000000000..88f9183d4 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SimpleRegistry.java @@ -0,0 +1,154 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; +import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; +import it.unimi.dsi.fastutil.objects.Reference2IntMap; +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.WritableRegistry; + +public class SimpleRegistry implements WritableRegistry, ClearableRegistry { + + private final NamespacedIdentifier identifier; + + private final Int2ReferenceMap values; + private final Reference2IntMap ids; + private final Map registry; + private final Map> keys; + private final Map identifiers; + + private int nextId = 0; + private boolean frozen; + + public SimpleRegistry(NamespacedIdentifier identifier) { + this.identifier = identifier; + + this.values = new Int2ReferenceOpenHashMap<>(); + this.ids = new Reference2IntOpenHashMap<>(); + this.registry = new HashMap<>(); + this.keys = new IdentityHashMap<>(); + this.identifiers = new IdentityHashMap<>(); + + this.ids.defaultReturnValue(-1); + } + + @Override + public V register(ResourceKey key, V value) { + return this.register(this.nextId++, key, value); + } + + @Override + public V register(int id, ResourceKey key, V value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + if (id < 0) { + throw new IllegalStateException("invalid ID " + id + " (must be >= 0)"); + } + if (this.values.containsKey(id)) { + throw new IllegalStateException("duplicate ID " + id + " (" + this.getKey(this.get(id)) + " and " + key + ")"); + } + if (this.registry.containsKey(key.identifier())) { + throw new IllegalStateException("duplicate Namespaced ID " + key.identifier() + " (" + this.getId(this.get(key)) + " and " + id + ")"); + } + if (this.ids.containsKey(value) || this.keys.containsKey(value) || this.identifiers.containsKey(value)) { + throw new IllegalStateException("value registered twice (" + this.getId(value) + ", " + this.getKey(value) + " and " + id + ", " + key + ")"); + } + + this.values.put(id, value); + this.ids.put(value, id); + this.registry.put(key.identifier(), value); + this.keys.put(value, key); + this.identifiers.put(value, key.identifier()); + + this.nextId = Math.max(this.nextId, id + 1); + + return value; + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } + + @Override + public T get(int id) { + return this.values.get(id); + } + + @Override + public T get(ResourceKey key) { + return this.registry.get(key.identifier()); + } + + @Override + public T get(NamespacedIdentifier identifier) { + return this.registry.get(identifier); + } + + @Override + public boolean has(T value) { + return this.ids.containsKey(value); + } + + @Override + public int getId(T value) { + return this.ids.getInt(value); + } + + @Override + public ResourceKey getKey(T value) { + return this.keys.get(value); + } + + @Override + public NamespacedIdentifier getIdentifier(T value) { + return this.identifiers.get(value); + } + + @Override + public Set> keySet() { + return this.keys.values().stream().collect(Collectors.toSet()); + } + + @Override + public Set identifierSet() { + return this.registry.keySet(); + } + + @Override + public Iterator iterator() { + return this.registry.values().iterator(); + } + + @Override + public Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public void clear() { + this.values.clear(); + this.ids.clear(); + this.registry.clear(); + this.keys.clear(); + this.identifiers.clear(); + + this.nextId = 0; + this.frozen = false; + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java new file mode 100644 index 000000000..ce910ae51 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java @@ -0,0 +1,101 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.core.api.util.NamespacedIdentifiers; +import net.ornithemc.osl.registries.api.registry.Registries; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.sync.IdFixer; +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.api.registry.sync.RegistryMappings; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMapper; + +public final class SyncedRegistriesImpl { + + public static final Registry SYNCED_REGISTRIES = new SimpleRegistry<>(NamespacedIdentifiers.from("synced_registry")); + + public static void register(ResourceKey> registry) { + NamespacedIdentifier identifier = registry.identifier(); + Registry instance = Registries.get(registry); + + if (instance == null) { + throw new IllegalArgumentException("unknown registry " + identifier); + } else if (!(instance instanceof ClearableRegistry)) { + throw new IllegalArgumentException("unsyncable registry " + identifier); + } else { + SyncedRegistry synced = SYNCED_REGISTRIES.get(identifier); + + if (synced != null) { + throw new IllegalArgumentException("duplicate synced registry " + identifier); + } else { + Registry.register(SYNCED_REGISTRIES, registry.identifier(), synced = new SyncedRegistry(instance)); + } + + synced.registerMapper(identifier, RegistryMapper.of(instance)); + } + } + + public static void registerMapper(ResourceKey> registry, NamespacedIdentifier identifier, IdMapper mapper) { + SyncedRegistry synced = SYNCED_REGISTRIES.get(registry.identifier()); + + if (synced == null) { + throw new IllegalArgumentException("registry " + registry.identifier() + " is not synced!"); + } else { + synced.registerMapper(identifier, mapper); + } + } + + public static void registerFixer(ResourceKey> registry, NamespacedIdentifier identifier, IdFixer fixer) { + SyncedRegistry synced = SYNCED_REGISTRIES.get(registry.identifier()); + + if (synced == null) { + throw new IllegalArgumentException("registry " + registry.identifier() + " is not synced!"); + } else { + synced.registerFixer(identifier, fixer); + } + } + + public static void init() { + for (Registry registry : Registries.REGISTRY) { + SyncedRegistry synced = SYNCED_REGISTRIES.get(registry.identifier()); + + if (synced != null) { + synced.getMappings().reset(); + } else { + RegistriesImpl.LOGGER.debug("registry {} is not synced!", registry.identifier()); + } + } + } + + public static void resetMappings() { + for (SyncedRegistry registry : SYNCED_REGISTRIES) { + registry.getMappings().reset(); + } + } + + public static void applyMappings() { + for (SyncedRegistry registry : SYNCED_REGISTRIES) { + RegistryMappings mappings = registry.getMappings(); + + for (IdMapper mapper : registry.getMappers()) { + mapper.apply(mappings); + } + for (IdFixer fixer : registry.getFixers()) { + fixer.apply(); + } + } + } + + public static void undoMappings() { + for (SyncedRegistry registry : SYNCED_REGISTRIES) { + RegistryMappings mappings = registry.getMappings(); + + for (IdMapper mapper : registry.getMappers()) { + mapper.undo(mappings); + } + for (IdFixer fixer : registry.getFixers()) { + fixer.apply(); + } + } + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistry.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistry.java new file mode 100644 index 000000000..e40ad159f --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistry.java @@ -0,0 +1,60 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.sync.IdFixer; +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.impl.registry.sync.SerializableRegistryMappings; + +public class SyncedRegistry { + + private final Registry registry; + + private final SerializableRegistryMappings mappings; + private final Map mappers; + private final Map fixers; + + public SyncedRegistry(Registry registry) { + this.registry = registry; + + this.mappings = SerializableRegistryMappings.of(this.registry); + this.mappers = new LinkedHashMap<>(); + this.fixers = new LinkedHashMap<>(); + } + + public void registerMapper(NamespacedIdentifier identifier, IdMapper mapper) { + if (this.mappers.containsKey(identifier)) { + throw new IllegalArgumentException("duplicate ID mapper " + identifier + " for registry " + this.registry.identifier()); + } else { + this.mappers.put(identifier, mapper); + } + } + + public void registerFixer(NamespacedIdentifier identifier, IdFixer fixer) { + if (this.fixers.containsKey(identifier)) { + throw new IllegalArgumentException("duplicate ID fixer " + identifier + " for registry " + this.registry.identifier()); + } else { + this.fixers.put(identifier, fixer); + } + } + + public NamespacedIdentifier identifier() { + return this.registry.identifier(); + } + + public SerializableRegistryMappings getMappings() { + return this.mappings; + } + + public Collection getMappers() { + return this.mappers.values(); + } + + public Collection getFixers() { + return this.fixers.values(); + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMapper.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMapper.java new file mode 100644 index 000000000..cf1c42818 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMapper.java @@ -0,0 +1,73 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.WritableRegistry; +import net.ornithemc.osl.registries.api.registry.sync.IdMapper; +import net.ornithemc.osl.registries.api.registry.sync.RegistryMappings; +import net.ornithemc.osl.registries.impl.registry.ClearableRegistry; +import net.ornithemc.osl.registries.impl.registry.SimpleRegistry; + +public class RegistryMapper implements IdMapper { + + public static RegistryMapper of(Registry registry) { + if (registry instanceof ClearableRegistry) { + return new RegistryMapper(registry); + } else { + throw new IllegalArgumentException("cannot create mapper for non-clearable registry " + registry.identifier()); + } + } + + private final ClearableRegistry registry; + private final ClearableRegistry backup; + + @SuppressWarnings("unchecked") + private RegistryMapper(Registry registry) { + this.registry = (ClearableRegistry) registry; + this.backup = new SimpleRegistry<>(registry.identifier()); + } + + @Override + public void apply(RegistryMappings mappings) { + this.backup.clear(); + + for (Object value : this.registry) { + ResourceKey key = this.registry.getKey(value); + int id = this.registry.getId(value); + + register(this.backup, id, key, value); + } + + this.registry.clear(); + + for (Object value : this.backup) { + ResourceKey key = this.backup.getKey(value); + int id = mappings.remap(key); + + if (id >= 0) { + register(this.registry, id, key, value); + } + } + + this.registry.freeze(); + } + + @Override + public void undo(RegistryMappings mappings) { + this.registry.clear(); + + for (Object value : this.backup) { + int id = this.backup.getId(value); + ResourceKey key = this.backup.getKey(value); + + register(this.registry, id, key, value); + } + + this.registry.freeze(); + } + + @SuppressWarnings("deprecation") + private static void register(WritableRegistry registry, int id, ResourceKey key, Object value) { + registry.register(id, key, value); + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMappingException.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMappingException.java new file mode 100644 index 000000000..92252a748 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMappingException.java @@ -0,0 +1,13 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +@SuppressWarnings("serial") +public class RegistryMappingException extends Exception { + + public RegistryMappingException(String message) { + super(message); + } + + public RegistryMappingException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMappingSource.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMappingSource.java new file mode 100644 index 000000000..768484742 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMappingSource.java @@ -0,0 +1,7 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +public enum RegistryMappingSource { + + WORLD_SAVE, REMOTE_SERVER, CLIENT + +} diff --git a/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java new file mode 100644 index 000000000..3dbc97bc8 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java @@ -0,0 +1,121 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +import java.io.IOException; + +import it.unimi.dsi.fastutil.ints.Int2IntMap; +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +import net.ornithemc.osl.registries.api.registry.sync.RegistryMappings; + +public class SerializableRegistryMappings implements RegistryMappings { + + public static SerializableRegistryMappings of(Registry registry) { + return new SerializableRegistryMappings(registry); + } + + final Registry registry; + + final Object2IntMap mappings = new Object2IntOpenHashMap<>(); + final Object2IntMap unmappings = new Object2IntOpenHashMap<>(); + + final Int2IntMap idMappings = new Int2IntOpenHashMap(); + final Int2IntMap idUnmappings = new Int2IntOpenHashMap(); + + @SuppressWarnings("unchecked") + private SerializableRegistryMappings(Registry registry) { + this.registry = (Registry) registry; + } + + @Override + public int remap(ResourceKey key) { + return this.mappings.getOrDefault(key.identifier(), -1); + } + + @Override + public int remap(int id) { + return this.idMappings.getOrDefault(id, -1); + } + + @Override + public int unmap(ResourceKey key) { + return this.unmappings.getOrDefault(key.identifier(), -1); + } + + @Override + public int unmap(int id) { + return this.idUnmappings.getOrDefault(id, -1); + } + + public void read(M medium, Deserializer deserializer, RegistryMappingSource source) throws IOException, RegistryMappingException { + deserializer.deserialize(medium, this.mappings, source); + } + + public void write(M medium, Serializer serializer) throws IOException { + serializer.serialize(medium, this.mappings); + } + + public void reset() { + this.mappings.clear(); + this.unmappings.clear(); + + this.idMappings.clear(); + this.idUnmappings.clear(); + + for (Object value : this.registry) { + NamespacedIdentifier identifier = this.registry.getIdentifier(value); + int id = this.registry.getId(value); + + this.mappings.put(identifier, id); + this.unmappings.put(identifier, id); + + this.idMappings.put(id, id); + this.idUnmappings.put(id, id); + } + } + + public void build(RegistryMappingSource source) throws RegistryMappingException { + this.idMappings.clear(); + this.idUnmappings.clear(); + + for (NamespacedIdentifier identifier : this.mappings.keySet()) { + int newId = this.mappings.getInt(identifier); + int oldId = this.unmappings.getInt(identifier); + + if (oldId >= 0) { + this.idMappings.put(oldId, newId); + } else if (source == RegistryMappingSource.REMOTE_SERVER) { + throw new RegistryMappingException("received mapping for unknown entry " + identifier); + } + } + + for (NamespacedIdentifier identifier : this.unmappings.keySet()) { + int oldId = this.unmappings.getInt(identifier); + int newId = this.mappings.getInt(identifier); + + if (newId >= 0) { + this.idUnmappings.put(newId, oldId); + } else if (source == RegistryMappingSource.CLIENT) { + throw new RegistryMappingException("missing mapping for required entry " + identifier); + } + } + } + + @FunctionalInterface + public interface Serializer { + + void serialize(M medium, Object2IntMap mappings) throws IOException; + + } + + @FunctionalInterface + public interface Deserializer { + + void deserialize(M Medium, Object2IntMap mappings, RegistryMappingSource source) throws IOException, RegistryMappingException; + + } +} diff --git a/settings.gradle b/settings.gradle index a71fb1581..22dc52993 100644 --- a/settings.gradle +++ b/settings.gradle @@ -116,6 +116,14 @@ include ':libraries:networking-impl:networking-impl-mc1.13-pre3-mc1.13-pre3' include ':libraries:networking-impl:networking-impl-mc1.13-pre4-mc1.13.2' include ':libraries:networking-impl:networking-impl-mc18w43a-mc1.14.4' +include ':libraries:registries' +include ':libraries:registries:registries-mca1.0.1_01-mc1.6.4' +include ':libraries:registries:registries-mc13w36a-mc14w26c' +include ':libraries:registries:registries-mc14w27a-mc17w46a' +include ':libraries:registries:registries-mc17w47a-mc18w31a' +include ':libraries:registries:registries-mc18w32a-mc1.13.2' +include ':libraries:registries:registries-mc18w43a-mc1.14.4' + include ':libraries:resource-loader' include ':libraries:resource-loader:resource-loader-mca1.0.1_01-mca1.2.1_01' include ':libraries:resource-loader:resource-loader-mca1.2.2-mc1.2.5'