Mirror von
https://github.com/ViaVersion/ViaVersion.git
synchronisiert 2024-12-26 08:10:09 +01:00
Support item provider on a 1.8 server
... 1.9 is on the way
Dieser Commit ist enthalten in:
Ursprung
976c418c9e
Commit
b3d3921f6e
@ -1,22 +1,55 @@
|
|||||||
package us.myles.ViaVersion.bukkit.protocol1_12to1_11_1;
|
package us.myles.ViaVersion.bukkit.protocol1_12to1_11_1;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import us.myles.ViaVersion.bukkit.providers.BukkitInvContainerItemProvider;
|
import us.myles.ViaVersion.bukkit.providers.BukkitInvContainerItemProvider;
|
||||||
|
import us.myles.ViaVersion.protocols.protocol1_12to1_11_1.storage.InvItemStorage;
|
||||||
|
|
||||||
public class BukkitInvContainerUpdateTask implements Runnable {
|
public class BukkitInvContainerUpdateTask implements Runnable {
|
||||||
|
|
||||||
private BukkitInvContainerItemProvider provider;
|
private BukkitInvContainerItemProvider provider;
|
||||||
private UUID uuid;
|
private final UUID uuid;
|
||||||
|
private final List<InvItemStorage> items;
|
||||||
|
|
||||||
public BukkitInvContainerUpdateTask(BukkitInvContainerItemProvider provider, UUID uuid) {
|
public BukkitInvContainerUpdateTask(BukkitInvContainerItemProvider provider, UUID uuid) {
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
|
this.items = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItem(short windowId, short slotId, short anumber) {
|
||||||
|
InvItemStorage storage = new InvItemStorage(windowId, slotId, anumber);
|
||||||
|
items.add(storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// TODO Auto-generated method stub
|
Player p = Bukkit.getServer().getPlayer(uuid);
|
||||||
provider.onTaskExecuted(uuid);
|
if (p == null) {
|
||||||
|
provider.onTaskExecuted(uuid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
synchronized (items) {
|
||||||
|
for (InvItemStorage storage : items) {
|
||||||
|
Object packet = provider.buildWindowClickPacket(p, storage);
|
||||||
|
boolean result = provider.sendPlayer(p, packet);
|
||||||
|
System.out.println("item result: " + result);
|
||||||
|
if (!result) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("items: " + items);
|
||||||
|
items.clear();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
provider.onTaskExecuted(uuid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,28 +1,167 @@
|
|||||||
package us.myles.ViaVersion.bukkit.providers;
|
package us.myles.ViaVersion.bukkit.providers;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.InventoryView;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
|
|
||||||
import us.myles.ViaVersion.api.data.UserConnection;
|
import us.myles.ViaVersion.api.data.UserConnection;
|
||||||
|
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
|
||||||
import us.myles.ViaVersion.bukkit.protocol1_12to1_11_1.BukkitInvContainerUpdateTask;
|
import us.myles.ViaVersion.bukkit.protocol1_12to1_11_1.BukkitInvContainerUpdateTask;
|
||||||
|
import us.myles.ViaVersion.bukkit.util.NMSUtil;
|
||||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||||
import us.myles.ViaVersion.protocols.protocol1_12to1_11_1.providers.InvContainerItemProvider;
|
import us.myles.ViaVersion.protocols.protocol1_12to1_11_1.providers.InvContainerItemProvider;
|
||||||
|
import us.myles.ViaVersion.protocols.protocol1_12to1_11_1.storage.InvItemStorage;
|
||||||
|
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||||
|
|
||||||
public class BukkitInvContainerItemProvider extends InvContainerItemProvider {
|
public class BukkitInvContainerItemProvider extends InvContainerItemProvider {
|
||||||
|
|
||||||
private static Map<UUID, BukkitInvContainerUpdateTask> updateTasks = new ConcurrentHashMap<>();
|
private static Map<UUID, BukkitInvContainerUpdateTask> updateTasks = new ConcurrentHashMap<>();
|
||||||
|
private boolean supported;
|
||||||
|
// packet class
|
||||||
|
private Class<?> wclickPacketClass;
|
||||||
|
// Use for nms
|
||||||
|
private Method nmsItemMethod;
|
||||||
|
private Method ephandle;
|
||||||
|
private Field connection;
|
||||||
|
private Method packetMethod;
|
||||||
|
|
||||||
|
public BukkitInvContainerItemProvider() {
|
||||||
|
this.supported = isSupported();
|
||||||
|
setupReflection();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean registerInvClickPacket(short windowId, short slotId, short anumber, UserConnection uconnection) {
|
public boolean registerInvClickPacket(short windowId, short slotId, short anumber, UserConnection uconnection) {
|
||||||
|
if (!supported) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
ProtocolInfo info = uconnection.get(ProtocolInfo.class);
|
ProtocolInfo info = uconnection.get(ProtocolInfo.class);
|
||||||
// TODO: lets add some stuff here :)
|
UUID uuid = info.getUuid();
|
||||||
|
BukkitInvContainerUpdateTask utask = updateTasks.get(uuid);
|
||||||
|
final boolean registered = utask != null;
|
||||||
|
if (!registered) {
|
||||||
|
utask = new BukkitInvContainerUpdateTask(this, uuid);
|
||||||
|
updateTasks.put(uuid, utask);
|
||||||
|
}
|
||||||
// http://wiki.vg/index.php?title=Protocol&oldid=13223#Click_Window
|
// http://wiki.vg/index.php?title=Protocol&oldid=13223#Click_Window
|
||||||
System.out.println("info: " + info + " QUICK ACTION windowId: " + windowId + " slotId: " + slotId + " button: " + 0 + " anumber: " + anumber + " mode: " + 1);
|
utask.addItem(windowId, slotId, anumber);
|
||||||
return false; // change to true once supported
|
if (!registered) {
|
||||||
|
scheduleTask(utask);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object buildWindowClickPacket(Player p, InvItemStorage storage) {
|
||||||
|
if (!supported) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
InventoryView inv = p.getOpenInventory();
|
||||||
|
short slotId = storage.getSlotId();
|
||||||
|
if (slotId > inv.countSlots()) {
|
||||||
|
return null; // wrong container open?
|
||||||
|
}
|
||||||
|
ItemStack itemstack = inv.getItem(slotId);
|
||||||
|
if (itemstack == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Object cinstance = null;
|
||||||
|
try {
|
||||||
|
Object nmsItem = nmsItemMethod.invoke(null, itemstack);
|
||||||
|
// TODO: PASSTHROUGH PROTOCOLS? (Make InvItemStorage inheritance from Item?)
|
||||||
|
cinstance = wclickPacketClass.newInstance();
|
||||||
|
ReflectionUtil.set(cinstance, "a", (int) storage.getWindowId());
|
||||||
|
ReflectionUtil.set(cinstance, "slot", (int) slotId);
|
||||||
|
ReflectionUtil.set(cinstance, "button", 0); // shift + left mouse click
|
||||||
|
ReflectionUtil.set(cinstance, "d", storage.getActionNumber());
|
||||||
|
ReflectionUtil.set(cinstance, "item", nmsItem);
|
||||||
|
// TODO: THIS MUST BE AN ENUM on 1.9+ SERVERS!!
|
||||||
|
ReflectionUtil.set(cinstance, "shift", 1); // mode
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return cinstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sendPlayer(Player p, Object packet) {
|
||||||
|
if (packet == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Object entityPlayer = ephandle.invoke(p);
|
||||||
|
Object pconnection = connection.get(entityPlayer);
|
||||||
|
// send
|
||||||
|
packetMethod.invoke(pconnection, packet);
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onTaskExecuted(UUID uuid) {
|
public void onTaskExecuted(UUID uuid) {
|
||||||
updateTasks.remove(uuid);
|
updateTasks.remove(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void scheduleTask(BukkitInvContainerUpdateTask utask) {
|
||||||
|
BukkitScheduler scheduler = Bukkit.getServer().getScheduler();
|
||||||
|
Plugin instance = Bukkit.getServer().getPluginManager().getPlugin("ViaVersion");
|
||||||
|
scheduler.runTaskLater(instance, utask, 5); // 5 ticks later.
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupReflection() {
|
||||||
|
if (!supported) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.wclickPacketClass = NMSUtil.nms("PacketPlayInWindowClick");
|
||||||
|
Class<?> citemStack = NMSUtil.obc("inventory.CraftItemStack");
|
||||||
|
this.nmsItemMethod = citemStack.getDeclaredMethod("asNMSCopy", ItemStack.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
this.supported = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.ephandle = NMSUtil.obc("entity.CraftPlayer").getDeclaredMethod("getHandle");
|
||||||
|
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||||
|
this.supported = false;
|
||||||
|
throw new RuntimeException("Couldn't find CraftPlayer", e);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.connection = NMSUtil.nms("EntityPlayer").getDeclaredField("playerConnection");
|
||||||
|
} catch (NoSuchFieldException | ClassNotFoundException e) {
|
||||||
|
this.supported = false;
|
||||||
|
throw new RuntimeException("Couldn't find Player Connection", e);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.packetMethod = NMSUtil.nms("PlayerConnection").getDeclaredMethod("a", wclickPacketClass);
|
||||||
|
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||||
|
this.supported = false;
|
||||||
|
throw new RuntimeException("Couldn't find CraftPlayer", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSupported() {
|
||||||
|
int protocolId = ProtocolRegistry.SERVER_PROTOCOL;
|
||||||
|
if (protocolId == 47) {
|
||||||
|
return true; // 1.8
|
||||||
|
} /**else if (protocolId >= 107 && protocolId <= 110) {
|
||||||
|
return true; // 1.9
|
||||||
|
} else if (protocolId == 210) {
|
||||||
|
return true; // 1.10
|
||||||
|
} else if (protocolId == 315 || protocolId == 316) {
|
||||||
|
return true; // 1.11
|
||||||
|
}*/
|
||||||
|
// this is not needed on 1.12+
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,8 +2,10 @@ package us.myles.ViaVersion.protocols.protocol1_12to1_11_1.storage;
|
|||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
@ToString
|
||||||
@Getter
|
@Getter
|
||||||
public class InvItemStorage {
|
public class InvItemStorage {
|
||||||
|
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren