Include UserConnection in StoredObject

Handle Blocking
Handle BossBars, Holograms
This commit is contained in:
Myles 2016-03-16 21:52:00 +00:00
parent 2197b938f8
commit 7e133a0be8
14 changed files with 290 additions and 16 deletions

View File

@ -1,4 +1,9 @@
package us.myles.ViaVersion2.api.data;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public class StoredObject {
private UserConnection user;
}

View File

@ -1,14 +1,24 @@
package us.myles.ViaVersion2.api.item;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.bukkit.inventory.ItemStack;
import org.spacehq.opennbt.tag.builtin.CompoundTag;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Item {
private short id;
private byte amount;
private short data;
private CompoundTag tag;
public static Item getItem(ItemStack stack) {
if(stack == null) return null;
return new Item((short) stack.getTypeId(), (byte) stack.getAmount(), stack.getDurability(), null);
}
}

View File

@ -30,7 +30,7 @@ public class ProtocolPipeline extends Protocol {
public void init(UserConnection userConnection) {
this.userConnection = userConnection;
ProtocolInfo protocolInfo = new ProtocolInfo();
ProtocolInfo protocolInfo = new ProtocolInfo(userConnection);
protocolInfo.setPipeline(this);
userConnection.put(protocolInfo);

View File

@ -4,6 +4,7 @@ import lombok.Getter;
import lombok.Setter;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion2.api.data.StoredObject;
import us.myles.ViaVersion2.api.data.UserConnection;
import us.myles.ViaVersion2.api.protocol.ProtocolPipeline;
import java.util.UUID;
@ -16,4 +17,8 @@ public class ProtocolInfo extends StoredObject{
private String username;
private UUID uuid;
private ProtocolPipeline pipeline;
public ProtocolInfo(UserConnection user) {
super(user);
}
}

View File

@ -1,11 +1,15 @@
package us.myles.ViaVersion2.api.protocol1_9to1_8;
import org.bukkit.Bukkit;
import org.bukkit.inventory.ItemStack;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion2.api.PacketWrapper;
import us.myles.ViaVersion2.api.data.UserConnection;
import us.myles.ViaVersion2.api.metadata.Metadata;
import us.myles.ViaVersion2.api.protocol.Protocol;
import us.myles.ViaVersion2.api.protocol.base.ProtocolInfo;
import us.myles.ViaVersion2.api.protocol1_9to1_8.packets.*;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.ClientChunks;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.EntityTracker;
@ -16,6 +20,9 @@ import us.myles.ViaVersion2.api.remapper.ValueTransformer;
import us.myles.ViaVersion2.api.type.Type;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
public class Protocol1_9TO1_8 extends Protocol {
public static Type<List<Metadata>> METADATA_LIST = new MetadataListType();
@ -59,10 +66,31 @@ public class Protocol1_9TO1_8 extends Protocol {
@Override
public void init(UserConnection userConnection) {
// Entity tracker
userConnection.put(new EntityTracker());
userConnection.put(new EntityTracker(userConnection));
// Chunk tracker
userConnection.put(new ClientChunks());
userConnection.put(new ClientChunks(userConnection));
// Movement tracker
userConnection.put(new MovementTracker());
userConnection.put(new MovementTracker(userConnection));
}
public static ItemStack getHandItem(final UserConnection info) {
try {
return Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable<ItemStack>() {
@Override
public ItemStack call() throws Exception {
UUID playerUUID = info.get(ProtocolInfo.class).getUuid();
if (Bukkit.getPlayer(playerUUID) != null) {
return Bukkit.getPlayer(playerUUID).getItemInHand();
}
return null;
}
}).get(10, TimeUnit.SECONDS);
} catch (Exception e) {
System.out.println("Error fetching hand item: " + e.getClass().getName());
if (ViaVersion.getInstance().isDebug())
e.printStackTrace();
return null;
}
}
}

View File

@ -47,7 +47,7 @@ public class MetadataRewriter {
int newIndex = MetaIndex.PLAYER_HAND.getNewIndex();
int typeID = MetaIndex.PLAYER_HAND.getNewType().getTypeID();
Metadata metadata = new Metadata(newIndex, typeID, us.myles.ViaVersion2.api.type.Type.BYTE, val);
// list.add(metadata);
list.add(metadata);
}
break;
case OptUUID:

View File

@ -1,5 +1,6 @@
package us.myles.ViaVersion2.api.protocol1_9to1_8.packets;
import org.bukkit.Material;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.packets.State;
@ -171,9 +172,7 @@ public class EntityPackets {
}
});
map(Type.ITEM); // 2 - Item
// TODO - Blocking patch
// Item Rewriter
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
@ -181,6 +180,23 @@ public class EntityPackets {
ItemRewriter.toClient(stack);
}
});
// Blocking
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
EntityTracker entityTracker = wrapper.user().get(EntityTracker.class);
int entityID = wrapper.get(Type.VAR_INT, 0);
Item stack = wrapper.get(Type.ITEM, 0);
if(stack != null){
if(Material.getMaterial(stack.getId()).name().endsWith("SWORD")){
entityTracker.getValidBlocking().add(entityID);
return;
}
}
entityTracker.getValidBlocking().remove(entityID);
}
});
}
});
// Entity Metadata Packet
@ -203,6 +219,17 @@ public class EntityPackets {
}
}
});
// Handler for meta data
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
List<Metadata> metadataList = wrapper.get(Protocol1_9TO1_8.METADATA_LIST, 0);
int entityID = wrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
tracker.handleMetadata(entityID, metadataList);
}
});
}
});
@ -216,7 +243,6 @@ public class EntityPackets {
map(Type.BYTE); // 2 - Amplifier
map(Type.VAR_INT); // 3 - Duration
map(Type.BOOLEAN, Type.BYTE); // 4 - Hide particles
// TODO: Test particles as conversion might not work
}
});

