diff --git a/libraries/networking-impl/gradle.properties b/libraries/networking-impl/gradle.properties index 1b783988..a23f1171 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 6748a0b3..dfa03a6d 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 00000000..e067a183 --- /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 00000000..1d596400 --- /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 ef5dbdfb..e43da06c 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 1b011d9d..bc5386d1 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 acd027e0..00000000 --- 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 e88d1f5a..463dde8b 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 ac66d440..270f4b80 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 00000000..3c389c76 --- /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 0da0ddaa..738808f8 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 f64bbc23..4c0a97f4 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 2785b5e8..9bc0ddf8 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 00000000..608aea8b --- /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 00000000..e067a183 --- /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 00000000..1d596400 --- /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 ef5dbdfb..e43da06c 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 1b011d9d..bc5386d1 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 00000000..e0d53ec6 --- /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 acd027e0..00000000 --- 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 e88d1f5a..463dde8b 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 ac66d440..270f4b80 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 00000000..3c389c76 --- /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 82188a84..89358be7 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 f64bbc23..a8084bf8 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 08410b9e..89ea1e8c 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 00000000..e067a183 --- /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 47f751c1..995b1149 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 00000000..1d596400 --- /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 6faff580..83a73afb 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 00000000..6600fd99 --- /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 310e1e82..1b5d4a10 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 00000000..445e1c41 --- /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 bf2aedb7..0b2b7052 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 fd9e42b4..6ce6f6ee 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 225ab3c4..7309aa67 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 00000000..938816a7 --- /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 b8b71777..4799bb11 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 68d5629c..89ea1e8c 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 00000000..e067a183 --- /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 47f751c1..995b1149 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 00000000..1d596400 --- /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 6faff580..83a73afb 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 00000000..6600fd99 --- /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 310e1e82..1b5d4a10 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 00000000..445e1c41 --- /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 bf2aedb7..0b2b7052 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 a07c8490..9b1e6ce4 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 15de3ea6..f240f699 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 00000000..938816a7 --- /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 b8b71777..4799bb11 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 f97e0a06..77c8c039 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 00000000..e067a183 --- /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 00000000..2537236c --- /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 00000000..1d596400 --- /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 a5a8a07b..d61a4420 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 00000000..12b4690c --- /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 00000000..6f698974 --- /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 00000000..32ec4bae --- /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 bcdecf70..2f4e70f3 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 c05277df..5fb807bd 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 f58bac87..59343247 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 6e7aac37..7239176e 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 f97e0a06..77c8c039 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 00000000..5ca85f59 --- /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 00000000..e067a183 --- /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 00000000..1d596400 --- /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 a5a8a07b..67a6060c 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 00000000..6f698974 --- /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 00000000..718f04e3 --- /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 524a0e78..6fc5bdde 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 dcf4301b..e481b3fc 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 00000000..b47de07d --- /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 c05277df..5fb807bd 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 2a1b77d2..dfa09175 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 bfb2c375..b739362a 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 10f44a33..3aea1c46 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 00000000..e067a183 --- /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 00000000..1d596400 --- /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 ef5dbdfb..e43da06c 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 00000000..a53f875a --- /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 00000000..7f4d6740 --- /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 77688e80..463dde8b 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 ac66d440..270f4b80 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 7a03c9bf..b5b15263 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 24982b35..7d6b73fe 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 10f44a33..3aea1c46 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 00000000..e067a183 --- /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 00000000..1d596400 --- /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 ef5dbdfb..e43da06c 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 1b011d9d..a53f875a 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 acd027e0..00000000 --- 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 e88d1f5a..463dde8b 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 ac66d440..270f4b80 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 00000000..cc6cfb48 --- /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 ed03b064..074ccede 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 f64bbc23..4c0a97f4 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 10f44a33..3aea1c46 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 00000000..cbf86c51 --- /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 00000000..e067a183 --- /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 00000000..1d596400 --- /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 ef5dbdfb..e43da06c 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 1b011d9d..00000000 --- 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 00000000..48b12988 --- /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 00000000..5b88c3f5 --- /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 00000000..f055ed64 --- /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 acd027e0..00000000 --- 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 e88d1f5a..463dde8b 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 ac66d440..270f4b80 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 00000000..3c389c76 --- /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 34f9bebd..6bdb081e 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 f64bbc23..d4dcc4aa 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 2785b5e8..9bc0ddf8 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 00000000..0e280793 --- /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 00000000..e067a183 --- /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 00000000..1d596400 --- /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 ef5dbdfb..e43da06c 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 2749c72d..00000000 --- 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 00000000..c31e69f0 --- /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 00000000..e01c0f43 --- /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 eb2bc2be..00000000 --- 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 eaca81eb..2f8c8bce 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 ac66d440..270f4b80 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 00000000..3c389c76 --- /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 0ab46b3f..932d872a 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 f64bbc23..c71fb00f 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 eb557624..e95e2602 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 7c0a837b..58fbbc99 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 283c296d..d5dc849d 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 00000000..1d596400 --- /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 00000000..445e1c41 --- /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 15b8f09f..6b80b7e9 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 381c0697..2928389b 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 a277a3cb..a39a44db 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 f0a604fc..d0d42247 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 eb557624..e95e2602 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 df5a55ff..4fd4b811 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 00000000..e067a183 --- /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 283c296d..d5dc849d 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 c48e552f..cf2bd322 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 00000000..4caa6dd3 --- /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 f744be9b..fde6d33d 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 00000000..938816a7 --- /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 c9867435..ded2c522 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 eb557624..e95e2602 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 85d0270a..cc0bc48a 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 00000000..e067a183 --- /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 283c296d..d5dc849d 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 00000000..1d596400 --- /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 c48e552f..a660862d 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 00000000..6600fd99 --- /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 00000000..445e1c41 --- /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 15b8f09f..6b80b7e9 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 381c0697..45a75421 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 f89c12ae..fd4148eb 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 00000000..938816a7 --- /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 95fccaf7..4c07c796 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 fd63fa5a..43bb1345 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 2bb2cf19..f5b0a2cb 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 00000000..e067a183 --- /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 283c296d..d5dc849d 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 00000000..1d596400 --- /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 c48e552f..a660862d 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 00000000..6600fd99 --- /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 00000000..445e1c41 --- /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 15b8f09f..6b80b7e9 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 381c0697..45a75421 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 76c0421a..fc81a562 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 00000000..938816a7 --- /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 95fccaf7..4c07c796 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 4ea198e6..436ca4a1 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 d5adcfb8..c971cb64 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 e248c524..83c6811c 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 bff1ba39..00000000 --- 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 00000000..9dcbf193 --- /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 42989829..a4350530 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 00000000..11c0dd0a --- /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 613dbee7..2bdfebea 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 1d450016..c881348f 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 d5adcfb8..c971cb64 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 e248c524..83c6811c 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 bff1ba39..00000000 --- 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 00000000..9dcbf193 --- /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 e9ba1661..42e00b83 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 00000000..11c0dd0a --- /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 647c0c11..2dc0cd7b 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 883a357e..1ec6f7ee 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 9d33bccf..f7c894fd 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 00000000..95d03542 --- /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 00000000..9e0c10f6 --- /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 98004bf7..7ecbb4d1 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 9d33bccf..f7c894fd 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 00000000..86769405 --- /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 501017a4..37ab456f 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 00000000..9972f883 --- /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 d5adcfb8..c971cb64 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 00000000..e067a183 --- /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 00000000..9dcbf193 --- /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 9ead7866..dd6007ea 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 d5adcfb8..c971cb64 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 9d33bccf..f7c894fd 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 00000000..9dcbf193 --- /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 00000000..86769405 --- /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 7569828e..e2103655 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 00000000..9972f883 --- /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 00000000..0d026b87 --- /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 00000000..6400d88f --- /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 00000000..dddbc1fe --- /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 00000000..403bf484 --- /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 00000000..0a350fdb --- /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 00000000..1cad83f5 --- /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 00000000..68100e62 --- /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 00000000..f6896b0b --- /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 00000000..02c3c958 --- /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 00000000..93002021 --- /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 00000000..4b2aa282 --- /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 00000000..e83acb15 --- /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 00000000..ea2c60af --- /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 00000000..d7da0d28 --- /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 00000000..37a827c2 --- /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 00000000..662971ff --- /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 00000000..e6535ddc --- /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 00000000..7d2fa4d6 --- /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 00000000..2c6ff332 --- /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 00000000..1876ef88 --- /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 00000000..e2478275 --- /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 00000000..f1fc0a2e --- /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 00000000..faa20f93 --- /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 00000000..5a5a61e9 --- /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 00000000..127fc893 --- /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 00000000..0a350fdb --- /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 00000000..6b9ea8e5 --- /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 00000000..68100e62 --- /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 00000000..17a3c64a --- /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 00000000..f6896b0b --- /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 00000000..89d9cc76 --- /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 00000000..02c3c958 --- /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 00000000..93002021 --- /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 00000000..9c720b26 --- /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 00000000..1cabc407 --- /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 00000000..2fee3cc2 --- /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 00000000..cc07e9aa --- /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 00000000..3e5c3bc3 --- /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 00000000..40d72e4c --- /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 00000000..37a827c2 --- /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 00000000..662971ff --- /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 00000000..7789e2a0 --- /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 00000000..e6535ddc --- /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 00000000..10f5ea4c --- /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 00000000..ae769c9c --- /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 00000000..c51a71cd --- /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 00000000..e2478275 --- /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 00000000..f1fc0a2e --- /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 00000000..b5628aeb --- /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 00000000..2382db14 --- /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 00000000..90ccd501 --- /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 00000000..0a350fdb --- /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 00000000..214f5d68 --- /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 00000000..68100e62 --- /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 00000000..17a3c64a --- /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 00000000..f6896b0b --- /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 00000000..02c3c958 --- /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 00000000..93002021 --- /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 00000000..9c720b26 --- /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 00000000..3dcf24cc --- /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 00000000..cc07e9aa --- /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 00000000..03edfe3f --- /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 00000000..40d72e4c --- /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 00000000..01174aa6 --- /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 00000000..662971ff --- /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 00000000..7789e2a0 --- /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 00000000..e6535ddc --- /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 00000000..10f5ea4c --- /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 00000000..ae769c9c --- /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 00000000..f5ba9338 --- /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 00000000..e2478275 --- /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 00000000..f1fc0a2e --- /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 00000000..712d8266 --- /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 00000000..2382db14 --- /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 00000000..21c84ee3 --- /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 00000000..0a350fdb --- /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 00000000..4c9c2619 --- /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 00000000..68100e62 --- /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 00000000..17a3c64a --- /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 00000000..f6896b0b --- /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 00000000..02c3c958 --- /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 00000000..93002021 --- /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 00000000..3dcf24cc --- /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 00000000..79f753e2 --- /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 00000000..03edfe3f --- /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 00000000..7accbaae --- /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 00000000..01174aa6 --- /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 00000000..3ec07e28 --- /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 00000000..662971ff --- /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 00000000..7789e2a0 --- /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 00000000..e6535ddc --- /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 00000000..9cdf561f --- /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 00000000..d1cf93ce --- /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 00000000..f8cf9d4c --- /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 00000000..e2478275 --- /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 00000000..f1fc0a2e --- /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 00000000..772a1eca --- /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 00000000..88c69c01 --- /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 00000000..7e3a3ca5 --- /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 00000000..0a350fdb --- /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 00000000..071d210e --- /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 00000000..68100e62 --- /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 00000000..17a3c64a --- /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 00000000..f6896b0b --- /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 00000000..02c3c958 --- /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 00000000..bfabeb1a --- /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 00000000..7b6b88a1 --- /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 00000000..3dcf24cc --- /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 00000000..79f753e2 --- /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 00000000..03edfe3f --- /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 00000000..46c6e516 --- /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 00000000..01174aa6 --- /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 00000000..662971ff --- /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 00000000..7789e2a0 --- /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 00000000..e6535ddc --- /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 00000000..9cdf561f --- /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 00000000..d1cf93ce --- /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 00000000..67192d99 --- /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 00000000..e2478275 --- /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 00000000..f1fc0a2e --- /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 00000000..fc44131f --- /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 00000000..88c69c01 --- /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 00000000..21c84ee3 --- /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 00000000..0a350fdb --- /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 00000000..a78fb883 --- /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 00000000..68100e62 --- /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 00000000..c27f86c9 --- /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 00000000..25a4ea67 --- /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 00000000..22ea5217 --- /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 00000000..ffe477a5 --- /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 00000000..02c3c958 --- /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 00000000..107f853f --- /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 00000000..93002021 --- /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 00000000..91ac9661 --- /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 00000000..f9fb53d5 --- /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 00000000..90ec0f0b --- /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 00000000..80e0a0ce --- /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 00000000..f1fc0a2e --- /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 00000000..bc28184e --- /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 00000000..c1ca5467 --- /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 00000000..9d829188 --- /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 00000000..16a62be6 --- /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 00000000..9e1bd01f --- /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 00000000..8f6dcc94 --- /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 00000000..00672809 --- /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 00000000..4f3bbeeb --- /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 00000000..ca3e5b0c --- /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 00000000..98618a75 --- /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 00000000..1fb30012 --- /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 00000000..08ae498f --- /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 00000000..809ae976 --- /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 00000000..2990d7a2 --- /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 00000000..669341b9 --- /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 00000000..909bc52f --- /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 00000000..a3054929 --- /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 00000000..5b786d35 --- /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 00000000..c1c7e0d4 --- /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 00000000..dcb933b8 --- /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 00000000..f00a2c19 --- /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 00000000..88f9183d --- /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 00000000..ce910ae5 --- /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 00000000..e40ad159 --- /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 00000000..cf1c4281 --- /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 00000000..92252a74 --- /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 00000000..76848474 --- /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 00000000..3dbc97bc --- /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 a71fb158..22dc5299 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'