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..1378abd3 --- /dev/null +++ b/libraries/registries/README.md @@ -0,0 +1 @@ +# Registries API 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..995d27d3 --- /dev/null +++ b/libraries/registries/gradle.properties @@ -0,0 +1,8 @@ +library_id = registries +library_name = Registries +library_description = Registries API and numerical ID synchronization. +library_version = 0.1.0-alpha.1 + +entrypoint_init = net.ornithemc.osl.registries.impl.RegistriesEntrypoint +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/api/registry/SyncedRegistries.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/api/registry/SyncedRegistries.java new file mode 100644 index 00000000..20ab0c61 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/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 registerMapper(ResourceKey> registry) { + SyncedRegistriesImpl.registerMapper(registry); + } + + public static void registerMapper(ResourceKey> registry, IdMapper mapper) { + SyncedRegistriesImpl.registerMapper(registry, mapper); + } + + public static void registerFixer(NamespacedIdentifier key, IdFixer fixer) { + SyncedRegistriesImpl.registerFixer(key, fixer); + } +} 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..06315d43 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,50 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.ModInitializer; +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.lifecycle.api.server.MinecraftServerEvents; +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; + +public final class RegistriesEntrypoint implements ModInitializer, ClientModInitializer { + + @Override + public void init() { + MinecraftServerEvents.STOP.register(server -> { + SyncedRegistriesImpl.undoMappings(); + }); + } + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(SyncedRegistriesImpl.CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesImpl.readMappings(buffer); + + 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/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..ad2ef0e0 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,126 @@ +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; + +@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); + SyncedRegistriesImpl.readMappings(nbt); + 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(); + SyncedRegistriesImpl.writeMappings(nbt); + + try { + 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..41998ffa --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/CrudeIncrementalIntIdentityHashMapMixin.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 CrudeIncrementalIntIdentityHashMapMixin 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-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..232ee79b --- /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(T 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..91b1959e --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,37 @@ +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.registry.SyncedRegistriesImpl; + +@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, SyncedRegistriesImpl.CHANNEL, SyncedRegistriesImpl::writeMappings); + } + } +} 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..062a303e --- /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(T 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/SyncedRegistriesImpl.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java new file mode 100644 index 00000000..0dd5676f --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java @@ -0,0 +1,188 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; + +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.networking.api.PacketBuffer; +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.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMapper; +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.SerializableRegistryMappings; + +public final class SyncedRegistriesImpl { + + public static final NamespacedIdentifier CHANNEL = Constants.OSL_REGISTRY_SYNC_CHANNEL; + + private static final Map REGISTRY_MAPPINGS = new LinkedHashMap<>(); + private static final Map REGISTRY_MAPPERS = new LinkedHashMap<>(); + private static final Map ID_FIXERS = new LinkedHashMap<>(); + + private static final String FORMAT_NBT_KEY = "format"; + private static final int FORMAT = 1; + + public static void registerMapper(ResourceKey> registry) { + registerMapper(registry, RegistryMapper.of(Registries.get(registry))); + } + + public static void registerMapper(ResourceKey> registry, IdMapper mapper) { + NamespacedIdentifier identifier = registry.identifier(); + + if (Registries.get(registry) == null) { + throw new IllegalArgumentException("cannot register registry mapper: unknown registry: " + identifier); + } else { + REGISTRY_MAPPERS.put(identifier, mapper); + } + } + + public static void registerFixer(NamespacedIdentifier identifier, IdFixer fixer) { + if (ID_FIXERS.containsKey(identifier)) { + throw new IllegalArgumentException("duplicate ID fixer " + identifier); + } else { + ID_FIXERS.put(identifier, fixer); + } + } + + public static void init() { + for (Registry registry : Registries.REGISTRY) { + if (registry instanceof ClearableRegistry) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = SerializableRegistryMappings.of(registry); + + REGISTRY_MAPPINGS.put(identifier, mappings); + } + } + + for (NamespacedIdentifier identifier : REGISTRY_MAPPERS.keySet()) { + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings == null) { + throw new IllegalStateException("Illegal registry mapper for unsynced registry " + identifier); + } else { + mappings.reset(); + } + } + } + + public static void readMappings(PacketBuffer buffer) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > 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(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings != null) { + try { + mappings.read(buffer, RegistryMappingSource.REMOTE_SERVER); + } 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 writeMappings(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(FORMAT); + buffer.writeVarInt(REGISTRY_MAPPINGS.size()); + + for (Map.Entry e : REGISTRY_MAPPINGS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + SerializableRegistryMappings mappings = e.getValue(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer); + } + } + + public static void readMappings(NbtCompound nbt) throws RegistryMappingException { + int format = nbt.getInt(FORMAT_NBT_KEY); + + if (format > FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + for (String nbtKey : nbt.getKeys()) { + NbtCompound mappingsNbt = nbt.getCompound(nbtKey); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(nbtKey); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings != null) { + try { + mappings.read(mappingsNbt, RegistryMappingSource.WORLD_SAVE); + } 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 writeMappings(NbtCompound nbt) { + nbt.putInt(FORMAT_NBT_KEY, FORMAT); + + for (Map.Entry e : REGISTRY_MAPPINGS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + SerializableRegistryMappings mappings = e.getValue(); + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt); + nbt.put(identifier.toString(), mappingsNbt); + } + } + + public static void resetMappings() { + for (SerializableRegistryMappings mappings : REGISTRY_MAPPINGS.values()) { + mappings.reset(); + } + } + + public static void applyMappings() { + for (Map.Entry e : REGISTRY_MAPPERS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + IdMapper mapper = e.getValue(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + mapper.apply(mappings); + } + + applyFixers(); + } + + public static void undoMappings() { + for (Map.Entry e : REGISTRY_MAPPERS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + IdMapper mapper = e.getValue(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + mapper.undo(mappings); + } + + applyFixers(); + } + + public static void applyFixers() { + for (IdFixer fixer : ID_FIXERS.values()) { + fixer.apply(); + } + } +} 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..17520775 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.IdRegistry; + +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 final class VanillaRegistries { + + public static WritableRegistry register(ResourceKey> key, IdRegistry registry) { + return RegistriesImpl.register(key, WrappedIdRegistry.of(key, registry), () -> { }); + } +} 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..a6ce345d --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java @@ -0,0 +1,141 @@ +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); + } + + private final NamespacedIdentifier identifier; + private final IdRegistry registry; + + private int nextId; + private boolean frozen; + + private WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + private NamespacedIdentifier serializeKey(String key) { + return NamespacedIdentifiers.parse(key); + } + + private String deserializeKey(NamespacedIdentifier identifier) { + return identifier.toString(); + } + + private ResourceKey resourceKey(NamespacedIdentifier identifier) { + return ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, String key, T value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public void register(ResourceKey key, T value) { + this.register(this.nextId, key, value); + } + + @Override + public void register(int id, ResourceKey key, T value) { + this.registry.register(id, this.deserializeKey(key.identifier()), 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 Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public Iterator iterator() { + return this.registry.iterator(); + } + + @Override + public void clear() { + this.registry.osl$registries$clear(); + + this.nextId = 0; + this.frozen = false; + } + + public interface RegisterCallback { + + void valueRegistered(int id, String key, T value); + + } +} diff --git a/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java new file mode 100644 index 00000000..c44b8c9a --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java @@ -0,0 +1,62 @@ +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.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; + +public final class SerializableRegistryMappings extends MemoryRegistryMappings { + + public static SerializableRegistryMappings of(Registry registry) { + return new SerializableRegistryMappings(registry); + } + + private SerializableRegistryMappings(Registry registry) { + super(registry); + } + + public void read(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + this.mappings.put(identifier, id); + } + + this.build(source); + } + + public void write(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(this.mappings.size()); + + for (Object2IntMap.Entry mapping : this.mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public void read(NbtCompound nbt, RegistryMappingSource source) throws RegistryMappingException { + for (String key : nbt.getKeys()) { + this.mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + + this.build(source); + } + + public void write(NbtCompound nbt) { + for (Object2IntMap.Entry mapping : this.mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } +} 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..2204e71b --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/fabric.mod.json @@ -0,0 +1,40 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc13w36a-mc14w26c", + "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ], + "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..e1f622f7 --- /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..522d14d2 --- /dev/null +++ b/libraries/registries/registries-mc13w36a-mc14w26c/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,21 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.BootstrapMixin", + "common.CrudeIncrementalIntIdentityHashMapMixin", + "common.Id2ObjectBiMapMixin", + "common.IdRegistryMixin", + "common.PlayerManagerMixin" + ], + "client": [ + ], + "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/SyncedRegistries.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/api/registry/SyncedRegistries.java new file mode 100644 index 00000000..20ab0c61 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/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 registerMapper(ResourceKey> registry) { + SyncedRegistriesImpl.registerMapper(registry); + } + + public static void registerMapper(ResourceKey> registry, IdMapper mapper) { + SyncedRegistriesImpl.registerMapper(registry, mapper); + } + + public static void registerFixer(NamespacedIdentifier key, IdFixer fixer) { + SyncedRegistriesImpl.registerFixer(key, fixer); + } +} 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..06315d43 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,50 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.ModInitializer; +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.lifecycle.api.server.MinecraftServerEvents; +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; + +public final class RegistriesEntrypoint implements ModInitializer, ClientModInitializer { + + @Override + public void init() { + MinecraftServerEvents.STOP.register(server -> { + SyncedRegistriesImpl.undoMappings(); + }); + } + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(SyncedRegistriesImpl.CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesImpl.readMappings(buffer); + + 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/RegistrySyncMixinPlugin.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/RegistrySyncMixinPlugin.java new file mode 100644 index 00000000..6458a1b6 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/RegistrySyncMixinPlugin.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 RegistrySyncMixinPlugin 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.registry.sync.impl.mixin.common.CrudeIncrementalIntIdentityHashMapMixinNew".equals(mixinClassName)) { + return NEW_CRUDE_INCREMENTAL_INT_IDENTITY_HASH_MAP_IMPLEMENTATION; + } + if ("net.ornithemc.osl.registry.sync.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/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..ad2ef0e0 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,126 @@ +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; + +@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); + SyncedRegistriesImpl.readMappings(nbt); + 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(); + SyncedRegistriesImpl.writeMappings(nbt); + + try { + 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/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..c18509cb --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java @@ -0,0 +1,27 @@ +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 net.minecraft.util.Id2ObjectBiMap; + +import net.ornithemc.osl.registries.impl.registry.Clearable; + +@Mixin(Id2ObjectBiMap.class) +public class Id2ObjectBiMapMixin implements Clearable { + + @Shadow @Final + private List values; + @Shadow @Final + private IdentityHashMap ids; + + @Override + public void osl$registries$clear() { + this.values.clear(); + this.ids.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..5e78af1f --- /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(V 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..91b1959e --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,37 @@ +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.registry.SyncedRegistriesImpl; + +@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, SyncedRegistriesImpl.CHANNEL, SyncedRegistriesImpl::writeMappings); + } + } +} 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/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..804a8fec --- /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(V 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/SyncedRegistriesImpl.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java new file mode 100644 index 00000000..0dd5676f --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java @@ -0,0 +1,188 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; + +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.networking.api.PacketBuffer; +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.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMapper; +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.SerializableRegistryMappings; + +public final class SyncedRegistriesImpl { + + public static final NamespacedIdentifier CHANNEL = Constants.OSL_REGISTRY_SYNC_CHANNEL; + + private static final Map REGISTRY_MAPPINGS = new LinkedHashMap<>(); + private static final Map REGISTRY_MAPPERS = new LinkedHashMap<>(); + private static final Map ID_FIXERS = new LinkedHashMap<>(); + + private static final String FORMAT_NBT_KEY = "format"; + private static final int FORMAT = 1; + + public static void registerMapper(ResourceKey> registry) { + registerMapper(registry, RegistryMapper.of(Registries.get(registry))); + } + + public static void registerMapper(ResourceKey> registry, IdMapper mapper) { + NamespacedIdentifier identifier = registry.identifier(); + + if (Registries.get(registry) == null) { + throw new IllegalArgumentException("cannot register registry mapper: unknown registry: " + identifier); + } else { + REGISTRY_MAPPERS.put(identifier, mapper); + } + } + + public static void registerFixer(NamespacedIdentifier identifier, IdFixer fixer) { + if (ID_FIXERS.containsKey(identifier)) { + throw new IllegalArgumentException("duplicate ID fixer " + identifier); + } else { + ID_FIXERS.put(identifier, fixer); + } + } + + public static void init() { + for (Registry registry : Registries.REGISTRY) { + if (registry instanceof ClearableRegistry) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = SerializableRegistryMappings.of(registry); + + REGISTRY_MAPPINGS.put(identifier, mappings); + } + } + + for (NamespacedIdentifier identifier : REGISTRY_MAPPERS.keySet()) { + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings == null) { + throw new IllegalStateException("Illegal registry mapper for unsynced registry " + identifier); + } else { + mappings.reset(); + } + } + } + + public static void readMappings(PacketBuffer buffer) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > 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(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings != null) { + try { + mappings.read(buffer, RegistryMappingSource.REMOTE_SERVER); + } 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 writeMappings(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(FORMAT); + buffer.writeVarInt(REGISTRY_MAPPINGS.size()); + + for (Map.Entry e : REGISTRY_MAPPINGS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + SerializableRegistryMappings mappings = e.getValue(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer); + } + } + + public static void readMappings(NbtCompound nbt) throws RegistryMappingException { + int format = nbt.getInt(FORMAT_NBT_KEY); + + if (format > FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + for (String nbtKey : nbt.getKeys()) { + NbtCompound mappingsNbt = nbt.getCompound(nbtKey); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(nbtKey); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings != null) { + try { + mappings.read(mappingsNbt, RegistryMappingSource.WORLD_SAVE); + } 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 writeMappings(NbtCompound nbt) { + nbt.putInt(FORMAT_NBT_KEY, FORMAT); + + for (Map.Entry e : REGISTRY_MAPPINGS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + SerializableRegistryMappings mappings = e.getValue(); + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt); + nbt.put(identifier.toString(), mappingsNbt); + } + } + + public static void resetMappings() { + for (SerializableRegistryMappings mappings : REGISTRY_MAPPINGS.values()) { + mappings.reset(); + } + } + + public static void applyMappings() { + for (Map.Entry e : REGISTRY_MAPPERS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + IdMapper mapper = e.getValue(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + mapper.apply(mappings); + } + + applyFixers(); + } + + public static void undoMappings() { + for (Map.Entry e : REGISTRY_MAPPERS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + IdMapper mapper = e.getValue(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + mapper.undo(mappings); + } + + applyFixers(); + } + + public static void applyFixers() { + for (IdFixer fixer : ID_FIXERS.values()) { + fixer.apply(); + } + } +} 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..d9dedd42 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,15 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.IdRegistry; + +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 final class VanillaRegistries { + + public static WritableRegistry register(ResourceKey> key, IdRegistry registry) { + return RegistriesImpl.register(key, WrappedIdRegistry.withIdentifierKey(key, registry), () -> { }); + } +} 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..a5d63bbd --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java @@ -0,0 +1,176 @@ +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.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 abstract class WrappedIdRegistry implements ClearableRegistry { + + public static WrappedIdRegistry withStringKey(ResourceKey> key, IdRegistry registry) { + return new WrappedIdRegistry.StringKey<>(key.identifier(), registry); + } + + public static WrappedIdRegistry withIdentifierKey(ResourceKey> key, IdRegistry registry) { + return new WrappedIdRegistry.IdentifierKey<>(key.identifier(), registry); + } + + private final NamespacedIdentifier identifier; + private final IdRegistry registry; + + private int nextId; + private boolean frozen; + + private WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + abstract NamespacedIdentifier serializeKey(K key); + + abstract K deserializeKey(NamespacedIdentifier identifier); + + private ResourceKey resourceKey(NamespacedIdentifier identifier) { + return ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, K key, V value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public void register(ResourceKey key, V value) { + this.register(this.nextId, key, value); + } + + @Override + public void register(int id, ResourceKey key, V value) { + this.registry.register(id, this.deserializeKey(key.identifier()), value); + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } + + @Override + public V get(int id) { + return this.registry.get(id); + } + + @Override + public V get(ResourceKey key) { + return this.registry.get(this.deserializeKey(key.identifier())); + } + + @Override + public V get(NamespacedIdentifier identifier) { + return this.registry.get(this.deserializeKey(identifier)); + } + + @Override + public boolean has(V value) { + return this.registry.osl$registries$has(value); + } + + @Override + public int getId(V value) { + return this.registry.getId(value); + } + + @Override + public ResourceKey getKey(V value) { + return this.resourceKey(this.serializeKey(this.registry.getKey(value))); + } + + @Override + public NamespacedIdentifier getIdentifier(V 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 Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public Iterator iterator() { + return this.registry.iterator(); + } + + @Override + public void clear() { + this.registry.osl$registries$clear(); + + this.nextId = 0; + this.frozen = false; + } + + public interface RegisterCallback { + + void valueRegistered(int id, K key, V value); + + } + + private static class StringKey extends WrappedIdRegistry { + + private StringKey(NamespacedIdentifier identifier, IdRegistry registry) { + super(identifier, registry); + } + + @Override + NamespacedIdentifier serializeKey(String key) { + return NamespacedIdentifiers.parse(key); + } + + @Override + String deserializeKey(NamespacedIdentifier identifier) { + return identifier.toString(); + } + } + + private static class IdentifierKey extends WrappedIdRegistry { + + private IdentifierKey(NamespacedIdentifier identifier, IdRegistry registry) { + super(identifier, registry); + } + + @Override + NamespacedIdentifier serializeKey(Identifier key) { + return NamespacedIdentifiers.from(key.getNamespace(), key.getPath()); + } + + @Override + Identifier deserializeKey(NamespacedIdentifier identifier) { + return new Identifier(identifier.namespace(), identifier.identifier()); + } + } +} diff --git a/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java new file mode 100644 index 00000000..c44b8c9a --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java @@ -0,0 +1,62 @@ +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.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; + +public final class SerializableRegistryMappings extends MemoryRegistryMappings { + + public static SerializableRegistryMappings of(Registry registry) { + return new SerializableRegistryMappings(registry); + } + + private SerializableRegistryMappings(Registry registry) { + super(registry); + } + + public void read(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + this.mappings.put(identifier, id); + } + + this.build(source); + } + + public void write(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(this.mappings.size()); + + for (Object2IntMap.Entry mapping : this.mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public void read(NbtCompound nbt, RegistryMappingSource source) throws RegistryMappingException { + for (String key : nbt.getKeys()) { + this.mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + + this.build(source); + } + + public void write(NbtCompound nbt) { + for (Object2IntMap.Entry mapping : this.mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } +} 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..54cd9bae --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/src/main/resources/fabric.mod.json @@ -0,0 +1,40 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc14w27a-mc17w46a", + "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ], + "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..f13b21d2 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/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 \ 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..fb609a17 --- /dev/null +++ b/libraries/registries/registries-mc14w27a-mc17w46a/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.BootstrapMixin", + "common.CrudeIncrementalIntIdentityHashMapMixinNew", + "common.CrudeIncrementalIntIdentityHashMapMixinOld", + "common.Id2ObjectBiMapMixin", + "common.IdRegistryMixin", + "common.PlayerManagerMixin" + ], + "client": [ + ], + "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/SyncedRegistries.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/api/registry/SyncedRegistries.java new file mode 100644 index 00000000..20ab0c61 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/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 registerMapper(ResourceKey> registry) { + SyncedRegistriesImpl.registerMapper(registry); + } + + public static void registerMapper(ResourceKey> registry, IdMapper mapper) { + SyncedRegistriesImpl.registerMapper(registry, mapper); + } + + public static void registerFixer(NamespacedIdentifier key, IdFixer fixer) { + SyncedRegistriesImpl.registerFixer(key, fixer); + } +} 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..06315d43 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,50 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.ModInitializer; +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.lifecycle.api.server.MinecraftServerEvents; +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; + +public final class RegistriesEntrypoint implements ModInitializer, ClientModInitializer { + + @Override + public void init() { + MinecraftServerEvents.STOP.register(server -> { + SyncedRegistriesImpl.undoMappings(); + }); + } + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(SyncedRegistriesImpl.CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesImpl.readMappings(buffer); + + 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/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..ad2ef0e0 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/AlphaWorldStorageMixin.java @@ -0,0 +1,126 @@ +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; + +@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); + SyncedRegistriesImpl.readMappings(nbt); + 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(); + SyncedRegistriesImpl.writeMappings(nbt); + + try { + 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/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..c18509cb --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/Id2ObjectBiMapMixin.java @@ -0,0 +1,27 @@ +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 net.minecraft.util.Id2ObjectBiMap; + +import net.ornithemc.osl.registries.impl.registry.Clearable; + +@Mixin(Id2ObjectBiMap.class) +public class Id2ObjectBiMapMixin implements Clearable { + + @Shadow @Final + private List values; + @Shadow @Final + private IdentityHashMap ids; + + @Override + public void osl$registries$clear() { + this.values.clear(); + this.ids.clear(); + } +} 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..5e78af1f --- /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(V 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..91b1959e --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/PlayerManagerMixin.java @@ -0,0 +1,37 @@ +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.registry.SyncedRegistriesImpl; + +@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, SyncedRegistriesImpl.CHANNEL, SyncedRegistriesImpl::writeMappings); + } + } +} 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/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..804a8fec --- /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(V 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/SyncedRegistriesImpl.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java new file mode 100644 index 00000000..0dd5676f --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java @@ -0,0 +1,188 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; + +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.networking.api.PacketBuffer; +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.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMapper; +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.SerializableRegistryMappings; + +public final class SyncedRegistriesImpl { + + public static final NamespacedIdentifier CHANNEL = Constants.OSL_REGISTRY_SYNC_CHANNEL; + + private static final Map REGISTRY_MAPPINGS = new LinkedHashMap<>(); + private static final Map REGISTRY_MAPPERS = new LinkedHashMap<>(); + private static final Map ID_FIXERS = new LinkedHashMap<>(); + + private static final String FORMAT_NBT_KEY = "format"; + private static final int FORMAT = 1; + + public static void registerMapper(ResourceKey> registry) { + registerMapper(registry, RegistryMapper.of(Registries.get(registry))); + } + + public static void registerMapper(ResourceKey> registry, IdMapper mapper) { + NamespacedIdentifier identifier = registry.identifier(); + + if (Registries.get(registry) == null) { + throw new IllegalArgumentException("cannot register registry mapper: unknown registry: " + identifier); + } else { + REGISTRY_MAPPERS.put(identifier, mapper); + } + } + + public static void registerFixer(NamespacedIdentifier identifier, IdFixer fixer) { + if (ID_FIXERS.containsKey(identifier)) { + throw new IllegalArgumentException("duplicate ID fixer " + identifier); + } else { + ID_FIXERS.put(identifier, fixer); + } + } + + public static void init() { + for (Registry registry : Registries.REGISTRY) { + if (registry instanceof ClearableRegistry) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = SerializableRegistryMappings.of(registry); + + REGISTRY_MAPPINGS.put(identifier, mappings); + } + } + + for (NamespacedIdentifier identifier : REGISTRY_MAPPERS.keySet()) { + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings == null) { + throw new IllegalStateException("Illegal registry mapper for unsynced registry " + identifier); + } else { + mappings.reset(); + } + } + } + + public static void readMappings(PacketBuffer buffer) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > 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(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings != null) { + try { + mappings.read(buffer, RegistryMappingSource.REMOTE_SERVER); + } 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 writeMappings(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(FORMAT); + buffer.writeVarInt(REGISTRY_MAPPINGS.size()); + + for (Map.Entry e : REGISTRY_MAPPINGS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + SerializableRegistryMappings mappings = e.getValue(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer); + } + } + + public static void readMappings(NbtCompound nbt) throws RegistryMappingException { + int format = nbt.getInt(FORMAT_NBT_KEY); + + if (format > FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + for (String nbtKey : nbt.getKeys()) { + NbtCompound mappingsNbt = nbt.getCompound(nbtKey); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(nbtKey); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings != null) { + try { + mappings.read(mappingsNbt, RegistryMappingSource.WORLD_SAVE); + } 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 writeMappings(NbtCompound nbt) { + nbt.putInt(FORMAT_NBT_KEY, FORMAT); + + for (Map.Entry e : REGISTRY_MAPPINGS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + SerializableRegistryMappings mappings = e.getValue(); + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt); + nbt.put(identifier.toString(), mappingsNbt); + } + } + + public static void resetMappings() { + for (SerializableRegistryMappings mappings : REGISTRY_MAPPINGS.values()) { + mappings.reset(); + } + } + + public static void applyMappings() { + for (Map.Entry e : REGISTRY_MAPPERS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + IdMapper mapper = e.getValue(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + mapper.apply(mappings); + } + + applyFixers(); + } + + public static void undoMappings() { + for (Map.Entry e : REGISTRY_MAPPERS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + IdMapper mapper = e.getValue(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + mapper.undo(mappings); + } + + applyFixers(); + } + + public static void applyFixers() { + for (IdFixer fixer : ID_FIXERS.values()) { + fixer.apply(); + } + } +} 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..d9dedd42 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,15 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.resource.Identifier; +import net.minecraft.util.registry.IdRegistry; + +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 final class VanillaRegistries { + + public static WritableRegistry register(ResourceKey> key, IdRegistry registry) { + return RegistriesImpl.register(key, WrappedIdRegistry.withIdentifierKey(key, registry), () -> { }); + } +} 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..dd9d041e --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/WrappedIdRegistry.java @@ -0,0 +1,176 @@ +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.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 abstract class WrappedIdRegistry implements ClearableRegistry { + + public static WrappedIdRegistry withStringKey(ResourceKey> key, IdRegistry registry) { + return new WrappedIdRegistry.StringKey<>(key.identifier(), registry); + } + + public static WrappedIdRegistry withIdentifierKey(ResourceKey> key, IdRegistry registry) { + return new WrappedIdRegistry.IdentifierKey<>(key.identifier(), registry); + } + + private final NamespacedIdentifier identifier; + private final IdRegistry registry; + + private int nextId; + private boolean frozen; + + private WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + abstract NamespacedIdentifier serializeKey(K key); + + abstract K deserializeKey(NamespacedIdentifier identifier); + + private ResourceKey resourceKey(NamespacedIdentifier identifier) { + return ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, K key, V value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public void register(ResourceKey key, V value) { + this.register(this.nextId, key, value); + } + + @Override + public void register(int id, ResourceKey key, V value) { + this.registry.register(id, this.deserializeKey(key.identifier()), value); + } + + @Override + public NamespacedIdentifier identifier() { + return this.identifier; + } + + @Override + public V get(int id) { + return this.registry.get(id); + } + + @Override + public V get(ResourceKey key) { + return this.registry.get(this.deserializeKey(key.identifier())); + } + + @Override + public V get(NamespacedIdentifier identifier) { + return this.registry.get(this.deserializeKey(identifier)); + } + + @Override + public boolean has(V value) { + return this.registry.osl$registries$has(value); + } + + @Override + public int getId(V value) { + return this.registry.getId(value); + } + + @Override + public ResourceKey getKey(V value) { + return this.resourceKey(this.serializeKey(this.registry.getKey(value))); + } + + @Override + public NamespacedIdentifier getIdentifier(V 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 Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public Iterator iterator() { + return this.registry.iterator(); + } + + @Override + public void clear() { + this.registry.osl$registries$clear(); + + this.nextId = 0; + this.frozen = false; + } + + public interface RegisterCallback { + + void valueRegistered(int id, K key, V value); + + } + + private static class StringKey extends WrappedIdRegistry { + + private StringKey(NamespacedIdentifier identifier, IdRegistry registry) { + super(identifier, registry); + } + + @Override + NamespacedIdentifier serializeKey(String key) { + return NamespacedIdentifiers.parse(key); + } + + @Override + String deserializeKey(NamespacedIdentifier identifier) { + return identifier.toString(); + } + } + + private static class IdentifierKey extends WrappedIdRegistry { + + private IdentifierKey(NamespacedIdentifier identifier, IdRegistry registry) { + super(identifier, registry); + } + + @Override + NamespacedIdentifier serializeKey(Identifier key) { + return NamespacedIdentifiers.from(key.getNamespace(), key.getPath()); + } + + @Override + Identifier deserializeKey(NamespacedIdentifier identifier) { + return new Identifier(identifier.namespace(), identifier.identifier()); + } + } +} diff --git a/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java new file mode 100644 index 00000000..c44b8c9a --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java @@ -0,0 +1,62 @@ +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.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; + +public final class SerializableRegistryMappings extends MemoryRegistryMappings { + + public static SerializableRegistryMappings of(Registry registry) { + return new SerializableRegistryMappings(registry); + } + + private SerializableRegistryMappings(Registry registry) { + super(registry); + } + + public void read(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + this.mappings.put(identifier, id); + } + + this.build(source); + } + + public void write(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(this.mappings.size()); + + for (Object2IntMap.Entry mapping : this.mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public void read(NbtCompound nbt, RegistryMappingSource source) throws RegistryMappingException { + for (String key : nbt.getKeys()) { + this.mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + + this.build(source); + } + + public void write(NbtCompound nbt) { + for (Object2IntMap.Entry mapping : this.mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } +} 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..86730855 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/fabric.mod.json @@ -0,0 +1,40 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc17w47a-mc18w31a", + "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ], + "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..f13b21d2 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/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 \ 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..522d14d2 --- /dev/null +++ b/libraries/registries/registries-mc17w47a-mc18w31a/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,21 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.BootstrapMixin", + "common.CrudeIncrementalIntIdentityHashMapMixin", + "common.Id2ObjectBiMapMixin", + "common.IdRegistryMixin", + "common.PlayerManagerMixin" + ], + "client": [ + ], + "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/SyncedRegistries.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/api/registry/SyncedRegistries.java new file mode 100644 index 00000000..20ab0c61 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/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 registerMapper(ResourceKey> registry) { + SyncedRegistriesImpl.registerMapper(registry); + } + + public static void registerMapper(ResourceKey> registry, IdMapper mapper) { + SyncedRegistriesImpl.registerMapper(registry, mapper); + } + + public static void registerFixer(NamespacedIdentifier key, IdFixer fixer) { + SyncedRegistriesImpl.registerFixer(key, fixer); + } +} 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..06315d43 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,50 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.ModInitializer; +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.lifecycle.api.server.MinecraftServerEvents; +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; + +public final class RegistriesEntrypoint implements ModInitializer, ClientModInitializer { + + @Override + public void init() { + MinecraftServerEvents.STOP.register(server -> { + SyncedRegistriesImpl.undoMappings(); + }); + } + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(SyncedRegistriesImpl.CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesImpl.readMappings(buffer); + + 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/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..ad2ef0e0 --- /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,126 @@ +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; + +@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); + SyncedRegistriesImpl.readMappings(nbt); + 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(); + SyncedRegistriesImpl.writeMappings(nbt); + + try { + 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/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..c18509cb --- /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,27 @@ +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 net.minecraft.util.Id2ObjectBiMap; + +import net.ornithemc.osl.registries.impl.registry.Clearable; + +@Mixin(Id2ObjectBiMap.class) +public class Id2ObjectBiMapMixin implements Clearable { + + @Shadow @Final + private List values; + @Shadow @Final + private IdentityHashMap ids; + + @Override + public void osl$registries$clear() { + this.values.clear(); + this.ids.clear(); + } +} 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..15b9c0c3 --- /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(T 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..91b1959e --- /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,37 @@ +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.registry.SyncedRegistriesImpl; + +@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, SyncedRegistriesImpl.CHANNEL, SyncedRegistriesImpl::writeMappings); + } + } +} 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..899032a5 --- /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,42 @@ +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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.util.registry.IdRegistry; +import net.minecraft.util.registry.Registry; + +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.VanillaRegistries; + +@Mixin(Registry.class) +public interface RegistryMixin { + + @Inject( + method = "register(Ljava/lang/String;Lnet/minecraft/util/registry/Registry;)Lnet/minecraft/util/registry/Registry;", + at = @At( + value = "RETURN" + ) + ) + static void osl$registries$register(String key, Registry registry, CallbackInfoReturnable> cir) { + if (registry instanceof IdRegistry) { + VanillaRegistries.register(RegistryKeys.from(key), (IdRegistry) registry); + } + } + + @Inject( + method = "init", + at = @At( + value = "TAIL" + ) + ) + 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/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..062a303e --- /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(T 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/SyncedRegistriesImpl.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java new file mode 100644 index 00000000..0dd5676f --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java @@ -0,0 +1,188 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; + +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.networking.api.PacketBuffer; +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.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMapper; +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.SerializableRegistryMappings; + +public final class SyncedRegistriesImpl { + + public static final NamespacedIdentifier CHANNEL = Constants.OSL_REGISTRY_SYNC_CHANNEL; + + private static final Map REGISTRY_MAPPINGS = new LinkedHashMap<>(); + private static final Map REGISTRY_MAPPERS = new LinkedHashMap<>(); + private static final Map ID_FIXERS = new LinkedHashMap<>(); + + private static final String FORMAT_NBT_KEY = "format"; + private static final int FORMAT = 1; + + public static void registerMapper(ResourceKey> registry) { + registerMapper(registry, RegistryMapper.of(Registries.get(registry))); + } + + public static void registerMapper(ResourceKey> registry, IdMapper mapper) { + NamespacedIdentifier identifier = registry.identifier(); + + if (Registries.get(registry) == null) { + throw new IllegalArgumentException("cannot register registry mapper: unknown registry: " + identifier); + } else { + REGISTRY_MAPPERS.put(identifier, mapper); + } + } + + public static void registerFixer(NamespacedIdentifier identifier, IdFixer fixer) { + if (ID_FIXERS.containsKey(identifier)) { + throw new IllegalArgumentException("duplicate ID fixer " + identifier); + } else { + ID_FIXERS.put(identifier, fixer); + } + } + + public static void init() { + for (Registry registry : Registries.REGISTRY) { + if (registry instanceof ClearableRegistry) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = SerializableRegistryMappings.of(registry); + + REGISTRY_MAPPINGS.put(identifier, mappings); + } + } + + for (NamespacedIdentifier identifier : REGISTRY_MAPPERS.keySet()) { + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings == null) { + throw new IllegalStateException("Illegal registry mapper for unsynced registry " + identifier); + } else { + mappings.reset(); + } + } + } + + public static void readMappings(PacketBuffer buffer) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > 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(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings != null) { + try { + mappings.read(buffer, RegistryMappingSource.REMOTE_SERVER); + } 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 writeMappings(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(FORMAT); + buffer.writeVarInt(REGISTRY_MAPPINGS.size()); + + for (Map.Entry e : REGISTRY_MAPPINGS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + SerializableRegistryMappings mappings = e.getValue(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer); + } + } + + public static void readMappings(NbtCompound nbt) throws RegistryMappingException { + int format = nbt.getInt(FORMAT_NBT_KEY); + + if (format > FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + for (String nbtKey : nbt.getKeys()) { + NbtCompound mappingsNbt = nbt.getCompound(nbtKey); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(nbtKey); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings != null) { + try { + mappings.read(mappingsNbt, RegistryMappingSource.WORLD_SAVE); + } 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 writeMappings(NbtCompound nbt) { + nbt.putInt(FORMAT_NBT_KEY, FORMAT); + + for (Map.Entry e : REGISTRY_MAPPINGS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + SerializableRegistryMappings mappings = e.getValue(); + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt); + nbt.put(identifier.toString(), mappingsNbt); + } + } + + public static void resetMappings() { + for (SerializableRegistryMappings mappings : REGISTRY_MAPPINGS.values()) { + mappings.reset(); + } + } + + public static void applyMappings() { + for (Map.Entry e : REGISTRY_MAPPERS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + IdMapper mapper = e.getValue(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + mapper.apply(mappings); + } + + applyFixers(); + } + + public static void undoMappings() { + for (Map.Entry e : REGISTRY_MAPPERS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + IdMapper mapper = e.getValue(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + mapper.undo(mappings); + } + + applyFixers(); + } + + public static void applyFixers() { + for (IdFixer fixer : ID_FIXERS.values()) { + fixer.apply(); + } + } +} 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..17520775 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.IdRegistry; + +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 final class VanillaRegistries { + + public static WritableRegistry register(ResourceKey> key, IdRegistry registry) { + return RegistriesImpl.register(key, WrappedIdRegistry.of(key, registry), () -> { }); + } +} 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..5cda4fad --- /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.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); + } + + private final NamespacedIdentifier identifier; + private final IdRegistry registry; + + private int nextId; + private boolean frozen; + + private WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + private NamespacedIdentifier serializeKey(Identifier key) { + return NamespacedIdentifiers.from(key.getNamespace(), key.getPath()); + } + + private Identifier deserializeKey(NamespacedIdentifier identifier) { + return new Identifier(identifier.namespace(), identifier.identifier()); + } + + private ResourceKey resourceKey(NamespacedIdentifier identifier) { + return ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, Identifier key, T value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public void register(ResourceKey key, T value) { + this.register(this.nextId, key, value); + } + + @Override + public void register(int id, ResourceKey key, T value) { + this.registry.register(id, this.deserializeKey(key.identifier()), 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 Registry freeze() { + if (!this.frozen) { + this.frozen = true; + } + + return this; + } + + @Override + public Iterator iterator() { + return this.registry.iterator(); + } + + @Override + public void clear() { + this.registry.osl$registries$clear(); + + this.nextId = 0; + this.frozen = false; + } + + public interface RegisterCallback { + + void valueRegistered(int id, Identifier key, T value); + + } +} diff --git a/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java new file mode 100644 index 00000000..c44b8c9a --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java @@ -0,0 +1,62 @@ +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.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; + +public final class SerializableRegistryMappings extends MemoryRegistryMappings { + + public static SerializableRegistryMappings of(Registry registry) { + return new SerializableRegistryMappings(registry); + } + + private SerializableRegistryMappings(Registry registry) { + super(registry); + } + + public void read(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + this.mappings.put(identifier, id); + } + + this.build(source); + } + + public void write(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(this.mappings.size()); + + for (Object2IntMap.Entry mapping : this.mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public void read(NbtCompound nbt, RegistryMappingSource source) throws RegistryMappingException { + for (String key : nbt.getKeys()) { + this.mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + + this.build(source); + } + + public void write(NbtCompound nbt) { + for (Object2IntMap.Entry mapping : this.mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } +} 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..bf7040f9 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/fabric.mod.json @@ -0,0 +1,40 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc18w32a-mc1.13.2", + "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ], + "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..b877af58 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/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-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..a435bc85 --- /dev/null +++ b/libraries/registries/registries-mc18w32a-mc1.13.2/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,21 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.CrudeIncrementalIntIdentityHashMapMixin", + "common.Id2ObjectBiMapMixin", + "common.IdRegistryMixin", + "common.PlayerManagerMixin", + "common.RegistryMixin" + ], + "client": [ + ], + "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/SyncedRegistries.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/api/registry/SyncedRegistries.java new file mode 100644 index 00000000..20ab0c61 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/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 registerMapper(ResourceKey> registry) { + SyncedRegistriesImpl.registerMapper(registry); + } + + public static void registerMapper(ResourceKey> registry, IdMapper mapper) { + SyncedRegistriesImpl.registerMapper(registry, mapper); + } + + public static void registerFixer(NamespacedIdentifier key, IdFixer fixer) { + SyncedRegistriesImpl.registerFixer(key, fixer); + } +} 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..06315d43 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/RegistriesEntrypoint.java @@ -0,0 +1,50 @@ +package net.ornithemc.osl.registries.impl; + +import net.minecraft.text.LiteralText; + +import net.ornithemc.osl.entrypoints.api.ModInitializer; +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.lifecycle.api.server.MinecraftServerEvents; +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; + +public final class RegistriesEntrypoint implements ModInitializer, ClientModInitializer { + + @Override + public void init() { + MinecraftServerEvents.STOP.register(server -> { + SyncedRegistriesImpl.undoMappings(); + }); + } + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(SyncedRegistriesImpl.CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesImpl.readMappings(buffer); + + 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/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..ad2ef0e0 --- /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,126 @@ +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; + +@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); + SyncedRegistriesImpl.readMappings(nbt); + 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(); + SyncedRegistriesImpl.writeMappings(nbt); + + try { + 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/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/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..c18509cb --- /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,27 @@ +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 net.minecraft.util.Id2ObjectBiMap; + +import net.ornithemc.osl.registries.impl.registry.Clearable; + +@Mixin(Id2ObjectBiMap.class) +public class Id2ObjectBiMapMixin implements Clearable { + + @Shadow @Final + private List values; + @Shadow @Final + private IdentityHashMap ids; + + @Override + public void osl$registries$clear() { + this.values.clear(); + this.ids.clear(); + } +} 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..799ecca4 --- /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.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 = "m_26252208", + 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(T 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..91b1959e --- /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,37 @@ +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.registry.SyncedRegistriesImpl; + +@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, SyncedRegistriesImpl.CHANNEL, SyncedRegistriesImpl::writeMappings); + } + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/RegistryMixin.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/RegistryMixin.java new file mode 100644 index 00000000..6aa8aa2a --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/mixin/common/RegistryMixin.java @@ -0,0 +1,42 @@ +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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.util.registry.IdRegistry; +import net.minecraft.util.registry.Registry; + +import net.ornithemc.osl.registries.api.registry.RegistryKeys; +import net.ornithemc.osl.registries.impl.registry.RegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.SyncedRegistriesImpl; +import net.ornithemc.osl.registries.impl.registry.VanillaRegistries; + +@Mixin(Registry.class) +public class RegistryMixin { + + @Inject( + method = "register(Ljava/lang/String;Lnet/minecraft/util/registry/Registry;)Lnet/minecraft/util/registry/Registry;", + at = @At( + value = "RETURN" + ) + ) + private static void osl$registries$register(String key, Registry registry, CallbackInfoReturnable> cir) { + if (registry instanceof IdRegistry) { + VanillaRegistries.register(RegistryKeys.from(key), (IdRegistry) registry); + } + } + + @Inject( + method = "init", + at = @At( + value = "TAIL" + ) + ) + private static void osl$registries$initRegistries(CallbackInfo ci) { + RegistriesImpl.init(); + SyncedRegistriesImpl.init(); + } +} 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/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..062a303e --- /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(T 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/SyncedRegistriesImpl.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java new file mode 100644 index 00000000..0dd5676f --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java @@ -0,0 +1,188 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; + +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.networking.api.PacketBuffer; +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.impl.Constants; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMapper; +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.SerializableRegistryMappings; + +public final class SyncedRegistriesImpl { + + public static final NamespacedIdentifier CHANNEL = Constants.OSL_REGISTRY_SYNC_CHANNEL; + + private static final Map REGISTRY_MAPPINGS = new LinkedHashMap<>(); + private static final Map REGISTRY_MAPPERS = new LinkedHashMap<>(); + private static final Map ID_FIXERS = new LinkedHashMap<>(); + + private static final String FORMAT_NBT_KEY = "format"; + private static final int FORMAT = 1; + + public static void registerMapper(ResourceKey> registry) { + registerMapper(registry, RegistryMapper.of(Registries.get(registry))); + } + + public static void registerMapper(ResourceKey> registry, IdMapper mapper) { + NamespacedIdentifier identifier = registry.identifier(); + + if (Registries.get(registry) == null) { + throw new IllegalArgumentException("cannot register registry mapper: unknown registry: " + identifier); + } else { + REGISTRY_MAPPERS.put(identifier, mapper); + } + } + + public static void registerFixer(NamespacedIdentifier identifier, IdFixer fixer) { + if (ID_FIXERS.containsKey(identifier)) { + throw new IllegalArgumentException("duplicate ID fixer " + identifier); + } else { + ID_FIXERS.put(identifier, fixer); + } + } + + public static void init() { + for (Registry registry : Registries.REGISTRY) { + if (registry instanceof ClearableRegistry) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = SerializableRegistryMappings.of(registry); + + REGISTRY_MAPPINGS.put(identifier, mappings); + } + } + + for (NamespacedIdentifier identifier : REGISTRY_MAPPERS.keySet()) { + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings == null) { + throw new IllegalStateException("Illegal registry mapper for unsynced registry " + identifier); + } else { + mappings.reset(); + } + } + } + + public static void readMappings(PacketBuffer buffer) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > 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(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings != null) { + try { + mappings.read(buffer, RegistryMappingSource.REMOTE_SERVER); + } 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 writeMappings(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(FORMAT); + buffer.writeVarInt(REGISTRY_MAPPINGS.size()); + + for (Map.Entry e : REGISTRY_MAPPINGS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + SerializableRegistryMappings mappings = e.getValue(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer); + } + } + + public static void readMappings(NbtCompound nbt) throws RegistryMappingException { + int format = nbt.getInt(FORMAT_NBT_KEY); + + if (format > FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + for (String nbtKey : nbt.getKeys()) { + NbtCompound mappingsNbt = nbt.getCompound(nbtKey); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(nbtKey); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings != null) { + try { + mappings.read(mappingsNbt, RegistryMappingSource.WORLD_SAVE); + } 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 writeMappings(NbtCompound nbt) { + nbt.putInt(FORMAT_NBT_KEY, FORMAT); + + for (Map.Entry e : REGISTRY_MAPPINGS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + SerializableRegistryMappings mappings = e.getValue(); + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt); + nbt.put(identifier.toString(), mappingsNbt); + } + } + + public static void resetMappings() { + for (SerializableRegistryMappings mappings : REGISTRY_MAPPINGS.values()) { + mappings.reset(); + } + } + + public static void applyMappings() { + for (Map.Entry e : REGISTRY_MAPPERS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + IdMapper mapper = e.getValue(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + mapper.apply(mappings); + } + + applyFixers(); + } + + public static void undoMappings() { + for (Map.Entry e : REGISTRY_MAPPERS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + IdMapper mapper = e.getValue(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + mapper.undo(mappings); + } + + applyFixers(); + } + + public static void applyFixers() { + for (IdFixer fixer : ID_FIXERS.values()) { + fixer.apply(); + } + } +} 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..17520775 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/VanillaRegistries.java @@ -0,0 +1,14 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.minecraft.util.registry.IdRegistry; + +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 final class VanillaRegistries { + + public static WritableRegistry register(ResourceKey> key, IdRegistry registry) { + return RegistriesImpl.register(key, WrappedIdRegistry.of(key, registry), () -> { }); + } +} 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..09052495 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/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.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); + } + + private final NamespacedIdentifier identifier; + private final IdRegistry registry; + + private int nextId; + private boolean frozen; + + private WrappedIdRegistry(NamespacedIdentifier identifier, IdRegistry registry) { + this.identifier = identifier; + this.registry = registry; + + this.registry.osl$registries$setCallback(this::valueRegistered); + } + + private NamespacedIdentifier serializeKey(Identifier key) { + return NamespacedIdentifiers.from(key.getNamespace(), key.getPath()); + } + + private Identifier deserializeKey(NamespacedIdentifier identifier) { + return new Identifier(identifier.namespace(), identifier.identifier()); + } + + private ResourceKey resourceKey(NamespacedIdentifier identifier) { + return ResourceKeys.from(this.identifier, identifier); + } + + private void valueRegistered(int id, Identifier key, T value) { + if (this.frozen) { + throw new IllegalStateException("registry is frozen!"); + } + + this.nextId = Math.max(this.nextId, id + 1); + } + + @Override + public void register(ResourceKey key, T value) { + this.register(this.nextId, key, value); + } + + @Override + public void register(int id, ResourceKey key, T value) { + this.registry.m_26252208(id, this.deserializeKey(key.identifier()), 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.getOrDefault(this.deserializeKey(key.identifier())); + } + + @Override + public T get(NamespacedIdentifier identifier) { + return this.registry.getOrDefault(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, T value); + + } +} diff --git a/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java new file mode 100644 index 00000000..c44b8c9a --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java @@ -0,0 +1,62 @@ +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.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; + +public final class SerializableRegistryMappings extends MemoryRegistryMappings { + + public static SerializableRegistryMappings of(Registry registry) { + return new SerializableRegistryMappings(registry); + } + + private SerializableRegistryMappings(Registry registry) { + super(registry); + } + + public void read(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + this.mappings.put(identifier, id); + } + + this.build(source); + } + + public void write(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(this.mappings.size()); + + for (Object2IntMap.Entry mapping : this.mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public void read(NbtCompound nbt, RegistryMappingSource source) throws RegistryMappingException { + for (String key : nbt.getKeys()) { + this.mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + + this.build(source); + } + + public void write(NbtCompound nbt) { + for (Object2IntMap.Entry mapping : this.mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } +} 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..206614dc --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/resources/fabric.mod.json @@ -0,0 +1,40 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mc18w43a-mc1.14.4", + "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ], + "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..e1f622f7 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/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-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..a435bc85 --- /dev/null +++ b/libraries/registries/registries-mc18w43a-mc1.14.4/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,21 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.CrudeIncrementalIntIdentityHashMapMixin", + "common.Id2ObjectBiMapMixin", + "common.IdRegistryMixin", + "common.PlayerManagerMixin", + "common.RegistryMixin" + ], + "client": [ + ], + "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/api/registry/SyncedRegistries.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/api/registry/SyncedRegistries.java new file mode 100644 index 00000000..20ab0c61 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/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 registerMapper(ResourceKey> registry) { + SyncedRegistriesImpl.registerMapper(registry); + } + + public static void registerMapper(ResourceKey> registry, IdMapper mapper) { + SyncedRegistriesImpl.registerMapper(registry, mapper); + } + + public static void registerFixer(NamespacedIdentifier key, IdFixer fixer) { + SyncedRegistriesImpl.registerFixer(key, fixer); + } +} 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..28c88bd4 --- /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,49 @@ +package net.ornithemc.osl.registries.impl; + +import net.ornithemc.osl.entrypoints.api.ModInitializer; +import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer; +import net.ornithemc.osl.lifecycle.api.server.MinecraftServerEvents; +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; + +public final class RegistriesEntrypoint implements ModInitializer, ClientModInitializer { + + @Override + public void init() { + MinecraftServerEvents.STOP.register(server -> { + SyncedRegistriesImpl.undoMappings(); + }); + } + + @Override + public void initClient() { + ClientPlayNetworking.registerListener(SyncedRegistriesImpl.CHANNEL, (context, buffer) -> { + try { + SyncedRegistriesImpl.readMappings(buffer); + + 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/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/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..ad2ef0e0 --- /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,126 @@ +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; + +@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); + SyncedRegistriesImpl.readMappings(nbt); + 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(); + SyncedRegistriesImpl.writeMappings(nbt); + + try { + 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..afcbdbb3 --- /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,37 @@ +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.registry.SyncedRegistriesImpl; + +@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, SyncedRegistriesImpl.CHANNEL, SyncedRegistriesImpl::writeMappings); + } + } +} 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..78fd4fa6 --- /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 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/Clearable.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.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-mca1.0.1_01-mc1.6.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-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java new file mode 100644 index 00000000..f752aafc --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/SyncedRegistriesImpl.java @@ -0,0 +1,189 @@ +package net.ornithemc.osl.registries.impl.registry; + +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; + +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.networking.api.PacketBuffer; +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.impl.Constants; +import net.ornithemc.osl.registries.impl.mixin.common.NbtCompoundAccess; +import net.ornithemc.osl.registries.impl.registry.sync.RegistryMapper; +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.SerializableRegistryMappings; + +public final class SyncedRegistriesImpl { + + public static final NamespacedIdentifier CHANNEL = Constants.OSL_REGISTRY_SYNC_CHANNEL; + + private static final Map REGISTRY_MAPPINGS = new LinkedHashMap<>(); + private static final Map REGISTRY_MAPPERS = new LinkedHashMap<>(); + private static final Map ID_FIXERS = new LinkedHashMap<>(); + + private static final String FORMAT_NBT_KEY = "format"; + private static final int FORMAT = 1; + + public static void registerMapper(ResourceKey> registry) { + registerMapper(registry, RegistryMapper.of(Registries.get(registry))); + } + + public static void registerMapper(ResourceKey> registry, IdMapper mapper) { + NamespacedIdentifier identifier = registry.identifier(); + + if (Registries.get(registry) == null) { + throw new IllegalArgumentException("cannot register registry mapper: unknown registry: " + identifier); + } else { + REGISTRY_MAPPERS.put(identifier, mapper); + } + } + + public static void registerFixer(NamespacedIdentifier identifier, IdFixer fixer) { + if (ID_FIXERS.containsKey(identifier)) { + throw new IllegalArgumentException("duplicate ID fixer " + identifier); + } else { + ID_FIXERS.put(identifier, fixer); + } + } + + public static void init() { + for (Registry registry : Registries.REGISTRY) { + if (registry instanceof ClearableRegistry) { + NamespacedIdentifier identifier = registry.identifier(); + SerializableRegistryMappings mappings = SerializableRegistryMappings.of(registry); + + REGISTRY_MAPPINGS.put(identifier, mappings); + } + } + + for (NamespacedIdentifier identifier : REGISTRY_MAPPERS.keySet()) { + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings == null) { + throw new IllegalStateException("Illegal registry mapper for unsynced registry " + identifier); + } else { + mappings.reset(); + } + } + } + + public static void readMappings(PacketBuffer buffer) throws IOException, RegistryMappingException { + int format = buffer.readVarInt(); + + if (format > 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(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings != null) { + try { + mappings.read(buffer, RegistryMappingSource.REMOTE_SERVER); + } 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 writeMappings(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(FORMAT); + buffer.writeVarInt(REGISTRY_MAPPINGS.size()); + + for (Map.Entry e : REGISTRY_MAPPINGS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + SerializableRegistryMappings mappings = e.getValue(); + + buffer.writeNamespacedIdentifier(identifier); + mappings.write(buffer); + } + } + + public static void readMappings(NbtCompound nbt) throws RegistryMappingException { + int format = nbt.getInt(FORMAT_NBT_KEY); + + if (format > FORMAT) { + throw new IllegalStateException("cannot read registry mappings of newer format " + format); + } + + for (String nbtKey : ((NbtCompoundAccess) nbt).accessElements().keySet()) { + NbtCompound mappingsNbt = nbt.getCompound(nbtKey); + + NamespacedIdentifier identifier = NamespacedIdentifiers.parse(nbtKey); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + if (mappings != null) { + try { + mappings.read(mappingsNbt, RegistryMappingSource.WORLD_SAVE); + } 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 writeMappings(NbtCompound nbt) { + nbt.putInt(FORMAT_NBT_KEY, FORMAT); + + for (Map.Entry e : REGISTRY_MAPPINGS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + SerializableRegistryMappings mappings = e.getValue(); + NbtCompound mappingsNbt = new NbtCompound(); + + mappings.write(mappingsNbt); + nbt.put(identifier.toString(), mappingsNbt); + } + } + + public static void resetMappings() { + for (SerializableRegistryMappings mappings : REGISTRY_MAPPINGS.values()) { + mappings.reset(); + } + } + + public static void applyMappings() { + for (Map.Entry e : REGISTRY_MAPPERS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + IdMapper mapper = e.getValue(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + mapper.apply(mappings); + } + + applyFixers(); + } + + public static void undoMappings() { + for (Map.Entry e : REGISTRY_MAPPERS.entrySet()) { + NamespacedIdentifier identifier = e.getKey(); + IdMapper mapper = e.getValue(); + SerializableRegistryMappings mappings = REGISTRY_MAPPINGS.get(identifier); + + mapper.undo(mappings); + } + + applyFixers(); + } + + public static void applyFixers() { + for (IdFixer fixer : ID_FIXERS.values()) { + fixer.apply(); + } + } +} diff --git a/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java new file mode 100644 index 00000000..6f039a1f --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/SerializableRegistryMappings.java @@ -0,0 +1,63 @@ +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.networking.api.PacketBuffer; +import net.ornithemc.osl.registries.api.registry.Registry; +import net.ornithemc.osl.registries.impl.mixin.common.NbtCompoundAccess; + +public final class SerializableRegistryMappings extends MemoryRegistryMappings { + + public static SerializableRegistryMappings of(Registry registry) { + return new SerializableRegistryMappings(registry); + } + + private SerializableRegistryMappings(Registry registry) { + super(registry); + } + + public void read(PacketBuffer buffer, RegistryMappingSource source) throws IOException, RegistryMappingException { + int size = buffer.readVarInt(); + + for (int i = 0; i < size; i++) { + NamespacedIdentifier identifier = buffer.readNamespacedIdentifier(); + int id = buffer.readVarInt(); + + this.mappings.put(identifier, id); + } + + this.build(source); + } + + public void write(PacketBuffer buffer) throws IOException { + buffer.writeVarInt(this.mappings.size()); + + for (Object2IntMap.Entry mapping : this.mappings.object2IntEntrySet()) { + NamespacedIdentifier identifier = mapping.getKey(); + int id = mapping.getIntValue(); + + buffer.writeNamespacedIdentifier(identifier); + buffer.writeVarInt(id); + } + } + + public void read(NbtCompound nbt, RegistryMappingSource source) throws RegistryMappingException { + for (String key : ((NbtCompoundAccess) nbt).accessElements().keySet()) { + this.mappings.put(NamespacedIdentifiers.parse(key), nbt.getInt(key)); + } + + this.build(source); + } + + public void write(NbtCompound nbt) { + for (Object2IntMap.Entry mapping : this.mappings.object2IntEntrySet()) { + nbt.putInt(mapping.getKey().toString(), mapping.getIntValue()); + } + } +} 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..3724f1f2 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/resources/fabric.mod.json @@ -0,0 +1,39 @@ +{ + "schemaVersion": 1, + "id": "osl-registries", + "version": "0.1.0-alpha.1+mca1.0.1_01-mc1.6.4", + "environment": "*", + "entrypoints": { + "init": [ + "net.ornithemc.osl.registries.impl.RegistriesEntrypoint" + ], + "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..8df3cba5 --- /dev/null +++ b/libraries/registries/registries-mca1.0.1_01-mc1.6.4/src/main/resources/osl.registries.mixins.json @@ -0,0 +1,21 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.ornithemc.osl.registries.impl.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "common.AlphaWorldStorageMixin", + "common.NbtCompoundAccess", + "common.PlayerManagerMixin" + ], + "client": [ + "client.ClientNetworkHandlerAccess", + "client.MinecraftMixin" + ], + "server": [ + "server.MinecraftServerMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} 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..d65d79be --- /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 WritableRegistry registerSimple(ResourceKey> key, Registry.Bootstrap bootstrap) { + return RegistriesImpl.registerSimple(key, bootstrap); + } + + public static WritableRegistry 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..16abed2c --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/Registry.java @@ -0,0 +1,36 @@ +package net.ornithemc.osl.registries.api.registry; + +import java.util.Set; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; + +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(); + + 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..17d809bc --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/api/registry/ResourceKeys.java @@ -0,0 +1,15 @@ +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(NamespacedIdentifier registry, NamespacedIdentifier identifier) { + return ResourceKeysImpl.from(registry, identifier); + } +} 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..0fd2ec79 --- /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 { + + void register(ResourceKey key, T value); + + @Deprecated + void register(int id, ResourceKey key, T 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/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..60cf351f --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/Constants.java @@ -0,0 +1,12 @@ +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 String REGISTRY_MAPPINGS_FILE_NAME = "registry_mappings.dat"; + public static final NamespacedIdentifier OSL_REGISTRY_SYNC_CHANNEL = ChannelRegistry.register(ChannelIdentifiers.from("osl", "registry-sync")); + +} 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/DefaultedRegistry.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/DefaultedRegistry.java new file mode 100644 index 00000000..2eba1624 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/DefaultedRegistry.java @@ -0,0 +1,69 @@ +package net.ornithemc.osl.registries.impl.registry; + +import net.ornithemc.osl.core.api.util.NamespacedIdentifier; +import net.ornithemc.osl.registries.api.registry.ResourceKey; + +public class DefaultedRegistry extends SimpleRegistry { + + private final NamespacedIdentifier defaultIdentifier; + + private T defaultValue; + + public DefaultedRegistry(NamespacedIdentifier identifier, NamespacedIdentifier defaultIdentifier) { + super(identifier); + + this.defaultIdentifier = defaultIdentifier; + } + + @Override + public void register(int id, ResourceKey key, T value) { + super.register(id, key, value); + + if (this.defaultIdentifier.equals(key.identifier())) { + this.defaultValue = 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..03509956 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/RegistriesImpl.java @@ -0,0 +1,93 @@ +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.registry.Registry; +import net.ornithemc.osl.registries.api.registry.ResourceKey; +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 DefaultedRegistry registerDefaulted(ResourceKey> key, NamespacedIdentifier defaultIdentifier, Registry.Bootstrap bootstrap) { + return register(key, new DefaultedRegistry<>(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 void init() { + 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..2807beb8 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/SimpleRegistry.java @@ -0,0 +1,152 @@ +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 void register(ResourceKey key, T value) { + this.register(this.nextId++, key, value); + } + + @Override + public void register(int id, ResourceKey key, T 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 + " (" + 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); + } + + @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/sync/MemoryRegistryMappings.java b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/MemoryRegistryMappings.java new file mode 100644 index 00000000..c5dc41f6 --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/MemoryRegistryMappings.java @@ -0,0 +1,93 @@ +package net.ornithemc.osl.registries.impl.registry.sync; + +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 MemoryRegistryMappings implements RegistryMappings { + + 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") + MemoryRegistryMappings(Registry registry) { + this.registry = (Registry) registry; + } + + 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); + } + } + + 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); + } + } + } + + @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); + } +} 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..94d0affb --- /dev/null +++ b/libraries/registries/src/main/java/net/ornithemc/osl/registries/impl/registry/sync/RegistryMapper.java @@ -0,0 +1,75 @@ +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) { + ResourceKey key = this.backup.getKey(value); + int id = mappings.unmap(key); + + if (id >= 0) { + 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/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'