View File

@ -6,6 +6,7 @@ import us.myles.ViaVersion2.api.item.Item;
import us.myles.ViaVersion2.api.protocol.Protocol;
import us.myles.ViaVersion2.api.protocol1_9to1_8.ItemRewriter;
import us.myles.ViaVersion2.api.protocol1_9to1_8.Protocol1_9TO1_8;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.EntityTracker;
import us.myles.ViaVersion2.api.remapper.PacketHandler;
import us.myles.ViaVersion2.api.remapper.PacketRemapper;
import us.myles.ViaVersion2.api.remapper.ValueCreator;
@ -164,14 +165,18 @@ public class InventoryPackets {
protocol.registerIncoming(State.PLAY, 0x0F, 0x05); // Confirm Transaction Packet
protocol.registerIncoming(State.PLAY, 0x11, 0x06); // Enchant Item Packet
// TODO Held Item change blocking patch
protocol.registerIncoming(State.PLAY, 0x09, 0x17, new PacketRemapper() {
@Override
public void registerMap() {
// Blocking patch
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
System.out.println("held item");
EntityTracker entityTracker = wrapper.user().get(EntityTracker.class);
if (entityTracker.isBlocking()) {
entityTracker.setBlocking(false);
entityTracker.setSecondHand(wrapper.user(), null);
}
}
});
}

View File

@ -1,10 +1,12 @@
package us.myles.ViaVersion2.api.protocol1_9to1_8.packets;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion2.api.PacketWrapper;
import us.myles.ViaVersion2.api.item.Item;
import us.myles.ViaVersion2.api.protocol.Protocol;
import us.myles.ViaVersion2.api.protocol1_9to1_8.PlayerMovementMapper;
import us.myles.ViaVersion2.api.protocol1_9to1_8.Protocol1_9TO1_8;
@ -307,6 +309,7 @@ public class PlayerPackets {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int hand = wrapper.read(Type.VAR_INT);
// Wipe the input buffer
wrapper.clearInputBuffer();
// First set this packet ID to Block placement
@ -314,7 +317,23 @@ public class PlayerPackets {
wrapper.write(Type.LONG, -1L);
wrapper.write(Type.BYTE, (byte) 255);
// Write item in hand
wrapper.write(Type.SHORT, (short) -1); // TODO
Item item = Item.getItem(Protocol1_9TO1_8.getHandItem(wrapper.user()));
// Blocking patch
if (item != null) {
if (Material.getMaterial(item.getId()).name().endsWith("SWORD")) {
if (hand == 0) {
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
if (!tracker.isBlocking()) {
tracker.setBlocking(true);
Item shield = new Item((short) 442, (byte) 1, (short) 0, null);
tracker.setSecondHand(wrapper.user(), shield);
}
wrapper.cancel();
}
}
}
wrapper.write(Type.ITEM, item);
wrapper.write(Type.BYTE, (byte) 0);
wrapper.write(Type.BYTE, (byte) 0);

View File

@ -170,7 +170,6 @@ public class SpawnPackets {
map(Type.SHORT); // 11 - Velocity Z
map(Protocol1_9TO1_8.METADATA_LIST);
// TODO: Metadata detector for bossbars, wither stuff.
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
@ -184,6 +183,16 @@ public class SpawnPackets {
}
}
});
// Handler for meta data
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
List<Metadata> metadataList = wrapper.get(Protocol1_9TO1_8.METADATA_LIST, 0);
int entityID = wrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
tracker.handleMetadata(entityID, metadataList);
}
});
}
});
@ -250,6 +259,17 @@ public class SpawnPackets {
}
}
});
// Handler for meta data
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
List<Metadata> metadataList = wrapper.get(Protocol1_9TO1_8.METADATA_LIST, 0);
int entityID = wrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
tracker.handleMetadata(entityID, metadataList);
}
});
}
});

