diff --git a/dist/dependency-reduced-pom.xml b/dist/dependency-reduced-pom.xml index 9ac078f..abcb5d0 100644 --- a/dist/dependency-reduced-pom.xml +++ b/dist/dependency-reduced-pom.xml @@ -31,6 +31,39 @@ + + net.md-5 + specialsource-maven-plugin + 1.2.4 + + + remap-obf + package + + remap + + + org.spigotmc:minecraft-server:1.19.3-R0.1-SNAPSHOT:txt:maps-mojang + true + org.spigotmc:spigot:1.19.3-R0.1-SNAPSHOT:jar:remapped-mojang + true + remapped-obf + + + + remap-spigot + package + + remap + + + ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar + org.spigotmc:minecraft-server:1.19.3-R0.1-SNAPSHOT:csrg:maps-spigot + org.spigotmc:spigot:1.19.3-R0.1-SNAPSHOT:jar:remapped-obf + + + + diff --git a/dist/pom.xml b/dist/pom.xml index 0384c21..d81b2f5 100644 --- a/dist/pom.xml +++ b/dist/pom.xml @@ -37,6 +37,39 @@ + + net.md-5 + specialsource-maven-plugin + 1.2.4 + + + package + + remap + + remap-obf + + org.spigotmc:minecraft-server:1.19.3-R0.1-SNAPSHOT:txt:maps-mojang + true + org.spigotmc:spigot:1.19.3-R0.1-SNAPSHOT:jar:remapped-mojang + true + remapped-obf + + + + package + + remap + + remap-spigot + + ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar + org.spigotmc:minecraft-server:1.19.3-R0.1-SNAPSHOT:csrg:maps-spigot + org.spigotmc:spigot:1.19.3-R0.1-SNAPSHOT:jar:remapped-obf + + + + @@ -66,7 +99,10 @@ nicko-v1_19_R1 ${project.parent.version} + + net.artelnatif + nicko-v1_19_R2 + ${project.parent.version} + - - \ No newline at end of file diff --git a/nicko-core/pom.xml b/nicko-core/pom.xml index b673d55..0917b60 100644 --- a/nicko-core/pom.xml +++ b/nicko-core/pom.xml @@ -71,7 +71,7 @@ de.studiocode.invui InvUI - 0.8.2 + 0.10.2 diff --git a/pom.xml b/pom.xml index 6cc51a1..31e0c49 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,7 @@ v1_18_R1 v1_18_R2 v1_19_R1 + v1_19_R2 diff --git a/v1_19_R2/pom.xml b/v1_19_R2/pom.xml new file mode 100644 index 0000000..ee71c1d --- /dev/null +++ b/v1_19_R2/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + + + net.artelnatif + nicko-parent + 1.0-SNAPSHOT + + + nicko-v1_19_R2 + 1.0-SNAPSHOT + + + + org.spigotmc + spigot + 1.19.3-R0.1-SNAPSHOT + remapped-mojang + provided + + + net.artelnatif + nicko-core + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/v1_19_R2/src/main/java/net/artelnatif/nicko/impl/v1_19_R2.java b/v1_19_R2/src/main/java/net/artelnatif/nicko/impl/v1_19_R2.java new file mode 100644 index 0000000..9448bfb --- /dev/null +++ b/v1_19_R2/src/main/java/net/artelnatif/nicko/impl/v1_19_R2.java @@ -0,0 +1,134 @@ +package net.artelnatif.nicko.impl; + +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import com.mojang.authlib.properties.PropertyMap; +import net.artelnatif.nicko.NickoBukkit; +import net.artelnatif.nicko.disguise.ActionResult; +import net.artelnatif.nicko.disguise.NickoProfile; +import net.artelnatif.nicko.i18n.I18NDict; +import net.artelnatif.nicko.mojang.MojangAPI; +import net.artelnatif.nicko.mojang.MojangSkin; +import net.minecraft.network.protocol.game.*; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.network.syncher.EntityDataSerializers; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; +import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerTeleportEvent; + +import java.io.IOException; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ExecutionException; + +public class v1_19_R2 implements Internals { + @Override + public void updateSelf(Player player) { + final ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle(); + final ServerLevel level = serverPlayer.getLevel(); + final ResourceKey levelResourceKey = serverPlayer.getLevel().dimension(); + final CraftWorld world = level.getWorld(); + // last boolean is: "has death location" attribute, if true, the optional contains the death dimension and position. + // with the boolean being false, we don't need to provide a value, and thus we return an empty optional. + final ClientboundRespawnPacket respawn = new ClientboundRespawnPacket(serverPlayer.level.dimensionTypeId(), + levelResourceKey, world.getSeed(), + serverPlayer.gameMode.getPreviousGameModeForPlayer(), serverPlayer.gameMode.getGameModeForPlayer(), + level.isDebug(), + level.isFlat(), + (byte) 0x00, + Optional.empty()); + + final boolean wasFlying = player.isFlying(); + serverPlayer.connection.send(respawn); + player.setFlying(wasFlying); + player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN); + player.updateInventory(); + } + + @Override + public void updateOthers(Player player) { + final ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle(); + final ClientboundRemoveEntitiesPacket remove = new ClientboundRemoveEntitiesPacket(serverPlayer.getBukkitEntity().getEntityId()); + final ClientboundAddEntityPacket add = new ClientboundAddEntityPacket(serverPlayer); + + /* + BIT MASKS: + 0x01 Cape enabled + 0x02 Jacket enabled + 0x04 Left sleeve enabled + 0x08 Right sleeve enabled + 0x10 Left pants leg enabled + 0x20 Right pants leg enabled + 0x40 Hat enabled + */ + final SynchedEntityData entityData = serverPlayer.getEntityData(); + final EntityDataAccessor skinPartAccessor = new EntityDataAccessor<>(17, EntityDataSerializers.BYTE); + entityData.set(skinPartAccessor, (byte) 0x7f); // 127, all masks combined + final ClientboundSetEntityDataPacket entityMetadata = new ClientboundSetEntityDataPacket(serverPlayer.getBukkitEntity().getEntityId(), entityData.getNonDefaultValues()); + + Bukkit.getOnlinePlayers().forEach(online -> { + ServerPlayer onlineServerPlayer = ((CraftPlayer) online).getHandle(); + if (onlineServerPlayer.getBukkitEntity().getUniqueId() != player.getUniqueId()) { + onlineServerPlayer.connection.send(remove); + onlineServerPlayer.connection.send(add); + } + onlineServerPlayer.connection.send(entityMetadata); + }); + } + + @Override + public ActionResult updateProfile(Player player, NickoProfile profile, boolean skinChange, boolean reset) { + final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName()); + final String profileName = profile.getName() == null ? player.getName() : profile.getName(); + Optional skin; + + final ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle(); + final GameProfile gameProfile = serverPlayer.getGameProfile(); + + final ClientboundPlayerInfoRemovePacket remove = new ClientboundPlayerInfoRemovePacket(List.of(player.getUniqueId())); + // TODO: 1/20/23 Sets Gamemode to Survival but keeps the flying? Visual effect only? + final ClientboundPlayerInfoUpdatePacket init = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(serverPlayer)); + + + if (skinChange || changeOnlyName) { + try { + final MojangAPI mojang = NickoBukkit.getInstance().getMojangAPI(); + final Optional uuid = mojang.getUUID(profile.getSkin()); + if (uuid.isPresent()) { + skin = (reset ? mojang.getSkinWithoutCaching(uuid.get()) : mojang.getSkin(uuid.get())); + if (skin.isPresent()) { + final PropertyMap properties = gameProfile.getProperties(); + properties.removeAll("textures"); + properties.put("textures", new Property("textures", skin.get().value(), skin.get().signature())); + updateSelf(player); + } else { + return new ActionResult(I18NDict.Error.SKIN_FAIL_MOJANG); + } + } else { + return new ActionResult(I18NDict.Error.NAME_FAIL_MOJANG); + } + } catch (ExecutionException e) { + return new ActionResult(I18NDict.Error.SKIN_FAIL_CACHE); + } catch (IOException e) { + return new ActionResult(I18NDict.Error.NAME_FAIL_MOJANG); + } + } + + serverPlayer.connection.send(remove); + serverPlayer.connection.send(init); + Bukkit.getOnlinePlayers().forEach(online -> { + ServerPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle(); + onlineEntityPlayer.connection.send(remove); + onlineEntityPlayer.connection.send(init); + }); + updateOthers(player); + return new ActionResult(); + } +}