mirror of
https://github.com/JamesPeters98/ChestsPlusPlus.git
synced 2024-11-22 10:36:11 +01:00
OfflinePlayerReflectionTests
This commit is contained in:
parent
332d6d3df1
commit
ab9a31d78a
@ -9,5 +9,5 @@ public interface CraftingProvider {
|
||||
|
||||
CraftingResult craft(Player player, World world, ItemStack[] items);
|
||||
|
||||
Recipe getRecipe(Player player, World world, ItemStack[] items);
|
||||
Recipe getRecipe(World world, ItemStack[] items);
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ public class Crafting implements CraftingProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Recipe getRecipe(Player player, World world, ItemStack[] items) {
|
||||
public Recipe getRecipe(World world, ItemStack[] items) {
|
||||
Container container = new Container(null, -1) {
|
||||
@Override
|
||||
public InventoryView getBukkitView() {
|
||||
|
@ -63,7 +63,7 @@ public class Crafting implements CraftingProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Recipe getRecipe(Player player, World world, ItemStack[] items) {
|
||||
public Recipe getRecipe(World world, ItemStack[] items) {
|
||||
Container container = new Container(null, -1) {
|
||||
@Override
|
||||
public InventoryView getBukkitView() {
|
||||
|
@ -63,7 +63,7 @@ public class Crafting implements CraftingProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Recipe getRecipe(Player player, World world, ItemStack[] items) {
|
||||
public Recipe getRecipe(World world, ItemStack[] items) {
|
||||
Container container = new Container(null, -1) {
|
||||
@Override
|
||||
public InventoryView getBukkitView() {
|
||||
|
@ -22,7 +22,7 @@ public class Crafting implements CraftingProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Recipe getRecipe(Player player, World world, ItemStack[] items) {
|
||||
public Recipe getRecipe(World world, ItemStack[] items) {
|
||||
return Bukkit.getCraftingRecipe(items, world);
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import com.jamesdpeters.minecraft.chests.misc.Stats;
|
||||
import com.jamesdpeters.minecraft.chests.misc.Utils;
|
||||
import com.jamesdpeters.minecraft.chests.party.PlayerParty;
|
||||
import com.jamesdpeters.minecraft.chests.party.PlayerPartyStorage;
|
||||
import com.jamesdpeters.minecraft.chests.players.PlayerStorage;
|
||||
import com.jamesdpeters.minecraft.chests.serialize.Config;
|
||||
import com.jamesdpeters.minecraft.chests.serialize.ConfigStorage;
|
||||
import com.jamesdpeters.minecraft.chests.serialize.LocationInfo;
|
||||
@ -141,6 +142,7 @@ public class ChestsPlusPlus extends JavaPlugin {
|
||||
getServer().getPluginManager().registerEvents(new InventoryListener(), this);
|
||||
getServer().getPluginManager().registerEvents(new HopperListener(), this);
|
||||
getServer().getPluginManager().registerEvents(new WorldListener(), this);
|
||||
getServer().getPluginManager().registerEvents(new PlayerStorage(), this);
|
||||
Config.getStorageTypes().forEach(storageType -> getServer().getPluginManager().registerEvents(storageType, this));
|
||||
getLogger().info("Chests++ enabled!");
|
||||
}, 1);
|
||||
|
@ -32,8 +32,8 @@ public class Crafting {
|
||||
});
|
||||
}
|
||||
|
||||
public static Recipe getRecipe(Player player, ItemStack[] craftingTable) {
|
||||
return ApiSpecific.getNmsProvider().getCraftingProvider().getRecipe(player, Bukkit.getWorlds().get(0), craftingTable);
|
||||
public static Recipe getRecipe(ItemStack[] craftingTable) {
|
||||
return ApiSpecific.getNmsProvider().getCraftingProvider().getRecipe(Bukkit.getWorlds().get(0), craftingTable);
|
||||
}
|
||||
|
||||
public static CraftingResult craft(Player player, ItemStack[] recipe) {
|
||||
|
@ -18,6 +18,7 @@ import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.Container;
|
||||
import org.bukkit.block.Hopper;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
@ -33,6 +34,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class VirtualCraftingHolder implements InventoryHolder {
|
||||
@ -44,6 +46,7 @@ public class VirtualCraftingHolder implements InventoryHolder {
|
||||
|
||||
private ItemStack[][] recipeChoices = new ItemStack[9][];
|
||||
private ItemStack result;
|
||||
private ItemStack[] matrixResult; // stored matrix result after a crafting event
|
||||
private final int[] recipeChoiceIndex = new int[9];
|
||||
private boolean hasCompleteRecipe = false;
|
||||
|
||||
@ -71,6 +74,7 @@ public class VirtualCraftingHolder implements InventoryHolder {
|
||||
|
||||
public void setCrafting(ShapelessRecipe shapelessRecipe) {
|
||||
result = shapelessRecipe.getResult();
|
||||
matrixResult = null;
|
||||
List<RecipeChoice> choiceList = shapelessRecipe.getChoiceList();
|
||||
for (int i = 0; i < choiceList.size(); i++) {
|
||||
RecipeChoice recipeChoice = choiceList.get(i);
|
||||
@ -84,6 +88,7 @@ public class VirtualCraftingHolder implements InventoryHolder {
|
||||
|
||||
public void setCrafting(ShapedRecipe recipe) {
|
||||
result = recipe.getResult();
|
||||
matrixResult = null;
|
||||
int row = 0;
|
||||
for (String r : recipe.getShape()) {
|
||||
int col = 0;
|
||||
@ -101,12 +106,13 @@ public class VirtualCraftingHolder implements InventoryHolder {
|
||||
setHasCompleteRecipe();
|
||||
}
|
||||
|
||||
public void setCrafting(Recipe recipe, ItemStack[] matrix) {
|
||||
public void setCrafting(Recipe recipe, ItemStack[] matrix, ItemStack[] matrixResult) {
|
||||
if (recipe instanceof ShapedRecipe) setCrafting((ShapedRecipe) recipe);
|
||||
else if (recipe instanceof ShapelessRecipe) setCrafting((ShapelessRecipe) recipe);
|
||||
else {
|
||||
// For ComplexRecipes or other implementations just use the result and original matrix for choices.
|
||||
result = ApiSpecific.getNmsProvider().getCraftingProvider().craft(storage.getOwner().getPlayer(), Bukkit.getWorlds().get(0), matrix).result();
|
||||
result = recipe.getResult();
|
||||
this.matrixResult = matrixResult;
|
||||
for (int i = 0; i < matrix.length; i++) {
|
||||
ItemStack item = matrix[i];
|
||||
if (item != null) {
|
||||
@ -131,15 +137,18 @@ public class VirtualCraftingHolder implements InventoryHolder {
|
||||
stopCraftingItems();
|
||||
}
|
||||
|
||||
public void updateCrafting() {
|
||||
public void updateCrafting(InventoryEvent event) {
|
||||
var crafting = Arrays.copyOfRange(inventory.getContents(),1, inventory.getContents().length);
|
||||
|
||||
Recipe recipe = Crafting.getRecipe(storage.getOwner().getPlayer(), crafting);
|
||||
getStorage().setRecipe(recipe, crafting); // Only store the crafting matrix if the recipe is valid
|
||||
Player player = (Player) event.getView().getPlayer();
|
||||
var craftingResult = ApiSpecific.getNmsProvider().getCraftingProvider().craft(player, player.getWorld(), Arrays.copyOf(crafting, crafting.length));
|
||||
|
||||
Recipe recipe = Crafting.getRecipe(crafting);
|
||||
getStorage().setRecipe(recipe, crafting, craftingResult.matrixResult()); // Only store the crafting matrix if the recipe is valid
|
||||
resetChoices();
|
||||
|
||||
if (recipe != null) {
|
||||
setCrafting(recipe, crafting);
|
||||
setCrafting(recipe, crafting, craftingResult.matrixResult());
|
||||
playSound(Sound.BLOCK_NOTE_BLOCK_CHIME, 0.5f, 1f);
|
||||
} else {
|
||||
stopCraftingItems();
|
||||
@ -426,13 +435,16 @@ public class VirtualCraftingHolder implements InventoryHolder {
|
||||
Inventory tempOutput = sameInv ? sameInventory : Utils.copyInventory(output);
|
||||
HashMap<Integer, ItemStack> map = tempOutput.addItem(craftingResult.result());
|
||||
|
||||
boolean isEmpty = Arrays.stream(craftingResult.matrixResult())
|
||||
.anyMatch(itemStack -> (itemStack == null || itemStack.getType() == Material.AIR));
|
||||
// Remove nulls from matrix result.
|
||||
var matrix = Arrays.stream(craftingResult.matrixResult())
|
||||
.filter(Objects::nonNull).toList();
|
||||
|
||||
boolean isEmpty = matrix.stream().allMatch(itemStack -> itemStack.getType() == Material.AIR);
|
||||
|
||||
// Add any leftover items from the recipe e.g buckets.
|
||||
HashMap<Integer, ItemStack> craftingMatrixLeftOvers =
|
||||
isEmpty ? Maps.newHashMap()
|
||||
: tempOutput.addItem(craftingResult.matrixResult());
|
||||
: tempOutput.addItem(matrix.toArray(ItemStack[]::new));
|
||||
|
||||
//If result fits into output copy over the temporary inventories.
|
||||
if (map.isEmpty() && craftingMatrixLeftOvers.isEmpty()) {
|
||||
|
@ -113,10 +113,9 @@ public class InventoryListener implements Listener {
|
||||
}
|
||||
|
||||
private void craftingUpdate(InventoryInteractEvent event) {
|
||||
InventoryHolder holder = event.getInventory().getHolder();
|
||||
if (holder instanceof VirtualCraftingHolder) {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(ChestsPlusPlus.PLUGIN, (((VirtualCraftingHolder) holder).setUpdatingRecipe(true))::updateCrafting, 1);
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(ChestsPlusPlus.PLUGIN, (((VirtualCraftingHolder) holder))::forceUpdateInventory, 1);
|
||||
if (event.getInventory().getHolder() instanceof VirtualCraftingHolder vHolder) {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(ChestsPlusPlus.PLUGIN, () -> vHolder.setUpdatingRecipe(true).updateCrafting(event), 1);
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(ChestsPlusPlus.PLUGIN, vHolder::forceUpdateInventory, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
package com.jamesdpeters.minecraft.chests.misc;
|
||||
|
||||
public class OfflinePlayerUtil {
|
||||
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package com.jamesdpeters.minecraft.chests.players;
|
||||
|
||||
import com.jamesdpeters.minecraft.chests.reflection.craftbukkit.CraftPlayer;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.craftbukkit.CraftServer;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.craftbukkit.CraftWorld;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.minecraft.EntityPlayer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.PrepareItemCraftEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.world.WorldSaveEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PlayerStorage implements Listener {
|
||||
|
||||
private static final HashMap<UUID, Player> offlinePlayers = new HashMap<>();
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerLoginEvent event) {
|
||||
if (event.getResult() == PlayerLoginEvent.Result.ALLOWED) {
|
||||
var player = offlinePlayers.remove(event.getPlayer().getUniqueId());
|
||||
if (player != null) {
|
||||
player.saveData();
|
||||
event.getPlayer().loadData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onSave(WorldSaveEvent event) {
|
||||
offlinePlayers.forEach((uuid, player) -> {
|
||||
player.saveData();
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onCraft(PrepareItemCraftEvent event) {
|
||||
Player player = (Player) event.getView().getPlayer();
|
||||
player.giveExp(10);
|
||||
|
||||
Bukkit.broadcastMessage("Inventory type: "+player.getOpenInventory().getType());
|
||||
}
|
||||
|
||||
public static void runMethodOnOfflinePlayer(OfflinePlayer offlinePlayer, World world, Consumer<Player> playerConsumer) {
|
||||
Player player = getPlayer(offlinePlayer, world);
|
||||
if (player != null) {
|
||||
playerConsumer.accept(player);
|
||||
}
|
||||
}
|
||||
|
||||
private static Player getPlayer(OfflinePlayer offlinePlayer, World world) {
|
||||
Player player = offlinePlayer.getPlayer();
|
||||
if (player != null)
|
||||
return player;
|
||||
|
||||
player = offlinePlayers.get(offlinePlayer.getUniqueId());
|
||||
if (player != null)
|
||||
return player;
|
||||
|
||||
try {
|
||||
player = generateFakePlayer(offlinePlayer, world);
|
||||
offlinePlayers.put(offlinePlayer.getUniqueId(), player);
|
||||
return player;
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Player generateFakePlayer(OfflinePlayer offlinePlayer, World world) throws NoSuchMethodException {
|
||||
var craftServer = new CraftServer(Bukkit.getServer());
|
||||
var minecraftServer = craftServer.getServer();
|
||||
var craftWorld = new CraftWorld(world);
|
||||
var worldServer = craftWorld.getWorldServer();
|
||||
|
||||
var gameProfile = minecraftServer.getGameProfile(offlinePlayer.getUniqueId(), offlinePlayer.getName());
|
||||
var entityPlayer = new EntityPlayer(minecraftServer, worldServer, gameProfile);
|
||||
minecraftServer.loadEntity(entityPlayer);
|
||||
|
||||
var craftPlayer = new CraftPlayer(craftServer, entityPlayer);
|
||||
var player = craftPlayer.getOriginalObj();
|
||||
player.loadData();
|
||||
return player;
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.jamesdpeters.minecraft.chests.reflection.craftbukkit;
|
||||
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.BaseReflection;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.ReflectMethod;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.ReflectionUtil;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.minecraft.EntityPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Objects;
|
||||
|
||||
public class CraftPlayer extends BaseReflection<Player> {
|
||||
|
||||
public static final Class<?> clazz = ReflectionUtil.getCraftBukkitClass("entity.CraftPlayer");
|
||||
private static final Constructor<?> constructor = ReflectionUtil.getConstructor(clazz, CraftServer.clazz, EntityPlayer.clazz);
|
||||
|
||||
private static final ReflectMethod getHandle = ReflectionUtil.getMethod("getHandle", clazz);
|
||||
|
||||
static {
|
||||
assert clazz != null;
|
||||
assert constructor != null;
|
||||
}
|
||||
|
||||
public CraftPlayer(CraftServer craftServer, EntityPlayer entityPlayer) throws NoSuchMethodException {
|
||||
super(clazz, Objects.requireNonNull(constructor), craftServer, entityPlayer);
|
||||
}
|
||||
|
||||
public CraftPlayer(Player player) {
|
||||
super(clazz, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getOriginalObj() {
|
||||
return (Player) getHandle();
|
||||
}
|
||||
|
||||
public EntityPlayer getEntityPlayer() {
|
||||
return new EntityPlayer(getHandle.invoke(getHandle()));
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package com.jamesdpeters.minecraft.chests.reflection.craftbukkit;
|
||||
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.BaseReflection;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.ReflectMethod;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.ReflectionUtil;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.minecraft.MinecraftServer;
|
||||
import org.bukkit.Server;
|
||||
|
||||
public class CraftServer extends BaseReflection<Server> {
|
||||
|
||||
public static final Class<?> clazz = ReflectionUtil.getCraftBukkitClass("CraftServer");
|
||||
private static final ReflectMethod getServer = ReflectionUtil.getMethod("getServer", clazz);
|
||||
|
||||
static {
|
||||
assert clazz != null;
|
||||
assert getServer != null;
|
||||
}
|
||||
|
||||
public CraftServer(Server server) {
|
||||
super(clazz, server);
|
||||
}
|
||||
|
||||
public MinecraftServer getServer() {
|
||||
assert getServer != null;
|
||||
return new MinecraftServer(getServer.invoke(getOriginalObj()));
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package com.jamesdpeters.minecraft.chests.reflection.craftbukkit;
|
||||
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.BaseReflection;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.ReflectMethod;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.ReflectionUtil;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.minecraft.WorldServer;
|
||||
import org.bukkit.World;
|
||||
|
||||
public class CraftWorld extends BaseReflection<World> {
|
||||
|
||||
private static final Class<?> clazz = ReflectionUtil.getCraftBukkitClass("CraftWorld");
|
||||
|
||||
public static final ReflectMethod getHandle = ReflectionUtil.getMethod("getHandle", clazz);
|
||||
|
||||
static {
|
||||
assert clazz != null;
|
||||
assert getHandle != null;
|
||||
}
|
||||
|
||||
public CraftWorld(World world) {
|
||||
super(clazz, world);
|
||||
}
|
||||
|
||||
public WorldServer getWorldServer() {
|
||||
return new WorldServer(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.jamesdpeters.minecraft.chests.reflection.helpers;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class BaseReflection<T> {
|
||||
|
||||
protected Object handle;
|
||||
private final T originalObj;
|
||||
private final Class<?> clazz;
|
||||
|
||||
public BaseReflection(Class<?> clazz, T from) {
|
||||
assert clazz.isAssignableFrom(from.getClass());
|
||||
this.handle = clazz.cast(from);
|
||||
this.clazz = clazz;
|
||||
this.originalObj = from;
|
||||
}
|
||||
|
||||
public BaseReflection(Class<?> clazz, Constructor<?> constructor, BaseReflection<?>... parameters) throws NoSuchMethodException {
|
||||
this.clazz = clazz;
|
||||
this.originalObj = null;
|
||||
try {
|
||||
var handles = Arrays.stream(parameters).map(BaseReflection::getHandle).toArray();
|
||||
this.handle = constructor.newInstance(handles);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public T getOriginalObj() {
|
||||
return originalObj;
|
||||
}
|
||||
|
||||
public Object getHandle() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
public Class<?> getClazz() {
|
||||
return clazz;
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.jamesdpeters.minecraft.chests.reflection.helpers;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ReflectMethod {
|
||||
|
||||
private final Method method;
|
||||
|
||||
public ReflectMethod(Method method) {
|
||||
method.setAccessible(true);
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public Object invoke(Object instance, Object... args) {
|
||||
try {
|
||||
return method.invoke(instance, args);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package com.jamesdpeters.minecraft.chests.reflection.helpers;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
public class ReflectionUtil {
|
||||
|
||||
private static final String version;
|
||||
|
||||
static {
|
||||
String packageName = Bukkit.getServer().getClass().getPackage().getName();
|
||||
var tempVersion = packageName.substring(packageName.lastIndexOf(".") + 1);
|
||||
if (tempVersion.equals("craftbukkit"))
|
||||
version = "";
|
||||
else version = tempVersion;
|
||||
}
|
||||
|
||||
public static String getNmsPrefix() {
|
||||
return "net.minecraft.server." + getVersionPrefix() ;
|
||||
}
|
||||
|
||||
private static String getVersionPrefix() {
|
||||
return version.isEmpty() ? "" : version + ".";
|
||||
}
|
||||
|
||||
public static String getCraftBukkitPrefix() {
|
||||
return "org.bukkit.craftbukkit." +getVersionPrefix();
|
||||
}
|
||||
|
||||
public static Class<?> getNmsClass(String name) {
|
||||
return getClass("net.minecraft.server." + name , false);
|
||||
}
|
||||
|
||||
public static Class<?> getNbtClass(String name) {
|
||||
return getClass("net.minecraft.nbt." + name , false);
|
||||
}
|
||||
|
||||
public static Class<?> getNmsClassAsArray(String name) {
|
||||
return getClass("net.minecraft.server." + name , true);
|
||||
}
|
||||
|
||||
public static Class<?> getCraftBukkitClass(String name) {
|
||||
return getClass("org.bukkit.craftbukkit." + getVersionPrefix() + name , false);
|
||||
}
|
||||
|
||||
public static Class<?> getCraftBukkitClassAsArray(String name) {
|
||||
return getClass("org.bukkit.craftbukkit." + getVersionPrefix() + name , true);
|
||||
}
|
||||
|
||||
public static Class<?> getMojangAuthClass(String name) {
|
||||
return getClass("com.mojang.authlib." + name , false);
|
||||
}
|
||||
|
||||
private static Class<?> getClass(String name, boolean asArray) {
|
||||
try {
|
||||
if(asArray) return Array.newInstance(Class.forName(name), 0).getClass();
|
||||
else return Class.forName(name);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static ReflectMethod getMethod(String name , Class<?> clazz , Class<?>... parameterClasses) {
|
||||
try {
|
||||
return new ReflectMethod(clazz.getDeclaredMethod(name, parameterClasses));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Constructor<?> getConstructor(Class<?> clazz, Class<?>... constructorParameters) {
|
||||
try {
|
||||
return clazz.getConstructor(constructorParameters);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.jamesdpeters.minecraft.chests.reflection.minecraft;
|
||||
|
||||
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.BaseReflection;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.ReflectMethod;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.ReflectionUtil;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.mojangauth.GameProfile;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Objects;
|
||||
|
||||
public class EntityPlayer extends BaseReflection<Object> {
|
||||
|
||||
public static final Class<?> clazz = ReflectionUtil.getNmsClass("level.EntityPlayer");
|
||||
private static final Constructor<?> constructor = ReflectionUtil.getConstructor(clazz, MinecraftServer.clazz, WorldServer.clazz, GameProfile.clazz);
|
||||
|
||||
private static final Class<?> nbtTagCompoundClazz = ReflectionUtil.getNbtClass("NBTTagCompound");
|
||||
private static final ReflectMethod loadGameTypes = ReflectionUtil.getMethod("loadGameTypes", clazz, nbtTagCompoundClazz);
|
||||
|
||||
static {
|
||||
assert clazz != null;
|
||||
assert constructor != null;
|
||||
}
|
||||
|
||||
public EntityPlayer(MinecraftServer minecraftServer, WorldServer worldServer, GameProfile gameProfile) throws NoSuchMethodException {
|
||||
super(clazz, Objects.requireNonNull(constructor), minecraftServer, worldServer, gameProfile);
|
||||
}
|
||||
|
||||
public EntityPlayer(Object object) {
|
||||
super(clazz, object);
|
||||
}
|
||||
|
||||
public void loadGameTypes(Object nbtTagCompound) {
|
||||
Object tag = nbtTagCompoundClazz.cast(nbtTagCompound);
|
||||
loadGameTypes.invoke(getHandle(), tag);
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package com.jamesdpeters.minecraft.chests.reflection.minecraft;
|
||||
|
||||
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.BaseReflection;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.ReflectMethod;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.ReflectionUtil;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.mojangauth.GameProfile;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MinecraftServer extends BaseReflection<Object> {
|
||||
|
||||
public static final Class<?> clazz = ReflectionUtil.getNmsClass("MinecraftServer");
|
||||
private static final Class<?> userCache = ReflectionUtil.getNmsClass("players.UserCache");
|
||||
private static final Class<?> playerList = ReflectionUtil.getNmsClass("players.PlayerList");
|
||||
|
||||
|
||||
private static final ReflectMethod getProfileCache = ReflectionUtil.getMethod("getProfileCache", clazz);
|
||||
private static final ReflectMethod userCache_get = ReflectionUtil.getMethod("get", userCache, UUID.class);
|
||||
|
||||
private static final ReflectMethod getPlayerList = ReflectionUtil.getMethod("getPlayerList", clazz);
|
||||
private static final ReflectMethod playerList_loadEntity = ReflectionUtil.getMethod("load", playerList, EntityPlayer.clazz);
|
||||
private static final ReflectMethod playerList_saveEntity = ReflectionUtil.getMethod("save", playerList, EntityPlayer.clazz);
|
||||
|
||||
static {
|
||||
assert clazz != null;
|
||||
assert userCache_get != null;
|
||||
assert getProfileCache != null;
|
||||
assert userCache_get != null;
|
||||
}
|
||||
|
||||
public MinecraftServer(Object dediServer) {
|
||||
super(clazz, dediServer);
|
||||
}
|
||||
|
||||
public GameProfile getGameProfile(UUID uuid, String defaultName) {
|
||||
assert getProfileCache != null;
|
||||
var profileCache = getProfileCache.invoke(getHandle());
|
||||
var opt = userCache_get.invoke(profileCache, uuid);
|
||||
return GameProfile.fromOptional((Optional<?>) opt, uuid, defaultName);
|
||||
}
|
||||
|
||||
public void loadEntity(EntityPlayer entityPlayer) {
|
||||
var playerList = getPlayerList.invoke(getHandle());
|
||||
var result = playerList_loadEntity.invoke(playerList, entityPlayer.getHandle());
|
||||
entityPlayer.loadGameTypes(result);
|
||||
}
|
||||
|
||||
public void saveEntity(EntityPlayer entityPlayer) {
|
||||
var playerList = getPlayerList.invoke(getHandle());
|
||||
playerList_saveEntity.invoke(playerList, entityPlayer.getHandle());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package com.jamesdpeters.minecraft.chests.reflection.minecraft;
|
||||
|
||||
import com.jamesdpeters.minecraft.chests.reflection.craftbukkit.CraftWorld;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.BaseReflection;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.ReflectionUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class WorldServer extends BaseReflection<Object> {
|
||||
|
||||
public static final Class<?> clazz = ReflectionUtil.getNmsClass("level.WorldServer");
|
||||
|
||||
static {
|
||||
assert clazz != null;
|
||||
}
|
||||
|
||||
public WorldServer(CraftWorld craftWorld) {
|
||||
super(clazz, Objects.requireNonNull(CraftWorld.getHandle).invoke(craftWorld.getHandle()));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.jamesdpeters.minecraft.chests.reflection.mojangauth;
|
||||
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.BaseReflection;
|
||||
import com.jamesdpeters.minecraft.chests.reflection.helpers.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GameProfile extends BaseReflection<Object> {
|
||||
|
||||
public static final Class<?> clazz = ReflectionUtil.getMojangAuthClass("GameProfile");
|
||||
private static final Constructor<?> constructor = ReflectionUtil.getConstructor(clazz, UUID.class, String.class);
|
||||
|
||||
public GameProfile(Object from) {
|
||||
super(clazz, from);
|
||||
}
|
||||
|
||||
public static GameProfile fromOptional(Optional<?> from, UUID defaultUUID, String defaultName) {
|
||||
return new GameProfile(from.orElseGet(() -> {
|
||||
try {
|
||||
constructor.newInstance(defaultName, defaultName);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}));
|
||||
}
|
||||
}
|
@ -7,14 +7,12 @@ import org.bukkit.Keyed;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.bukkit.configuration.serialization.SerializableAs;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.Recipe;
|
||||
import org.bukkit.inventory.ShapedRecipe;
|
||||
import org.bukkit.inventory.ShapelessRecipe;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@SerializableAs("C++Recipe")
|
||||
@ -25,10 +23,12 @@ public class RecipeSerializable implements ConfigurationSerializable {
|
||||
|
||||
// Store items used for ComplexRecipes
|
||||
private ItemStack[] items;
|
||||
private ItemStack[] returnedItems; // Stores and items returned from the recipe. i.e Buckets/bottles etc.
|
||||
|
||||
public RecipeSerializable(Recipe recipe, ItemStack[] items) {
|
||||
public RecipeSerializable(Recipe recipe, ItemStack[] items, ItemStack[] returnedItems) {
|
||||
this.recipe = recipe;
|
||||
this.items = items;
|
||||
this.returnedItems = returnedItems;
|
||||
if (recipe instanceof Keyed){
|
||||
namespacedKey = ((Keyed) recipe).getKey();
|
||||
}
|
||||
@ -37,18 +37,22 @@ public class RecipeSerializable implements ConfigurationSerializable {
|
||||
public RecipeSerializable(Map<String, Object> map) {
|
||||
Object obj = map.get("items");
|
||||
if (obj != null) {
|
||||
//noinspection unchecked
|
||||
items = (ItemStack[]) obj;
|
||||
}
|
||||
|
||||
Object retItems = map.get("returnedItems");
|
||||
if (retItems != null) {
|
||||
returnedItems = (ItemStack[]) retItems;
|
||||
}
|
||||
|
||||
//noinspection deprecation
|
||||
namespacedKey = new NamespacedKey((String) map.get("namespace"), (String) map.get("key"));
|
||||
recipe = Crafting.getRecipeByKey(namespacedKey);
|
||||
}
|
||||
|
||||
public void updateRecipe(Player player) {
|
||||
public void updateRecipe() {
|
||||
if (recipe == null) {
|
||||
recipe = ApiSpecific.getNmsProvider().getCraftingProvider().getRecipe(player, Bukkit.getWorlds().get(0), items);
|
||||
recipe = ApiSpecific.getNmsProvider().getCraftingProvider().getRecipe(Bukkit.getWorlds().get(0), items);
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,6 +63,7 @@ public class RecipeSerializable implements ConfigurationSerializable {
|
||||
map.put("key", namespacedKey.getKey());
|
||||
if (!(recipe instanceof ShapedRecipe || recipe instanceof ShapelessRecipe)) {
|
||||
map.put("items", items);
|
||||
map.put("returnedItems", returnedItems);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
@ -74,4 +79,8 @@ public class RecipeSerializable implements ConfigurationSerializable {
|
||||
public ItemStack[] getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public ItemStack[] getReturnedItems() {
|
||||
return returnedItems;
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public class AutoCraftingStorage extends AbstractStorage implements Configuratio
|
||||
recipeSerializable = (RecipeSerializable) map.get("recipe");
|
||||
//If autocraft doesn't have a recipe in it it will be throw a NPE, this check seems to be working. Also the exception caused data loss in the data file
|
||||
if (recipeSerializable != null) {
|
||||
recipeSerializable.updateRecipe(getOwner().getPlayer());
|
||||
recipeSerializable.updateRecipe();
|
||||
}
|
||||
identifier = (String) map.get("identifier");
|
||||
initInventory();
|
||||
@ -63,12 +63,12 @@ public class AutoCraftingStorage extends AbstractStorage implements Configuratio
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setRecipe(Recipe recipe, ItemStack[] items) {
|
||||
public void setRecipe(Recipe recipe, ItemStack[] items, ItemStack[] returnedItems) {
|
||||
if (recipe == null) {
|
||||
recipeSerializable = null;
|
||||
return;
|
||||
}
|
||||
recipeSerializable = new RecipeSerializable(recipe, items);
|
||||
recipeSerializable = new RecipeSerializable(recipe, items, returnedItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -109,7 +109,7 @@ public class AutoCraftingStorage extends AbstractStorage implements Configuratio
|
||||
virtualCraftingHolder.setCrafting((ShapedRecipe) recipe);
|
||||
}
|
||||
else {
|
||||
virtualCraftingHolder.setCrafting(recipe, recipeSerializable.getItems());
|
||||
virtualCraftingHolder.setCrafting(recipe, recipeSerializable.getItems(), recipeSerializable.getReturnedItems());
|
||||
}
|
||||
} else {
|
||||
virtualCraftingHolder.resetChoices();
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Chests++ Language File (Version 2.5.2-BETA-2)
|
||||
# Chests++ Language File (Version 2.5.2-BETA-3)
|
||||
# NOTE: This file gets replaced when the plugin launches! If you want to make modifications create a copy first!
|
||||
# To create a new language file simply create a copy of this file and rename it to your desired choice for example 'en_US.properties'
|
||||
# It should be located in the 'lang' folder
|
||||
|
Loading…
Reference in New Issue
Block a user