View File

@ -6,9 +6,11 @@ import us.myles.ViaVersion2.api.PacketWrapper;
import us.myles.ViaVersion2.api.protocol.Protocol;
import us.myles.ViaVersion2.api.protocol1_9to1_8.Protocol1_9TO1_8;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.ClientChunks;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.EntityTracker;
import us.myles.ViaVersion2.api.protocol1_9to1_8.types.ChunkType;
import us.myles.ViaVersion2.api.remapper.PacketHandler;
import us.myles.ViaVersion2.api.remapper.PacketRemapper;
import us.myles.ViaVersion2.api.remapper.ValueCreator;
import us.myles.ViaVersion2.api.type.Type;
public class WorldPackets {
@ -125,7 +127,20 @@ public class WorldPackets {
wrapper.cancel();
}
});
// TODO: Blocking patch stopped if blocking and 5
// Blocking
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int status = wrapper.get(Type.UNSIGNED_BYTE, 0);
if (status == 5) {
EntityTracker entityTracker = wrapper.user().get(EntityTracker.class);
if(entityTracker.isBlocking()){
entityTracker.setBlocking(false);
entityTracker.setSecondHand(wrapper.user(), null);
}
}
}
});
}
});
@ -136,7 +151,13 @@ public class WorldPackets {
map(Type.POSITION); // 0 - Position
map(Type.VAR_INT, Type.BYTE); // 1 - Block Face
map(Type.VAR_INT, Type.NOTHING); // 2 - Hand
// TODO: Insert hand item here
// TODO: Actual hand item
create(new ValueCreator() {
@Override
public void write(PacketWrapper wrapper) throws Exception {
wrapper.write(Type.SHORT, (short) -1);
}
});
// Did have item rewriter but its not needed
map(Type.UNSIGNED_BYTE); // 4 - X
map(Type.UNSIGNED_BYTE); // 5 - Y

View File

@ -6,6 +6,7 @@ import lombok.Getter;
import org.bukkit.Bukkit;
import us.myles.ViaVersion.util.ReflectionUtil;
import us.myles.ViaVersion2.api.data.StoredObject;
import us.myles.ViaVersion2.api.data.UserConnection;
import java.util.List;
import java.util.Set;
@ -28,6 +29,10 @@ public class ClientChunks extends StoredObject {
}
}
public ClientChunks(UserConnection user) {
super(user);
}
public List<Object> transformMapChunkBulk(Object packet) {
List<Object> list = Lists.newArrayList();
try {

View File

@ -1,24 +1,46 @@
package us.myles.ViaVersion2.api.protocol1_9to1_8.storage;
import io.netty.buffer.ByteBuf;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Bukkit;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.boss.BossBar;
import us.myles.ViaVersion.api.boss.BossColor;
import us.myles.ViaVersion.api.boss.BossStyle;
import us.myles.ViaVersion.metadata.NewType;
import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion2.api.PacketWrapper;
import us.myles.ViaVersion2.api.data.StoredObject;
import us.myles.ViaVersion2.api.data.UserConnection;
import us.myles.ViaVersion2.api.item.Item;
import us.myles.ViaVersion2.api.metadata.Metadata;
import us.myles.ViaVersion2.api.protocol.base.ProtocolInfo;
import us.myles.ViaVersion2.api.type.Type;
import java.util.*;
@Getter
public class EntityTracker extends StoredObject{
public class EntityTracker extends StoredObject {
private final Map<Integer, UUID> uuidMap = new HashMap<>();
private final Map<Integer, EntityType> clientEntityTypes = new HashMap<>();
private final Map<Integer, Integer> vehicleMap = new HashMap<>();
private final Map<Integer, BossBar> bossBarMap = new HashMap<>();
private final Set<Integer> validBlocking = new HashSet<>();
private final Set<Integer> knownHolograms = new HashSet<>();
@Getter
@Setter
private boolean blocking = false;
@Setter
private int entityID;
public EntityTracker(UserConnection user) {
super(user);
}
public UUID getEntityUUID(int id) {
if (uuidMap.containsKey(id)) {
return uuidMap.get(id);
@ -29,6 +51,18 @@ public class EntityTracker extends StoredObject{
}
}
public void setSecondHand(UserConnection connection, Item item) {
PacketWrapper wrapper = new PacketWrapper(0x3C, null, connection);
wrapper.write(Type.VAR_INT, entityID);
wrapper.write(Type.VAR_INT, 1); // slot
wrapper.write(Type.ITEM, item);
try {
wrapper.send();
} catch (Exception e) {
e.printStackTrace();
}
}
public void removeEntity(Integer entityID) {
clientEntityTypes.remove(entityID);
vehicleMap.remove(entityID);
@ -41,4 +75,95 @@ public class EntityTracker extends StoredObject{
bar.hide();
}
}
public void handleMetadata(int entityID, List<Metadata> metadataList) {
if (!clientEntityTypes.containsKey(entityID)) return;
EntityType type = clientEntityTypes.get(entityID);
for (Metadata metadata : new ArrayList<>(metadataList)) {
// Fix: wither (crash fix)
if (type == EntityType.WITHER) {
if (metadata.getId() == 10) {
metadataList.remove(metadata);
//metadataList.add(new Metadata(10, NewType.Byte.getTypeID(), Type.BYTE, 0));
}
}
// Fix: enderdragon (crash fix)
if (type == EntityType.ENDER_DRAGON) {
if (metadata.getId() == 11) {
metadataList.remove(metadata);
// metadataList.add(new Metadata(11, NewType.Byte.getTypeID(), Type.VAR_INT, 0));
}
}
if (type == EntityType.PLAYER) {
if (metadata.getId() == 0) {
// Byte
byte data = (byte) metadata.getValue();
if (entityID != getEntityID() && ((ViaVersionPlugin) ViaVersion.getInstance()).isShieldBlocking()) {
if ((data & 0x10) == 0x10) {
if (validBlocking.contains(entityID)) {
Item shield = new Item((short) 442, (byte) 1, (short) 0, null);
setSecondHand(getUser(), shield);
}
} else {
setSecondHand(getUser(), null);
}
}
}
}
if (type == EntityType.ARMOR_STAND && ((ViaVersionPlugin) ViaVersion.getInstance()).isHologramPatch()) {
if (metadata.getId() == 0) {
byte data = (byte) metadata.getValue();
if ((data & 0x20) == 0x20) {
if (!knownHolograms.contains(entityID)) {
knownHolograms.add(entityID);
// Send movement
ByteBuf buf = getUser().getChannel().alloc().buffer();
PacketUtil.writeVarInt(0x25, buf); // Relative Move Packet
PacketUtil.writeVarInt(entityID, buf);
buf.writeShort(0);
buf.writeShort((short) (128D * (((ViaVersionPlugin) ViaVersion.getInstance()).getHologramYOffset() * 32D)));
buf.writeShort(0);
buf.writeBoolean(true);
getUser().sendRawPacket(buf, false);
}
}
}
}
Player player = Bukkit.getPlayer(getUser().get(ProtocolInfo.class).getUuid());
// Boss bar
if (((ViaVersionPlugin) ViaVersion.getInstance()).isBossbarPatch()) {
if (type == EntityType.ENDER_DRAGON || type == EntityType.WITHER) {
if (metadata.getId() == 2) {
BossBar bar = bossBarMap.get(entityID);
String title = (String) metadata.getValue();
title = title.isEmpty() ? (type == EntityType.ENDER_DRAGON ? "Ender Dragon" : "Wither") : title;
if (bar == null) {
bar = ViaVersion.getInstance().createBossBar(title, BossColor.PINK, BossStyle.SOLID);
bossBarMap.put(entityID, bar);
bar.addPlayer(player);
bar.show();
} else {
bar.setTitle(title);
}
} else if (metadata.getId() == 6 && !((ViaVersionPlugin) ViaVersion.getInstance()).isBossbarAntiflicker()) { // If anti flicker is enabled, don't update health
BossBar bar = bossBarMap.get(entityID);
// Make health range between 0 and 1
float maxHealth = type == EntityType.ENDER_DRAGON ? 200.0f : 300.0f;
float health = Math.max(0.0f, Math.min(((float) metadata.getValue()) / maxHealth, 1.0f));
if (bar == null) {
String title = type == EntityType.ENDER_DRAGON ? "Ender Dragon" : "Wither";
bar = ViaVersion.getInstance().createBossBar(title, health, BossColor.PINK, BossStyle.SOLID);
bossBarMap.put(entityID, bar);
bar.addPlayer(player);
bar.show();
} else {
bar.setHealth(health);
}
}
}
}
}
}
}

View File

@ -2,6 +2,7 @@ package us.myles.ViaVersion2.api.protocol1_9to1_8.storage;
import lombok.Getter;
import us.myles.ViaVersion2.api.data.StoredObject;
import us.myles.ViaVersion2.api.data.UserConnection;
public class MovementTracker extends StoredObject{
private static final long IDLE_PACKET_DELAY = 50L; // Update every 50ms (20tps)
@ -9,6 +10,10 @@ public class MovementTracker extends StoredObject{
@Getter
private long nextIdlePacket = 0L;
public MovementTracker(UserConnection user) {
super(user);
}
public void incrementIdlePacket() {
// Notify of next update
// Allow a maximum lag spike of 1 second (20 ticks/updates)