Skip to content

Commit

Permalink
fix(Sponge): Fixed Sponge_SkinHandler for versions below 1.18
Browse files Browse the repository at this point in the history
  • Loading branch information
GeorgeV220 committed Jan 17, 2023
1 parent bb15107 commit 87bfd7f
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 29 deletions.
10 changes: 8 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ allprojects {
compileOnly 'co.aikar:acf-bungee:0.5.1-G-1.0-SNAPSHOT'
compileOnly 'co.aikar:acf-velocity:0.5.1-G-1.0-SNAPSHOT'
compileOnly 'co.aikar:acf-sponge8:0.5.1-G-1.0-SNAPSHOT'
compileOnly 'com.georgev22:martexlibrary:8.12.0'
compileOnly 'com.georgev22:martexlibrary:8.13.0'
compileOnly 'com.georgev22.api:libraryloader:1.4.0'
compileOnly 'org.jetbrains:annotations:23.1.0'
compileOnly 'commons-codec:commons-codec:1.15'
Expand Down Expand Up @@ -106,7 +106,7 @@ dependencies {
implementation 'co.aikar:acf-bungee:0.5.1-G-1.0-SNAPSHOT'
implementation 'co.aikar:acf-velocity:0.5.1-G-1.0-SNAPSHOT'
implementation 'co.aikar:acf-sponge8:0.5.1-G-1.0-SNAPSHOT'
implementation 'com.georgev22:martexlibrary:8.12.0'
implementation 'com.georgev22:martexlibrary:8.13.0'
implementation 'com.georgev22.api:libraryloader:1.4.0'
implementation 'com.google.code.gson:gson:2.10.1'
implementation project(path: ':core')
Expand All @@ -131,6 +131,12 @@ shadowJar {
relocate 'com.georgev22.library', "${packageName}.library"
}

jar {
manifest {
attributes["MixinConfigs"] = "mixins.skinoverlay.json"
}
}

tasks.build.dependsOn(shadowJar)
tasks.publish.dependsOn(shadowJar)

Expand Down
12 changes: 11 additions & 1 deletion sponge/build.gradle
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
import org.spongepowered.gradle.plugin.config.PluginLoaders
import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform
import org.spongepowered.plugin.metadata.model.PluginDependency

plugins {
id("org.spongepowered.gradle.plugin") version "2.1.1"
id("org.spongepowered.gradle.vanilla") version "0.2+"
}

dependencies {
compileOnly project(path: ':core')
compileOnly("org.spongepowered:mixin:0.8.3")
}


minecraft {
version("1.19.3")
platform(MinecraftPlatform.SERVER)
injectRepositories(false)
}

sponge {
apiVersion("9.1.0-SNAPSHOT")
apiVersion("8.0.0")
loader {
name(PluginLoaders.JAVA_PLAIN)
version("1.0")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.georgev22.skinoverlay.handler.handlers;

import com.georgev22.library.exceptions.ReflectionException;
import com.georgev22.library.minecraft.SpongeMinecraftUtils;
import com.georgev22.library.utilities.Utils;
import com.georgev22.library.yaml.file.FileConfiguration;
import com.georgev22.skinoverlay.SkinOverlay;
import com.georgev22.skinoverlay.SkinOverlaySponge;
import com.georgev22.skinoverlay.handler.SkinHandler.SkinHandler_;
import com.georgev22.skinoverlay.utilities.player.PlayerObject;
Expand All @@ -12,7 +14,6 @@
import com.mojang.authlib.properties.Property;
import lombok.SneakyThrows;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.data.Keys;
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
import org.spongepowered.api.entity.living.player.tab.TabListEntry;
Expand All @@ -23,6 +24,7 @@
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashSet;
import java.util.concurrent.ExecutionException;

Expand All @@ -37,7 +39,7 @@ public class SkinHandler_Sponge extends SkinHandler_ {
private final Class<?> respawnPacketClass;
private final Class<?> entityDataPacketClass;
private final Class<?> entityDataSerializersClass;
private final Class<?> entityDataAccesorClass;
private final Class<?> entityDataAccessorClass;

private final Class<?> packet;

Expand All @@ -48,7 +50,7 @@ public SkinHandler_Sponge() {
respawnPacketClass = Utils.Reflection.getClass("net.minecraft.network.protocol.game.ClientboundRespawnPacket", classLoader);
entityDataPacketClass = Utils.Reflection.getClass("net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket", classLoader);
entityDataSerializersClass = Utils.Reflection.getClass("net.minecraft.network.syncher.EntityDataSerializers", classLoader);
entityDataAccesorClass = Utils.Reflection.getClass("net.minecraft.network.syncher.EntityDataAccessor", classLoader);
entityDataAccessorClass = Utils.Reflection.getClass("net.minecraft.network.syncher.EntityDataAccessor", classLoader);
packet = Utils.Reflection.getClass("net.minecraft.network.protocol.Packet", classLoader);
}

Expand Down Expand Up @@ -94,10 +96,9 @@ public void updateSkin(@NotNull FileConfiguration fileConfiguration, @NotNull Pl
Object respawnPacket;
//Respawn packet
try {
Object deathLocation = fetchMethodAndInvoke(serverPlayerClass, "getLastDeathLocation", serverPlayer, new Object[]{}, new Class[]{});

switch (Sponge.platform().minecraftVersion().name()) {
case "1.19.3" -> respawnPacket = invokeConstructor(
switch (SpongeMinecraftUtils.MinecraftVersion.getCurrentVersion()) {
case V1_19_R2, UNKNOWN -> respawnPacket = invokeConstructor(
respawnPacketClass,
dimensionType,
dimension,
Expand All @@ -107,9 +108,9 @@ public void updateSkin(@NotNull FileConfiguration fileConfiguration, @NotNull Pl
fetchMethodAndInvoke(serverWorldClass, "isDebug", serverWorld, new Object[]{}, new Class[]{}),
fetchMethodAndInvoke(serverWorldClass, "isFlat", serverWorld, new Object[]{}, new Class[]{}),
(byte) 3,
deathLocation
fetchMethodAndInvoke(serverPlayerClass, "getLastDeathLocation", serverPlayer, new Object[]{}, new Class[]{})
);
case "1.19.2" -> respawnPacket = invokeConstructor(
case V1_19_R1 -> respawnPacket = invokeConstructor(
respawnPacketClass,
dimensionType,
dimension,
Expand All @@ -119,7 +120,7 @@ public void updateSkin(@NotNull FileConfiguration fileConfiguration, @NotNull Pl
fetchMethodAndInvoke(serverWorldClass, "isDebug", serverWorld, new Object[]{}, new Class[]{}),
fetchMethodAndInvoke(serverWorldClass, "isFlat", serverWorld, new Object[]{}, new Class[]{}),
true,
deathLocation
fetchMethodAndInvoke(serverPlayerClass, "getLastDeathLocation", serverPlayer, new Object[]{}, new Class[]{})
);
default -> respawnPacket = invokeConstructor(
respawnPacketClass,
Expand All @@ -146,8 +147,8 @@ public void updateSkin(@NotNull FileConfiguration fileConfiguration, @NotNull Pl
fetchMethodAndInvoke(synchedEntityData.getClass(), "set", synchedEntityData,
new Object[]{
entityDataAccessor = invokeConstructor(
entityDataAccesorClass,
17,
entityDataAccessorClass,
SpongeMinecraftUtils.MinecraftVersion.getCurrentVersion().isBelow(SpongeMinecraftUtils.MinecraftVersion.V1_17_R1) ? 16 : 17,
fetchField(entityDataSerializersClass, null, "BYTE")),
(byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40)
},
Expand All @@ -159,8 +160,8 @@ public void updateSkin(@NotNull FileConfiguration fileConfiguration, @NotNull Pl
fetchMethodAndInvoke(synchedEntityData.getClass(), "set", synchedEntityData,
new Object[]{
entityDataAccessor = invokeConstructor(
entityDataAccesorClass,
17,
entityDataAccessorClass,
SpongeMinecraftUtils.MinecraftVersion.getCurrentVersion().isBelow(SpongeMinecraftUtils.MinecraftVersion.V1_17_R1) ? 16 : 17,
fetchField(entityDataSerializersClass, null, "BYTE")),
(byte)
((fileConfiguration.getBoolean("Options.overlays." + skinName + ".cape", false) ? 0x01 : 0x00) |
Expand All @@ -176,8 +177,12 @@ public void updateSkin(@NotNull FileConfiguration fileConfiguration, @NotNull Pl
Object.class
});
}
if (Sponge.platform().minecraftVersion().name().equals("1.19.3")) {
try {
fetchMethodAndInvoke(synchedEntityData.getClass(), "markDirty", synchedEntityData, new Object[]{entityDataAccessor}, new Class[]{entityDataAccessorClass});
} catch (Exception ignore) {
markDirty(synchedEntityData, entityDataAccessor);
}
if (SpongeMinecraftUtils.MinecraftVersion.getCurrentVersion().equals(SpongeMinecraftUtils.MinecraftVersion.V1_19_R2)) {
entityDataPacket = invokeConstructor(entityDataPacketClass,
fetchMethodAndInvoke(serverPlayerClass, "getId", serverPlayer, new Object[]{}, new Class[]{}),
fetchMethodAndInvoke(synchedEntityData.getClass(), "packDirty", synchedEntityData, new Object[]{}, new Class[]{})
Expand All @@ -186,7 +191,7 @@ public void updateSkin(@NotNull FileConfiguration fileConfiguration, @NotNull Pl
entityDataPacket = invokeConstructor(entityDataPacketClass,
fetchMethodAndInvoke(serverPlayerClass, "getId", serverPlayer, new Object[]{}, new Class[]{}),
synchedEntityData,
true
false
);
}

Expand All @@ -204,23 +209,49 @@ public void updateSkin(@NotNull FileConfiguration fileConfiguration, @NotNull Pl

Object playerConnection = getFieldByType(serverPlayer, "ServerGamePacketListenerImpl");
sendPacket(playerConnection, respawnPacket);
SkinOverlay.getInstance().getLogger().info("EntityDataPacket: " + Arrays.toString(entityDataPacket.getClass().getConstructors()) + "\n" + "Accessor: " + entityDataAccessor);
sendPacket(playerConnection, entityDataPacket);

Object playerPositionPacket;
Object playerCarriedItemPacket;
try {
Class<?> playerPositionPacketClass = Utils.Reflection.getClass("net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket", classLoader);
Class<?> playerCarriedItemPacketClass = Utils.Reflection.getClass("net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket", classLoader);
switch (SpongeMinecraftUtils.MinecraftVersion.getCurrentVersion()) {
case V1_19_R2, V1_19_R1, V1_18_R2, V1_18_R1 ->
playerPositionPacket = invokeConstructor(playerPositionPacketClass,
serverLocation.x(),
serverLocation.y(),
serverLocation.z(),
(float) rotation.y(),
(float) rotation.x(),
new HashSet<>(),
0,
false);
case V1_17_R1 -> playerPositionPacket = invokeConstructor(playerPositionPacketClass,
serverLocation.x(),
serverLocation.y(),
serverLocation.z(),
(float) rotation.y(),
(float) rotation.x(),
false);
case V1_16_R3, V1_16_R2 -> playerPositionPacket = invokeConstructor(playerPositionPacketClass,
serverLocation.x(),
serverLocation.y(),
serverLocation.z(),
(float) rotation.y(),
(float) rotation.x(),
new HashSet<>(),
0);
default -> playerPositionPacket = invokeConstructor(playerPositionPacketClass,
serverLocation.x(),
serverLocation.y(),
serverLocation.z(),
(float) rotation.y(),
(float) rotation.x(),
new HashSet<>());
}

playerPositionPacket = invokeConstructor(playerPositionPacketClass,
serverLocation.x(),
serverLocation.y(),
serverLocation.z(),
(float) rotation.y(),
(float) rotation.x(),
new HashSet<>(),
0,
false);
playerCarriedItemPacket = invokeConstructor(playerCarriedItemPacketClass,
receiver.inventory().hotbar().selectedSlotIndex()
);
Expand Down Expand Up @@ -255,8 +286,8 @@ private void sendPacket(Object playerConnection, Object packet) throws Reflectio
fetchMethodAndInvoke(playerConnection.getClass(), "send", playerConnection, new Object[]{packet}, new Class<?>[]{this.packet});
}

private void markDirty(@NotNull Object obj, @NotNull Object datawatcherobject) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, NoSuchFieldException {
Object getItem = fetchDeclaredMethodAndInvoke(obj.getClass(), "getItem", obj, new Object[]{datawatcherobject}, new Class[]{datawatcherobject.getClass()});
private void markDirty(@NotNull Object obj, @NotNull Object dataWatcherObject) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, NoSuchFieldException {
Object getItem = fetchDeclaredMethodAndInvoke(obj.getClass(), "getItem", obj, new Object[]{dataWatcherObject}, new Class[]{entityDataAccessorClass});
fetchMethodAndInvoke(getItem.getClass(), "setDirty", getItem, new Object[]{true}, new Class[]{boolean.class});
setDeclaredFieldValue(obj.getClass(), obj, "isDirty", true);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.georgev22.skinoverlay.mixin.sponge;

import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;

@Mixin(SynchedEntityData.class)
public abstract class SynchedEntityData_Mixin {

@Shadow
private boolean isDirty;

@Shadow
protected abstract <T> SynchedEntityData.DataItem<T> getItem(EntityDataAccessor<T> dataWatcherObject);

public <T> void markDirty(EntityDataAccessor<T> dataWatcherObject) {
getItem(dataWatcherObject).setDirty(true);
isDirty = true;
}

}
14 changes: 14 additions & 0 deletions sponge/src/main/resources/mixins.skinoverlay.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"required": true,
"minVersion": "0.8.3",
"package": "com.georgev22.skinoverlay.mixin.sponge",
"refmap": "mixins.skinoverlay.refmap.json",
"target": "@env(DEFAULT)",
"compatibilityLevel": "JAVA_11",
"injectors": {
"defaultRequire": 1
},
"mixins": [
"SynchedEntityData_Mixin"
]
}

0 comments on commit 87bfd7f

Please sign in to comment.