mirror of
https://github.com/amalthea-mc/ShopChest.git
synced 2024-11-22 10:22:29 +00:00
Change FakeArmorStand structure to implement FakeItem
This commit is contained in:
parent
2fda9bbf8d
commit
a7bc054dce
@ -3,18 +3,10 @@ package de.epiceric.shopchest.nms;
|
|||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.util.UUID;
|
public interface FakeArmorStand extends FakeEntity {
|
||||||
|
|
||||||
public interface FakeArmorStand {
|
|
||||||
|
|
||||||
int getEntityId();
|
|
||||||
|
|
||||||
void sendData(String name, Iterable<Player> receivers);
|
void sendData(String name, Iterable<Player> receivers);
|
||||||
|
|
||||||
void remove(Iterable<Player> receivers);
|
|
||||||
|
|
||||||
void setLocation(Location location, Iterable<Player> receivers);
|
void setLocation(Location location, Iterable<Player> receivers);
|
||||||
|
|
||||||
void spawn(UUID uuid, Location location, Iterable<Player> receivers);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
package de.epiceric.shopchest.nms;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface FakeEntity {
|
||||||
|
|
||||||
|
int getEntityId();
|
||||||
|
|
||||||
|
void spawn(UUID uuid, Location location, Iterable<Player> receivers);
|
||||||
|
|
||||||
|
void remove(Iterable<Player> receivers);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package de.epiceric.shopchest.nms;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
public interface FakeItem extends FakeEntity{
|
||||||
|
|
||||||
|
void sendData(ItemStack item, Iterable<Player> receivers);
|
||||||
|
|
||||||
|
}
|
@ -4,4 +4,6 @@ public interface Platform {
|
|||||||
|
|
||||||
FakeArmorStand createFakeArmorStand();
|
FakeArmorStand createFakeArmorStand();
|
||||||
|
|
||||||
|
FakeItem createFakeItem();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,115 +6,75 @@ import net.md_5.bungee.api.chat.TextComponent;
|
|||||||
import net.md_5.bungee.chat.ComponentSerializer;
|
import net.md_5.bungee.chat.ComponentSerializer;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.network.protocol.Packet;
|
|
||||||
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
|
|
||||||
import net.minecraft.network.protocol.game.ClientboundRemoveEntityPacket;
|
|
||||||
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
|
|
||||||
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
|
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
|
||||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||||
import net.minecraft.network.syncher.SynchedEntityData;
|
import net.minecraft.network.syncher.SynchedEntityData;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.EntityType;
|
import net.minecraft.world.entity.EntityType;
|
||||||
import net.minecraft.world.phys.Vec3;
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
public class FakeArmorStandImpl implements FakeArmorStand {
|
public class FakeArmorStandImpl extends FakeEntityImpl<String> implements FakeArmorStand {
|
||||||
|
|
||||||
private final static byte INVISIBLE_FLAG = 0b100000;
|
private final static byte INVISIBLE_FLAG = 0b100000;
|
||||||
private final static AtomicInteger ENTITY_COUNTER;
|
|
||||||
protected static final EntityDataAccessor<Byte> DATA_SHARED_FLAGS_ID;
|
protected static final EntityDataAccessor<Byte> DATA_SHARED_FLAGS_ID;
|
||||||
private static final EntityDataAccessor<Boolean> DATA_NO_GRAVITY;
|
|
||||||
private static final EntityDataAccessor<Optional<Component>> DATA_CUSTOM_NAME;
|
private static final EntityDataAccessor<Optional<Component>> DATA_CUSTOM_NAME;
|
||||||
private static final EntityDataAccessor<Boolean> DATA_CUSTOM_NAME_VISIBLE;
|
private static final EntityDataAccessor<Boolean> DATA_CUSTOM_NAME_VISIBLE;
|
||||||
private static final EntityDataAccessor<Boolean> DATA_SILENT;
|
|
||||||
private final static Field packedItemField;
|
|
||||||
private final static float MARKER_ARMOR_STAND_OFFSET = 1.975f;
|
private final static float MARKER_ARMOR_STAND_OFFSET = 1.975f;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
final Field entityCounterField = Entity.class.getDeclaredField("b"); // ENTITY_COUNTER
|
|
||||||
ENTITY_COUNTER = (AtomicInteger) entityCounterField.get(null);
|
|
||||||
final Field dataSharedFlagsId = Entity.class.getDeclaredField("Z"); // DATA_SHARED_FLAGS_ID
|
final Field dataSharedFlagsId = Entity.class.getDeclaredField("Z"); // DATA_SHARED_FLAGS_ID
|
||||||
DATA_SHARED_FLAGS_ID = forceCast(dataSharedFlagsId.get(null));
|
DATA_SHARED_FLAGS_ID = FakeEntityImpl.forceCast(dataSharedFlagsId.get(null));
|
||||||
final Field dataNoGravityField = Entity.class.getDeclaredField("aM"); // DATA_NO_GRAVITY
|
|
||||||
DATA_NO_GRAVITY = forceCast(dataNoGravityField.get(null));
|
|
||||||
final Field dataCustomNameField = Entity.class.getDeclaredField("aJ"); // DATA_CUSTOM_NAME
|
final Field dataCustomNameField = Entity.class.getDeclaredField("aJ"); // DATA_CUSTOM_NAME
|
||||||
DATA_CUSTOM_NAME = forceCast(dataCustomNameField.get(null));
|
DATA_CUSTOM_NAME = FakeEntityImpl.forceCast(dataCustomNameField.get(null));
|
||||||
final Field dataCustomNameVisibleField = Entity.class.getDeclaredField("aK"); // DATA_CUSTOM_NAME_VISIBLE
|
final Field dataCustomNameVisibleField = Entity.class.getDeclaredField("aK"); // DATA_CUSTOM_NAME_VISIBLE
|
||||||
DATA_CUSTOM_NAME_VISIBLE = forceCast(dataCustomNameVisibleField.get(null));
|
DATA_CUSTOM_NAME_VISIBLE = FakeEntityImpl.forceCast(dataCustomNameVisibleField.get(null));
|
||||||
final Field dataSilentField = Entity.class.getDeclaredField("aL"); // DATA_SILENT
|
|
||||||
DATA_SILENT = forceCast(dataSilentField.get(null));
|
|
||||||
packedItemField = ClientboundSetEntityDataPacket.class.getDeclaredField("b"); // packedItems
|
|
||||||
} catch (ReflectiveOperationException e){
|
} catch (ReflectiveOperationException e){
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static <T> T forceCast(Object o){
|
|
||||||
return (T) o;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final int entityId;
|
|
||||||
|
|
||||||
public FakeArmorStandImpl() {
|
public FakeArmorStandImpl() {
|
||||||
entityId = ENTITY_COUNTER.incrementAndGet();
|
super();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getEntityId() {
|
|
||||||
return entityId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendPacket(Packet<?> packet, Iterable<Player> receivers){
|
|
||||||
for(Player receiver : receivers){
|
|
||||||
((CraftPlayer)receiver).getHandle().connection.send(packet);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendData(String name, Iterable<Player> receivers) {
|
public void sendData(String name, Iterable<Player> receivers) {
|
||||||
// Create packet
|
sendData(receivers, name);
|
||||||
final SynchedEntityData entityData = new SynchedEntityData(null);
|
|
||||||
final ClientboundSetEntityDataPacket dataPacket = new ClientboundSetEntityDataPacket(entityId, entityData, false);
|
|
||||||
final List<SynchedEntityData.DataItem<?>> packedItems = new ArrayList<>(5);
|
|
||||||
|
|
||||||
// Setup data
|
|
||||||
packedItems.add(new SynchedEntityData.DataItem<>(DATA_SHARED_FLAGS_ID, INVISIBLE_FLAG));
|
|
||||||
packedItems.add(new SynchedEntityData.DataItem<>(DATA_NO_GRAVITY, true));
|
|
||||||
packedItems.add(new SynchedEntityData.DataItem<>(DATA_CUSTOM_NAME, Optional.ofNullable(
|
|
||||||
Component.Serializer.fromJson(
|
|
||||||
ComponentSerializer.toString(
|
|
||||||
TextComponent.fromLegacyText(name)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)));
|
|
||||||
packedItems.add(new SynchedEntityData.DataItem<>(DATA_CUSTOM_NAME_VISIBLE, true));
|
|
||||||
packedItems.add(new SynchedEntityData.DataItem<>(DATA_SILENT, true));
|
|
||||||
|
|
||||||
try {
|
|
||||||
packedItemField.set(dataPacket, packedItems);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send packet
|
|
||||||
sendPacket(dataPacket, receivers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(Iterable<Player> receivers) {
|
protected EntityType<?> getEntityType() {
|
||||||
final ClientboundRemoveEntityPacket removePacket = new ClientboundRemoveEntityPacket(entityId);
|
return EntityType.ARMOR_STAND;
|
||||||
sendPacket(removePacket, receivers);
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float getSpawnOffSet() {
|
||||||
|
return MARKER_ARMOR_STAND_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getDataItemCount() {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addSpecificData(List<SynchedEntityData.DataItem<?>> packedItems, String name) {
|
||||||
|
packedItems.add(new SynchedEntityData.DataItem<>(DATA_SHARED_FLAGS_ID, INVISIBLE_FLAG));
|
||||||
|
packedItems.add(new SynchedEntityData.DataItem<>(DATA_CUSTOM_NAME, Optional.ofNullable(
|
||||||
|
Component.Serializer.fromJson(
|
||||||
|
ComponentSerializer.toString(
|
||||||
|
TextComponent.fromLegacyText(name)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)));
|
||||||
|
packedItems.add(new SynchedEntityData.DataItem<>(DATA_CUSTOM_NAME_VISIBLE, true));
|
||||||
|
// TODO Add Marker (specific to ArmorStand)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -131,20 +91,4 @@ public class FakeArmorStandImpl implements FakeArmorStand {
|
|||||||
sendPacket(positionPacket, receivers);
|
sendPacket(positionPacket, receivers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void spawn(UUID uuid, Location location, Iterable<Player> receivers) {
|
|
||||||
final ClientboundAddEntityPacket spawnPacket = new ClientboundAddEntityPacket(
|
|
||||||
entityId,
|
|
||||||
uuid,
|
|
||||||
location.getX(),
|
|
||||||
location.getY() + MARKER_ARMOR_STAND_OFFSET,
|
|
||||||
location.getZ(),
|
|
||||||
0f,
|
|
||||||
0f,
|
|
||||||
EntityType.ARMOR_STAND,
|
|
||||||
0,
|
|
||||||
Vec3.ZERO
|
|
||||||
);
|
|
||||||
sendPacket(spawnPacket, receivers);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,120 @@
|
|||||||
|
package de.epiceric.shopchest.nms.v1_17_R1;
|
||||||
|
|
||||||
|
import de.epiceric.shopchest.nms.FakeEntity;
|
||||||
|
import net.minecraft.network.protocol.Packet;
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundRemoveEntityPacket;
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
|
||||||
|
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||||
|
import net.minecraft.network.syncher.SynchedEntityData;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.EntityType;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
public abstract class FakeEntityImpl<T> implements FakeEntity {
|
||||||
|
|
||||||
|
private final static AtomicInteger ENTITY_COUNTER;
|
||||||
|
private final static EntityDataAccessor<Boolean> DATA_NO_GRAVITY;
|
||||||
|
private final static EntityDataAccessor<Boolean> DATA_SILENT;
|
||||||
|
private final static Field packedItemField;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
final Field entityCounterField = Entity.class.getDeclaredField("b"); // ENTITY_COUNTER
|
||||||
|
ENTITY_COUNTER = (AtomicInteger) entityCounterField.get(null);
|
||||||
|
final Field dataNoGravityField = Entity.class.getDeclaredField("aM"); // DATA_NO_GRAVITY
|
||||||
|
DATA_NO_GRAVITY = forceCast(dataNoGravityField.get(null));
|
||||||
|
final Field dataSilentField = Entity.class.getDeclaredField("aL"); // DATA_SILENT
|
||||||
|
DATA_SILENT = forceCast(dataSilentField.get(null));
|
||||||
|
packedItemField = ClientboundSetEntityDataPacket.class.getDeclaredField("b"); // packedItems
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected static <T> T forceCast(Object o){
|
||||||
|
return (T) o;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final int entityId;
|
||||||
|
|
||||||
|
public FakeEntityImpl() {
|
||||||
|
entityId = ENTITY_COUNTER.incrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getEntityId() {
|
||||||
|
return entityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void sendPacket(Packet<?> packet, Iterable<Player> receivers){
|
||||||
|
for(Player receiver : receivers){
|
||||||
|
((CraftPlayer)receiver).getHandle().connection.send(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void spawn(UUID uuid, Location location, Iterable<Player> receivers) {
|
||||||
|
final ClientboundAddEntityPacket spawnPacket = new ClientboundAddEntityPacket(
|
||||||
|
entityId,
|
||||||
|
uuid,
|
||||||
|
location.getX(),
|
||||||
|
location.getY() + getSpawnOffSet(),
|
||||||
|
location.getZ(),
|
||||||
|
0f,
|
||||||
|
0f,
|
||||||
|
getEntityType(),
|
||||||
|
0,
|
||||||
|
Vec3.ZERO
|
||||||
|
);
|
||||||
|
sendPacket(spawnPacket, receivers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(Iterable<Player> receivers) {
|
||||||
|
final ClientboundRemoveEntityPacket removePacket = new ClientboundRemoveEntityPacket(entityId);
|
||||||
|
sendPacket(removePacket, receivers);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void sendData(Iterable<Player> receivers, T data){
|
||||||
|
// Create packet
|
||||||
|
final SynchedEntityData entityData = new SynchedEntityData(null);
|
||||||
|
final ClientboundSetEntityDataPacket dataPacket = new ClientboundSetEntityDataPacket(entityId, entityData, false);
|
||||||
|
final List<SynchedEntityData.DataItem<?>> packedItems = new ArrayList<>(2 + getDataItemCount());
|
||||||
|
|
||||||
|
// Setup data
|
||||||
|
packedItems.add(new SynchedEntityData.DataItem<>(DATA_NO_GRAVITY, true));
|
||||||
|
packedItems.add(new SynchedEntityData.DataItem<>(DATA_SILENT, true));
|
||||||
|
addSpecificData(packedItems, data);
|
||||||
|
|
||||||
|
try {
|
||||||
|
packedItemField.set(dataPacket, packedItems);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send packet
|
||||||
|
sendPacket(dataPacket, receivers);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract EntityType<?> getEntityType();
|
||||||
|
|
||||||
|
protected float getSpawnOffSet(){
|
||||||
|
return 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract int getDataItemCount();
|
||||||
|
|
||||||
|
protected abstract void addSpecificData(List<SynchedEntityData.DataItem<?>> packedItems, T data);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package de.epiceric.shopchest.nms.v1_17_R1;
|
||||||
|
|
||||||
|
import de.epiceric.shopchest.nms.FakeItem;
|
||||||
|
import net.minecraft.network.syncher.SynchedEntityData;
|
||||||
|
import net.minecraft.world.entity.EntityType;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class FakeItemImpl extends FakeEntityImpl<ItemStack> implements FakeItem {
|
||||||
|
|
||||||
|
public FakeItemImpl() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendData(ItemStack item, Iterable<Player> receivers) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected EntityType<?> getEntityType() {
|
||||||
|
return EntityType.ITEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getDataItemCount() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addSpecificData(List<SynchedEntityData.DataItem<?>> packedItems, ItemStack data) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package de.epiceric.shopchest.nms.v1_17_R1;
|
package de.epiceric.shopchest.nms.v1_17_R1;
|
||||||
|
|
||||||
import de.epiceric.shopchest.nms.FakeArmorStand;
|
import de.epiceric.shopchest.nms.FakeArmorStand;
|
||||||
|
import de.epiceric.shopchest.nms.FakeItem;
|
||||||
import de.epiceric.shopchest.nms.Platform;
|
import de.epiceric.shopchest.nms.Platform;
|
||||||
|
|
||||||
public class PlatformImpl implements Platform {
|
public class PlatformImpl implements Platform {
|
||||||
@ -10,4 +11,9 @@ public class PlatformImpl implements Platform {
|
|||||||
return new FakeArmorStandImpl();
|
return new FakeArmorStandImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FakeItem createFakeItem() {
|
||||||
|
return new FakeItemImpl();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user