Skip to content

Commit

Permalink
Merge pull request #31 from CuukyOfficial/fix/xp-field
Browse files Browse the repository at this point in the history
feat: new xp cooldown field resolving method
  • Loading branch information
CuukyOfficial authored Sep 14, 2024
2 parents 4d824da + 7626b44 commit 4249f79
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ protected void initLocale() throws NoSuchFieldException, SecurityException, Ille
}

@Override
protected void initXp() {
protected void initXp(Player player) {
try {
Class<?> entityHuman = Class.forName("net.minecraft.entity.player.EntityPlayer");
this.xpCooldownField = entityHuman.getDeclaredField("field_71090_bL");
Class<?> entityHumanClass = Class.forName("net.minecraft.entity.player.EntityPlayer");
this.xpCooldownField = entityHumanClass.getDeclaredField("field_71090_bL");
} catch (Throwable t) {
t.printStackTrace();
}
Expand Down

This file was deleted.

87 changes: 54 additions & 33 deletions src/main/java/de/varoplugin/cfw/version/OneSevenVersionAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.bukkit.Bukkit;
Expand All @@ -38,6 +40,8 @@
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
Expand Down Expand Up @@ -77,7 +81,52 @@ protected void init() throws IllegalArgumentException, NoSuchMethodException, Se
this.initRespawn();
this.initNetworkManager();
this.initLocale();
this.initXp();
}

protected void initXp(Player player) {
this.searchXpField(player, VersionUtils.getNmsClass() + ".EntityHuman", VersionUtils.getNmsClass() + ".EntityExperienceOrb");
}

protected void searchXpField(Player player, String humanClassName, String experienceOrbClassName) {
try {
Class<?> entityHumanClass = Class.forName(humanClassName);
Map<Field, Integer> values = new HashMap<>();
Object craftPlayer = this.getHandle(player);

// Get values of all int fields of player
for (Field field : entityHumanClass.getDeclaredFields()) {
if (field.getType() == int.class) {
field.setAccessible(true);
values.put(field, field.getInt(craftPlayer));
}
}

// Invoke method which sets the value of xp cooldown to 2
Location randomLoc = new Location(player.getWorld(), 0, 0, 0);
ExperienceOrb orb = (ExperienceOrb) player.getWorld().spawnEntity(randomLoc, EntityType.EXPERIENCE_ORB);
orb.setExperience(0);
Class<?> entityExperienceOrbClass = Class.forName(experienceOrbClassName);
for (Method method : entityExperienceOrbClass.getDeclaredMethods()) {
if (method.getParameterTypes().length == 1 && method.getParameterTypes()[0] == entityHumanClass) {
method.setAccessible(true);
method.invoke(this.getHandle(orb), craftPlayer);
}
}

orb.remove();

// Compare values and use the field with changed value
for (Field field : values.keySet()) {
if (field.getInt(craftPlayer) != values.get(field)) {
this.xpCooldownField = field;
return;
}
}

throw new Error("Unable to find xp cooldown field");
} catch (SecurityException | IllegalAccessException | InvocationTargetException | ClassNotFoundException e) {
throw new Error(e);
}
}

protected void initServerProperties() throws ClassNotFoundException, NoSuchMethodException, SecurityException, NoSuchFieldException {
Expand Down Expand Up @@ -118,38 +167,6 @@ protected void initLocale() throws NoSuchFieldException, SecurityException, Ille
this.localeField.setAccessible(true);
}

protected void initXp() {
this.initXp(VersionUtils.getNmsClass() + ".EntityHuman", VersionUtils.getNmsClass() + ".FoodMetaData");
}

protected void initXp(String entityHumanName, String foodMetaName) {
// this is EXTREMELY unsafe
try {
int fieldNum = 0;
for (Field field : Class.forName(entityHumanName).getDeclaredFields())
if (fieldNum == 0 && field.getType() == Class.forName(foodMetaName))
fieldNum = 1;
// This is for 1.19+, but I don't want to create a new version adapter class for one single line of code (Yes, I am lazy)
else if (fieldNum == 1 && field.getType().getName().equals("net.minecraft.world.entity.monster.warden.WardenSpawnTracker"))
;
else if (fieldNum == 1 && field.getType() == int.class)
fieldNum = 2;
else if (fieldNum == 2 && field.getType() == float.class)
fieldNum = 3;
else if (fieldNum == 3 && field.getType() == float.class)
fieldNum = 4;
else if (fieldNum == 4 && field.getType() == int.class) {
this.xpCooldownField = field;
return;
} else
fieldNum = 0;

throw new Error("Unable to find xp cooldown field");
} catch (SecurityException | ClassNotFoundException e) {
throw new Error(e);
}
}

protected Object getHandle(Entity entity) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
return this.entityHandleMethod.invoke(entity);
}
Expand Down Expand Up @@ -263,6 +280,10 @@ public void removeAi(LivingEntity entity) {

@Override
public void setXpCooldown(Player player, int cooldown) {
if (this.xpCooldownField == null) {
this.initXp(player);
}

try {
this.xpCooldownField.set(this.getHandle(player), cooldown);
} catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ protected void initRespawn() {
}

@Override
protected void initXp() {
this.initXp("net.minecraft.world.entity.player.EntityHuman", "net.minecraft.world.food.FoodMetaData");
protected void initXp(Player player) {
String entityHumanClass = "net.minecraft.world.entity.player.EntityHuman";
String entityExperienceOrbClass = "net.minecraft.world.entity.EntityExperienceOrb";
this.searchXpField(player, entityHumanClass, entityExperienceOrbClass);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
public class OneTwentyVersionAdapter extends OneNineteenVersionAdapter {

@Override
protected void initXp() {
// nop
protected void initXp(Player player) {
// Not needed, since Player#setExpCooldown is available
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
public enum ServerSoftware {

MAGMA_1_18("Magma 1.18.2", SpigotVersionAdapter::new, "org.magmafoundation.magma.helpers.EnumJ17Helper", "Magma"),
MAGMA_1_12("Magma", versionSupplier -> new MagmaOneTwelveVersionAdapter(), "org.magmafoundation.magma.Magma", "Magma"),
MAGMA_1_12("Magma", SpigotVersionAdapter::new, "org.magmafoundation.magma.Magma", "Magma"),
CRUCIBLE("Crucible", versionSupplier -> new CrucibleVersionAdapter(), "io.github.crucible.CrucibleCommand", "Crucible"),
URANIUM("Uranium", null, null, "Uranium"),
THERMOS("Thermos", null, "thermos.Thermos", "Thermos"),
Expand Down

0 comments on commit 4249f79

Please sign in to comment.