Continue 1.11 update.

This commit is contained in:
Matsv 2017-05-31 00:03:42 +02:00
parent 168803ae8a
commit 51c502486e
No known key found for this signature in database
GPG Key ID: 97CEC2A2EA31350F
27 changed files with 1400 additions and 630 deletions

View File

@ -5,3 +5,10 @@ Allows 1.9.x on a 1.10 Spigot server
Requires [ViaVersion](http://viaversion.com) to be installed
**Spigot page:** https://www.spigotmc.org/resources/viabackwards.27448/
TODO:
- Entity names that changed?
- llama inventory slots
- Rewrite Shulker box name

View File

@ -18,4 +18,9 @@ public class BukkitPlugin extends JavaPlugin implements ViaBackwardsPlatform {
public void onEnable() {
this.init();
}
@Override
public void disable() {
getPluginLoader().disablePlugin(this);
}
}

View File

@ -19,4 +19,9 @@ public class BungeePlugin extends Plugin implements ViaBackwardsPlatform {
public void onEnable() {
this.init();
}
// Why is this not a thing in Bungee? O_o
@Override
public void disable() {
}
}

View File

@ -12,10 +12,13 @@ package nl.matsv.viabackwards.api;
import nl.matsv.viabackwards.ViaBackwards;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.Protocol1_10To1_11;
import nl.matsv.viabackwards.protocol.protocol1_11to1_11_1.Protocol1_11To1_11_1;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.Protocol1_9_4To1_10;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.chunks.ChunkSection1_9_3_4;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.logging.Logger;
@ -25,8 +28,12 @@ public interface ViaBackwardsPlatform {
*/
default void init() {
ViaBackwards.init(this);
ProtocolRegistry.registerProtocol(new Protocol1_9_4To1_10(), Collections.singletonList(ProtocolVersion.v1_9_3.getId()), ProtocolVersion.v1_10.getId());
ProtocolRegistry.registerProtocol(new Protocol1_10To1_11(), Collections.singletonList(ProtocolVersion.v1_10.getId()), ProtocolVersion.v1_11.getId());
if (!isOutdated()) {
ProtocolRegistry.registerProtocol(new Protocol1_9_4To1_10(), Collections.singletonList(ProtocolVersion.v1_9_3.getId()), ProtocolVersion.v1_10.getId());
ProtocolRegistry.registerProtocol(new Protocol1_10To1_11(), Collections.singletonList(ProtocolVersion.v1_10.getId()), ProtocolVersion.v1_11.getId());
ProtocolRegistry.registerProtocol(new Protocol1_11To1_11_1(), Collections.singletonList(ProtocolVersion.v1_11.getId()), ProtocolVersion.v1_11_1.getId());
}
}
/**
@ -35,4 +42,32 @@ public interface ViaBackwardsPlatform {
* @return logger instance
*/
Logger getLogger();
// TODO remove or better implement on full release
default boolean isOutdated() {
Method m = null;
try {
m = ChunkSection1_9_3_4.class.getMethod("getBlock", int.class, int.class, int.class);
} catch (NoSuchMethodException ignored) {
}
if (m == null) {
getLogger().severe("================================");
getLogger().severe("YOUR VIAVERSION IS OUTDATED");
getLogger().severe("PLEASE USE THE LATEST DEVBUILD");
getLogger().severe("LINK: https://ci.viaversion.com/job/ViaVersion-DEV/");
getLogger().severe("VIABACKWARDS WILL NOW DISABLE");
getLogger().severe("================================");
disable();
return true;
}
return false;
}
/**
* Disable the plugin
*/
void disable();
}

View File

@ -10,6 +10,8 @@
package nl.matsv.viabackwards.api.entities;
import java.util.List;
public interface AbstractEntityType {
/**
@ -26,4 +28,11 @@ public interface AbstractEntityType {
*/
AbstractEntityType getParent();
boolean is(AbstractEntityType... types);
boolean is(AbstractEntityType type);
boolean isOrHasParent(AbstractEntityType type);
List<AbstractEntityType> getParents();
}

View File

@ -8,28 +8,20 @@
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.chunks;
package nl.matsv.viabackwards.api.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
import us.myles.viaversion.libs.opennbt.tag.builtin.CompoundTag;
public interface AbstractObjectType {
/**
* Get the metadata id
*
* @return the metadata index
*/
int getId();
import java.util.List;
@Data
@AllArgsConstructor
public class Chunk1_10 implements Chunk {
private int x;
private int z;
private boolean groundUp;
private int bitmask;
private ChunkSection1_10[] sections;
private byte[] biomeData;
private List<CompoundTag> blockEntities;
@Override
public boolean isBiomeData() {
return biomeData != null;
}
}
/**
* Get the entity type
*
* @return Entity type
*/
AbstractEntityType getType();
}

View File

@ -10,11 +10,14 @@
package nl.matsv.viabackwards.api.entities;
import com.google.common.base.Optional;
import lombok.AllArgsConstructor;
import lombok.Getter;
import nl.matsv.viabackwards.ViaBackwards;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
// 1.10 Entity / Object ids
public class EntityType1_10 {
@ -27,7 +30,7 @@ public class EntityType1_10 {
type = EntityType.findById(typeID);
if (!type.isPresent()) {
ViaBackwards.getPlatform().getLogger().severe("Could not find type id " + typeID + " isObject=" + isObject);
ViaBackwards.getPlatform().getLogger().severe("[EntityType1_10] Could not find type id " + typeID + " isObject=" + isObject);
return EntityType.ENTITY; // Fall back to the basic ENTITY
}
@ -133,19 +136,59 @@ public class EntityType1_10 {
public static Optional<EntityType> findById(int id) {
if (id == -1) // Check if this is called
return Optional.absent();
return Optional.empty();
for (EntityType ent : EntityType.values())
if (ent.getId() == id)
return Optional.of(ent);
return Optional.absent();
return Optional.empty();
}
@Override
public boolean is(AbstractEntityType... types) {
for (AbstractEntityType type : types)
if (is(type))
return true;
return false;
}
@Override
public boolean is(AbstractEntityType type) {
return this == type;
}
@Override
public boolean isOrHasParent(AbstractEntityType type) {
EntityType parent = this;
do {
if (parent.equals(type))
return true;
parent = parent.getParent();
} while (parent != null);
return false;
}
@Override
public List<AbstractEntityType> getParents() {
List<AbstractEntityType> types = new ArrayList<>();
EntityType parent = this;
do {
types.add(parent);
parent = parent.getParent();
} while (parent != null);
return types;
}
}
@AllArgsConstructor
@Getter
public enum ObjectType {
public enum ObjectType implements AbstractObjectType {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.DROPPED_ITEM),
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
@ -177,20 +220,20 @@ public class EntityType1_10 {
public static Optional<ObjectType> findById(int id) {
if (id == -1)
return Optional.absent();
return Optional.empty();
for (ObjectType ent : ObjectType.values())
if (ent.getId() == id)
return Optional.of(ent);
return Optional.absent();
return Optional.empty();
}
public static Optional<EntityType> getPCEntity(int id) {
Optional<ObjectType> output = findById(id);
if (!output.isPresent())
return Optional.absent();
return Optional.empty();
return Optional.of(output.get().getType());
}
}

View File

@ -10,14 +10,17 @@
package nl.matsv.viabackwards.api.entities;
import com.google.common.base.Optional;
import lombok.AllArgsConstructor;
import lombok.Getter;
import nl.matsv.viabackwards.ViaBackwards;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class EntityType1_11 {
public static EntityType getTypeFromId(int typeID, boolean isObject) {
public static EntityType getTypeFromId(int typeID, boolean isObject) throws Exception {
Optional<EntityType> type;
if (isObject)
@ -26,7 +29,7 @@ public class EntityType1_11 {
type = EntityType.findById(typeID);
if (!type.isPresent()) {
ViaBackwards.getPlatform().getLogger().severe("Could not find type id " + typeID + " isObject=" + isObject);
ViaBackwards.getPlatform().getLogger().severe("[EntityType1_11] Could not find type id " + typeID + " isObject=" + isObject);
return EntityType.ENTITY; // Fall back to the basic ENTITY
}
@ -53,7 +56,6 @@ public class EntityType1_11 {
PRIMED_TNT(20, ENTITY),
FALLING_BLOCK(21, ENTITY),
FIREWORK(22, ENTITY),
TIPPED_ARROW(23, ARROW),
SPECTRAL_ARROW(24, ARROW),
SHULKER_BULLET(25, ENTITY),
DRAGON_FIREBALL(26, FIREBALL),
@ -161,27 +163,30 @@ public class EntityType1_11 {
public static Optional<EntityType> findById(int id) {
if (id == -1) // Check if this is called
return Optional.absent();
return Optional.empty();
for (EntityType ent : EntityType.values())
if (ent.getId() == id)
return Optional.of(ent);
return Optional.absent();
return Optional.empty();
}
public boolean is(EntityType... types) {
for (EntityType type : types)
@Override
public boolean is(AbstractEntityType... types) {
for (AbstractEntityType type : types)
if (is(type))
return true;
return false;
}
public boolean is(EntityType type) {
@Override
public boolean is(AbstractEntityType type) {
return this == type;
}
public boolean isOrHasParent(EntityType type) {
@Override
public boolean isOrHasParent(AbstractEntityType type) {
EntityType parent = this;
do {
@ -193,18 +198,31 @@ public class EntityType1_11 {
return false;
}
@Override
public List<AbstractEntityType> getParents() {
List<AbstractEntityType> types = new ArrayList<>();
EntityType parent = this;
do {
types.add(parent);
parent = parent.getParent();
} while (parent != null);
return types;
}
}
@AllArgsConstructor
@Getter
public enum ObjectType {
public enum ObjectType implements AbstractObjectType {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.DROPPED_ITEM),
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
MINECART(10, EntityType.MINECART_ABSTRACT),
TNT_PRIMED(50, EntityType.PRIMED_TNT),
ENDER_CRYSTAL(51, EntityType.ENDER_CRYSTAL),
TIPPED_ARROW(60, EntityType.TIPPED_ARROW),
TIPPED_ARROW(60, EntityType.ARROW),
SNOWBALL(61, EntityType.SNOWBALL),
EGG(62, EntityType.EGG),
FIREBALL(63, EntityType.FIREBALL),
@ -221,7 +239,7 @@ public class EntityType1_11 {
FIREWORK(76, EntityType.FIREWORK),
LEASH(77, EntityType.LEASH_HITCH),
ARMOR_STAND(78, EntityType.ARMOR_STAND),
EVOCATION_FANGS(39, EntityType.EVOCATION_FANGS),
EVOCATION_FANGS(79, EntityType.EVOCATION_FANGS),
FISHIHNG_HOOK(90, EntityType.FISHING_HOOK),
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
@ -231,20 +249,20 @@ public class EntityType1_11 {
public static Optional<ObjectType> findById(int id) {
if (id == -1)
return Optional.absent();
return Optional.empty();
for (ObjectType ent : ObjectType.values())
if (ent.getId() == id)
return Optional.of(ent);
return Optional.absent();
return Optional.empty();
}
public static Optional<EntityType> getPCEntity(int id) {
Optional<ObjectType> output = findById(id);
if (!output.isPresent())
return Optional.absent();
return Optional.empty();
return Optional.of(output.get().getType());
}
}

View File

@ -75,11 +75,26 @@ public abstract class BlockItemRewriter<T extends BackwardsProtocol> extends Rew
return item;
}
protected Block handleBlock(int block) {
protected int handleBlockID(int idx) {
int type = idx >> 4;
int meta = idx & 15;
if (!containsBlock(type))
return idx;
Block b = handleBlock(type, meta);
return (b.getId() << 4 | (b.getData() & 15));
}
protected Block handleBlock(int block, int data) {
if (!containsBlock(block))
return null;
return blockRewriter.get(block);
Block b = blockRewriter.get(block);
// For some blocks, the data can still be useful (:
if (b.getData() == -1)
b.setData(data);
return b;
}
protected boolean containsBlock(int block) {

View File

@ -13,26 +13,31 @@ package nl.matsv.viabackwards.api.rewriters;
import lombok.RequiredArgsConstructor;
import nl.matsv.viabackwards.ViaBackwards;
import nl.matsv.viabackwards.api.BackwardsProtocol;
import nl.matsv.viabackwards.api.MetaRewriter;
import nl.matsv.viabackwards.api.entities.AbstractEntityType;
import nl.matsv.viabackwards.api.entities.AbstractObjectType;
import nl.matsv.viabackwards.api.exceptions.RemovedValueException;
import nl.matsv.viabackwards.api.storage.EntityData;
import nl.matsv.viabackwards.api.storage.EntityTracker;
import us.myles.ViaVersion.api.ViaVersion;
import nl.matsv.viabackwards.api.v2.MetaHandlerEvent;
import nl.matsv.viabackwards.api.v2.MetaHandlerSettings;
import nl.matsv.viabackwards.api.v2.MetaStorage;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Logger;
@RequiredArgsConstructor
public abstract class EntityRewriter<T extends BackwardsProtocol> extends Rewriter<T> {
private final Map<AbstractEntityType, Short> entityTypes = new ConcurrentHashMap<>();
private final List<MetaRewriter> metaRewriters = new ArrayList<>();
private final Map<AbstractEntityType, EntityData> entityTypes = new ConcurrentHashMap<>();
private final Map<AbstractObjectType, EntityData> objectTypes = new ConcurrentHashMap<>();
private final List<MetaHandlerSettings> metaHandlers = new ArrayList<>();
protected AbstractEntityType getEntityType(UserConnection connection, int id) {
return getEntityTracker(connection).getEntityType(id);
@ -42,53 +47,76 @@ public abstract class EntityRewriter<T extends BackwardsProtocol> extends Rewrit
getEntityTracker(connection).trackEntityType(entityId, type);
}
protected void rewriteEntityType(AbstractEntityType type, int newId) {
entityTypes.put(type, (short) newId);
protected Optional<EntityData> getEntityData(AbstractEntityType type) {
if (!entityTypes.containsKey(type))
return Optional.empty();
return Optional.of(entityTypes.get(type));
}
protected boolean isRewriteEntityType(AbstractEntityType type) {
return entityTypes.containsKey(type);
protected Optional<EntityData> getObjectData(AbstractObjectType type) {
if (!objectTypes.containsKey(type))
return Optional.empty();
return Optional.of(objectTypes.get(type));
}
protected short getNewEntityType(AbstractEntityType type) {
if (!isRewriteEntityType(type))
return -1;
return entityTypes.get(type);
protected EntityData regEntType(AbstractEntityType oldEnt, AbstractEntityType replacement) {
return regEntType(oldEnt, (short) replacement.getId());
}
public void registerMetaRewriter(MetaRewriter rewriter) {
metaRewriters.add(rewriter);
private EntityData regEntType(AbstractEntityType oldEnt, short replacementId) {
EntityData data = new EntityData(oldEnt.getId(), false, replacementId, -1);
entityTypes.put(oldEnt, data);
return data;
}
protected List<Metadata> handleMeta(UserConnection user, int entityId, List<Metadata> metaData) {
protected EntityData regObjType(AbstractObjectType oldObj, AbstractObjectType replacement, int data) {
return regObjType(oldObj, (short) replacement.getId(), data);
}
private EntityData regObjType(AbstractObjectType oldObj, short replacementId, int data) {
EntityData entData = new EntityData(oldObj.getId(), true, replacementId, data);
objectTypes.put(oldObj, entData);
return entData;
}
public MetaHandlerSettings registerMetaHandler() {
MetaHandlerSettings settings = new MetaHandlerSettings();
metaHandlers.add(settings);
return settings;
}
protected MetaStorage handleMeta(UserConnection user, int entityId, MetaStorage storage) throws Exception {
EntityTracker tracker = user.get(EntityTracker.class);
AbstractEntityType type = tracker.get(getProtocol()).getEntityType(entityId);
List<Metadata> newMeta = new CopyOnWriteArrayList<>();
for (Metadata md : metaData) {
Metadata nmd = md;
try {
for (MetaRewriter rewriter : metaRewriters) {
if (type != null)
nmd = rewriter.handleMetadata(type, nmd);
else
throw new Exception("Panic, entitytype is null");
List<Metadata> newList = new CopyOnWriteArrayList<>();
for (MetaHandlerSettings settings : metaHandlers) {
for (Metadata md : storage.getMetaDataList()) {
Metadata nmd = md;
try {
if (settings.isGucci(type, nmd))
nmd = settings.getHandler().handle(new MetaHandlerEvent(type, nmd.getId(), nmd, storage));
if (nmd == null)
throw new RemovedValueException();
}
newMeta.add(nmd);
} catch (RemovedValueException ignored) {
} catch (Exception e) {
if (ViaVersion.getInstance().isDebug()) {
Logger log = ViaBackwards.getPlatform().getLogger();
log.warning("Unable to handle metadata " + md);
log.warning("Full metadata list " + metaData);
e.printStackTrace();
newList.add(nmd);
} catch (RemovedValueException ignored) {
} catch (Exception e) {
if (Via.getManager().isDebug()) {
Logger log = ViaBackwards.getPlatform().getLogger();
log.warning("Unable to handle metadata " + nmd);
log.warning("Full metadata list " + storage);
e.printStackTrace();
}
}
}
storage.setMetaDataList(new ArrayList<>(newList));
newList.clear();
}
return newMeta;
return storage;
}
protected EntityTracker.ProtocolEntityTracker getEntityTracker(UserConnection user) {

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2016 Matsv
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package nl.matsv.viabackwards.api.storage;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import nl.matsv.viabackwards.api.v2.MetaStorage;
@RequiredArgsConstructor
@Getter
@ToString
public class EntityData {
private final int id;
private final boolean isObject;
private final int replacementId;
private final int objectData;
private MetaCreator defaultMeta;
public void spawnMetadata(MetaCreator handler) {
this.defaultMeta = handler;
}
public boolean hasBaseMeta() {
return this.defaultMeta != null;
}
public interface MetaCreator {
void handle(MetaStorage storage);
}
}

View File

@ -8,12 +8,11 @@
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package nl.matsv.viabackwards.api;
package nl.matsv.viabackwards.api.v2;
import nl.matsv.viabackwards.api.entities.AbstractEntityType;
import nl.matsv.viabackwards.api.exceptions.RemovedValueException;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
public interface MetaRewriter {
Metadata handleMetadata(AbstractEntityType type, Metadata data) throws RemovedValueException;
public interface MetaHandler {
Metadata handle(MetaHandlerEvent e) throws RemovedValueException;
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2016 Matsv
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package nl.matsv.viabackwards.api.v2;
import lombok.AllArgsConstructor;
import lombok.Getter;
import nl.matsv.viabackwards.api.entities.AbstractEntityType;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import java.util.Optional;
@Getter
@AllArgsConstructor
public class MetaHandlerEvent {
private AbstractEntityType type;
private int index = -1;
private Metadata data;
@Getter
private MetaStorage storage;
public boolean hasData() {
return data != null;
}
public Optional<Metadata> getMetaByIndex(int index) {
for (Metadata meta : getStorage().getMetaDataList())
if (index == meta.getId())
return Optional.of(meta);
return Optional.empty();
}
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2016 Matsv
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package nl.matsv.viabackwards.api.v2;
import lombok.Getter;
import lombok.ToString;
import nl.matsv.viabackwards.api.entities.AbstractEntityType;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import java.util.List;
@ToString
@Getter
public class MetaHandlerSettings {
private AbstractEntityType filterType;
private boolean filterFamily = false;
private int filterIndex = -1;
private MetaHandler handler;
public MetaHandlerSettings filter(AbstractEntityType type) {
return filter(type, filterFamily, filterIndex);
}
public MetaHandlerSettings filter(AbstractEntityType type, boolean filterFamily) {
return filter(type, filterFamily, filterIndex);
}
public MetaHandlerSettings filter(int index) {
return filter(filterType, filterFamily, index);
}
public MetaHandlerSettings filter(AbstractEntityType type, int index) {
return filter(type, filterFamily, index);
}
public MetaHandlerSettings filter(AbstractEntityType type, boolean filterFamily, int index) {
this.filterType = type;
this.filterFamily = filterFamily;
this.filterIndex = index;
return this;
}
public void handle(MetaHandler handler) {
this.handler = handler;
}
public boolean hasHandler() {
return handler != null;
}
public boolean hasType() {
return filterType != null;
}
public boolean hasIndex() {
return filterIndex > -1;
}
public boolean isFilterFamily() {
return filterFamily;
}
public boolean isGucci(AbstractEntityType type, Metadata metadata) {
if (hasHandler()) {
if (hasType()) {
List<AbstractEntityType> family = type.getParents();
if (isFilterFamily()) {
if (!family.contains(getFilterType()))
return false;
} else {
if (!getFilterType().is(type))
return false;
}
}
if (hasIndex() && metadata.getId() != getFilterIndex())
return false;
return true;
}
return false;
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2016 Matsv
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package nl.matsv.viabackwards.api.v2;
import lombok.*;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import java.util.List;
import java.util.Optional;
@Getter
@Setter
@ToString
@AllArgsConstructor
public class MetaStorage {
@NonNull
private List<Metadata> metaDataList;
public boolean has(Metadata data) {
return this.getMetaDataList().contains(data);
}
public void delete(Metadata data) {
this.getMetaDataList().remove(data);
}
public void delete(int index) {
Optional<Metadata> data = get(index);
if (data.isPresent())
delete(data.get());
}
public void add(Metadata data) {
this.getMetaDataList().add(data);
}
public Optional<Metadata> get(int index) {
for (Metadata meta : this.getMetaDataList())
if (index == meta.getId())
return Optional.of(meta);
return Optional.empty();
}
public Metadata getOrDefault(int index, Metadata data) {
return getOrDefault(index, false, data);
}
public Metadata getOrDefault(int index, boolean removeIfExists, Metadata data) {
Optional<Metadata> existingData = get(index);
if (removeIfExists && existingData.isPresent())
delete(existingData.get());
return existingData.orElse(data);
}
}

View File

@ -10,6 +10,7 @@
package nl.matsv.viabackwards.protocol.protocol1_10to1_11;
import lombok.Getter;
import nl.matsv.viabackwards.api.BackwardsProtocol;
import nl.matsv.viabackwards.api.storage.EntityTracker;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.packets.BlockItemPackets;
@ -19,9 +20,12 @@ import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
public class Protocol1_10To1_11 extends BackwardsProtocol {
@Getter
private EntityPackets entityPackets; // Required for the item rewriter
@Override
protected void registerPackets() {
new EntityPackets().register(this);
(entityPackets = new EntityPackets()).register(this);
new PlayerPackets().register(this);
new BlockItemPackets().register(this);
}

View File

@ -12,16 +12,18 @@ package nl.matsv.viabackwards.protocol.protocol1_10to1_11.packets;
import nl.matsv.viabackwards.api.rewriters.BlockItemRewriter;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.Protocol1_10To1_11;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.chunks.Chunk1_10;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.chunks.Chunk1_10Type;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.chunks.ChunkSection1_10;
import nl.matsv.viabackwards.utils.Block;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.minecraft.item.Item;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_9;
import us.myles.ViaVersion.api.remapper.PacketHandler;
import us.myles.ViaVersion.api.remapper.PacketRemapper;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.chunks.Chunk1_9_3_4;
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.chunks.ChunkSection1_9_3_4;
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
public class BlockItemPackets extends BlockItemRewriter<Protocol1_10To1_11> {
@ -165,20 +167,21 @@ public class BlockItemPackets extends BlockItemRewriter<Protocol1_10To1_11> {
public void handle(PacketWrapper wrapper) throws Exception {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
Chunk1_10Type type = new Chunk1_10Type(clientWorld); // Use the 1.10 Chunk type since nothing changed.
Chunk1_10 chunk = (Chunk1_10) wrapper.passthrough(type);
Chunk1_9_3_4Type type = new Chunk1_9_3_4Type(clientWorld); // Use the 1.10 Chunk type since nothing changed.
Chunk1_9_3_4 chunk = (Chunk1_9_3_4) wrapper.passthrough(type);
for (int i = 0; i < chunk.getSections().length; i++) {
ChunkSection1_10 section = chunk.getSections()[i];
ChunkSection1_9_3_4 section = chunk.getSections()[i];
if (section == null)
continue;
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
int block = section.getBlockId(x, y, z);
if (containsBlock(block)) {
Block b = handleBlock(block);
int block = section.getBlock(x, y, z);
int btype = block >> 4;
if (containsBlock(btype)) {
Block b = handleBlock(btype, block & 15); // Type / data
section.setBlock(x, y, z, b.getId(), b.getData());
}
}
@ -233,16 +236,15 @@ public class BlockItemPackets extends BlockItemRewriter<Protocol1_10To1_11> {
}
}
);
}
protected int handleBlockID(int idx) {
int type = idx >> 4;
protocol.getEntityPackets().registerMetaHandler().handle(e -> {
Metadata data = e.getData();
if (!containsBlock(type))
return idx;
if (data.getMetaType().equals(MetaType1_9.Slot)) // Is Item
data.setValue(handleItemToClient((Item) data.getValue()));
Block b = handleBlock(type);
return (b.getId() << 4 | (b.getData() & 15));
return data;
});
}
@Override
@ -253,7 +255,7 @@ public class BlockItemPackets extends BlockItemRewriter<Protocol1_10To1_11> {
new Item((short) 54, (byte) 1, (short) 0, getNamedTag("1.11 Shulker Box (Color #" + (i - 219) + ")")),
new Block(i, 1));
// Observer to Dispenser
// Observer to Dispenser TODO facing position?
rewriteBlockItem(218, new Item((short) 23, (byte) 1, (short) 0, getNamedTag("1.11 Observer")), new Block(23, 0));
// Totem of Undying to Dead Bush

View File

@ -10,10 +10,17 @@
package nl.matsv.viabackwards.protocol.protocol1_10to1_11.packets;
import nl.matsv.viabackwards.ViaBackwards;
import nl.matsv.viabackwards.api.entities.AbstractEntityType;
import nl.matsv.viabackwards.api.exceptions.RemovedValueException;
import nl.matsv.viabackwards.api.rewriters.EntityRewriter;
import nl.matsv.viabackwards.api.storage.EntityData;
import nl.matsv.viabackwards.api.v2.MetaStorage;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.Protocol1_10To1_11;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_9;
import us.myles.ViaVersion.api.remapper.PacketHandler;
import us.myles.ViaVersion.api.remapper.PacketRemapper;
import us.myles.ViaVersion.api.type.Type;
@ -21,10 +28,14 @@ import us.myles.ViaVersion.api.type.types.version.Types1_9;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import java.util.Optional;
import static nl.matsv.viabackwards.api.entities.EntityType1_11.*;
public class EntityPackets extends EntityRewriter<Protocol1_10To1_11> {
@Override
protected void registerPackets(Protocol1_10To1_11 protocol) {
// Spawn Object
@ -34,6 +45,12 @@ public class EntityPackets extends EntityRewriter<Protocol1_10To1_11> {
map(Type.VAR_INT); // 0 - Entity id
map(Type.UUID); // 1 - UUID
map(Type.BYTE); // 2 - Type
map(Type.DOUBLE); // 3 - x
map(Type.DOUBLE); // 4 - y
map(Type.DOUBLE); // 5 - z
map(Type.BYTE); // 6 - Pitch
map(Type.BYTE); // 7 - Yaw
map(Type.INT); // 8 - data
// Track Entity
handler(new PacketHandler() {
@ -46,6 +63,27 @@ public class EntityPackets extends EntityRewriter<Protocol1_10To1_11> {
);
}
});
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Optional<ObjectType> type = ObjectType.findById(wrapper.get(Type.BYTE, 0));
if (type.isPresent()) {
Optional<EntityData> optEntDat = getObjectData(type.get());
if (optEntDat.isPresent()) {
EntityData data = optEntDat.get();
wrapper.set(Type.BYTE, 0, ((Integer) data.getReplacementId()).byteValue());
if (data.getObjectData() != -1)
wrapper.set(Type.INT, 0, data.getObjectData());
}
} else {
if (Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().warning("Could not find Entity Type" + wrapper.get(Type.BYTE, 0));
}
}
}
});
}
});
@ -120,35 +158,33 @@ public class EntityPackets extends EntityRewriter<Protocol1_10To1_11> {
}
});
// Rewrite entity ids
// Rewrite entity type / metadata
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int entityId = wrapper.get(Type.VAR_INT, 0);
AbstractEntityType type = getEntityType(wrapper.user(), entityId);
short newType = getNewEntityType(type);
// Keep doing what you are doing
if (newType == -1)
return;
MetaStorage storage = new MetaStorage(wrapper.get(Types1_9.METADATA_LIST, 0));
handleMeta(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
storage
);
wrapper.set(Type.UNSIGNED_BYTE, 0, newType);
}
});
Optional<EntityData> optEntDat = getEntityData(type);
if (optEntDat.isPresent()) {
EntityData data = optEntDat.get();
wrapper.set(Type.UNSIGNED_BYTE, 0, ((Integer) data.getReplacementId()).shortValue());
if (data.hasBaseMeta())
data.getDefaultMeta().handle(storage);
}
// Rewrite metadata
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
// Rewrite Metadata
wrapper.set(
Types1_9.METADATA_LIST,
0,
handleMeta(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
wrapper.get(Types1_9.METADATA_LIST, 0)
)
storage.getMetaDataList()
);
}
});
@ -256,8 +292,8 @@ public class EntityPackets extends EntityRewriter<Protocol1_10To1_11> {
handleMeta(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
wrapper.get(Types1_9.METADATA_LIST, 0)
)
new MetaStorage(wrapper.get(Types1_9.METADATA_LIST, 0))
).getMetaDataList()
);
}
});
@ -296,8 +332,8 @@ public class EntityPackets extends EntityRewriter<Protocol1_10To1_11> {
handleMeta(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
wrapper.get(Types1_9.METADATA_LIST, 0)
)
new MetaStorage(wrapper.get(Types1_9.METADATA_LIST, 0))
).getMetaDataList()
);
}
});
@ -307,6 +343,188 @@ public class EntityPackets extends EntityRewriter<Protocol1_10To1_11> {
@Override
protected void registerRewrites() {
// Guardian
regEntType(EntityType.ELDER_GUARDIAN, EntityType.GUARDIAN);
// Skeletons
regEntType(EntityType.WITHER_SKELETON, EntityType.SKELETON).spawnMetadata(storage -> storage.add(getSkeletonTypeMeta(1)));
regEntType(EntityType.STRAY, EntityType.SKELETON).spawnMetadata(storage -> storage.add(getSkeletonTypeMeta(2)));
// Zombies
regEntType(EntityType.HUSK, EntityType.ZOMBIE).spawnMetadata(storage -> handleZombieType(storage, 6));
regEntType(EntityType.ZOMBIE_VILLAGER, EntityType.ZOMBIE).spawnMetadata(storage -> handleZombieType(storage, 1));
// Horses
regEntType(EntityType.HORSE, EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(0))); // Nob able to ride the horse without having the MetaType sent.
regEntType(EntityType.DONKEY, EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(1)));
regEntType(EntityType.MULE, EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(2)));
regEntType(EntityType.SKELETON_HORSE, EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(4)));
regEntType(EntityType.ZOMBIE_HORSE, EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(3)));
// New mobs
regEntType(EntityType.EVOCATION_FANGS, EntityType.SHULKER);
regEntType(EntityType.EVOCATION_ILLAGER, EntityType.VILLAGER);
regEntType(EntityType.VEX, EntityType.BAT);
regEntType(EntityType.VINDICATION_ILLAGER, EntityType.VILLAGER).spawnMetadata(storage -> storage.add(new Metadata(13, MetaType1_9.VarInt, 4))); // Base Profession
regEntType(EntityType.LIAMA, EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(1))); // TODO fix chest slots
regEntType(EntityType.LIAMA_SPIT, EntityType.SNOWBALL);
regObjType(ObjectType.LIAMA_SPIT, ObjectType.SNOWBALL, -1);
// Replace with endertorchthingies
regObjType(ObjectType.EVOCATION_FANGS, ObjectType.FALLING_BLOCK, 198 | 1 << 12);
// Handle ElderGuardian & target metadata
registerMetaHandler().filter(EntityType.GUARDIAN, true, 12).handle(e -> {
Metadata data = e.getData();
boolean b = (boolean) data.getValue();
int bitmask = b ? 0x02 : 0;
if (e.getType().is(EntityType.ELDER_GUARDIAN))
bitmask |= 0x04;
data.setMetaType(MetaType1_9.Byte);
data.setValue((byte) bitmask);
return data;
});
// Handle skeleton swing
registerMetaHandler().filter(EntityType.ABSTRACT_SKELETON, true, 12).handle(e -> {
e.getData().setId(13);
return e.getData();
});
/*
ZOMBIE CHANGES
*/
registerMetaHandler().filter(EntityType.ZOMBIE, true).handle(e -> {
Metadata data = e.getData();
switch (data.getId()) {
case 13:
throw new RemovedValueException();
case 14:
data.setId(15);
break;
case 15:
data.setId(14);
break;
// Profession
case 16:
data.setId(13);
data.setValue(1 + (int) data.getValue());
break;
}
return data;
});
// Handle Evocation Illager
registerMetaHandler().filter(EntityType.EVOCATION_ILLAGER, 12).handle(e -> {
Metadata data = e.getData();
data.setId(13);
data.setMetaType(MetaType1_9.VarInt);
data.setValue(((Byte) data.getValue()).intValue()); // Change the profession for the states
return data;
});
// Handle Vex (Remove this field completely since the position is not updated correctly when idling for bats. Sad ):
registerMetaHandler().filter(EntityType.VEX, 12).handle(e -> {
Metadata data = e.getData();
data.setValue((byte) 0x00);
return data;
});
// Handle VindicationIllager
registerMetaHandler().filter(EntityType.VINDICATION_ILLAGER, 12).handle(e -> {
Metadata data = e.getData();
data.setId(13);
data.setMetaType(MetaType1_9.VarInt);
data.setValue((byte) data.getValue() == 1 ? 2 : 4);
return data;
});
/*
HORSES
*/
// Handle Horse (Correct owner)
registerMetaHandler().filter(EntityType.ABSTRACT_HORSE, true, 14).handle(e -> {
Metadata data = e.getData();
data.setId(16);
return data;
});
// Handle horse armor
registerMetaHandler().filter(EntityType.HORSE, 16).handle(e -> {
Metadata data = e.getData();
data.setId(17);
return data;
});
// Handle chested horse - flag is still sent in horse flags
registerMetaHandler().filter(EntityType.CHESTED_HORSE, true, 15).handle(e -> {
throw new RemovedValueException();
});
// Get rid of Liama metadata TODO maybe for some special magic in the future?
registerMetaHandler().filter(EntityType.LIAMA).handle(e -> {
int index = e.getIndex();
if (index == 16 || index == 17 || index == 18)
throw new RemovedValueException();
return e.getData();
});
// Handle villager - Change non-existing profession
registerMetaHandler().filter(EntityType.VILLAGER, 13).handle(e -> {
Metadata data = e.getData();
if ((int) data.getValue() == 5)
data.setValue(0);
return data;
});
// handle new Shulker color meta
registerMetaHandler().filter(EntityType.SHULKER, 15).handle(e -> {
throw new RemovedValueException();
});
}
/*
0 - Skeleton
1 - Wither Skeleton
2 - Stray
*/
private Metadata getSkeletonTypeMeta(int type) {
return new Metadata(12, MetaType1_9.VarInt, type);
}
/*
0 - Zombie
1-5 - Villager with profession
6 - Husk
*/
private Metadata getZombieTypeMeta(int type) {
return new Metadata(13, MetaType1_9.VarInt, type);
}
private void handleZombieType(MetaStorage storage, int type) {
Optional<Metadata> meta = storage.get(13);
if (!meta.isPresent())
storage.add(getZombieTypeMeta(type));
}
/*
Horse 0
Donkey 1
Mule 2
Zombie horse 3
Skeleton horse 4
*/
private Metadata getHorseMetaType(int type) {
return new Metadata(14, MetaType1_9.VarInt, type);
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2016 Matsv
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package nl.matsv.viabackwards.protocol.protocol1_11to1_11_1;
import nl.matsv.viabackwards.api.BackwardsProtocol;
import nl.matsv.viabackwards.api.storage.EntityTracker;
import nl.matsv.viabackwards.protocol.protocol1_11to1_11_1.packets.EntityPackets;
import nl.matsv.viabackwards.protocol.protocol1_11to1_11_1.packets.ItemPackets;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
public class Protocol1_11To1_11_1 extends BackwardsProtocol {
@Override
protected void registerPackets() {
new EntityPackets().register(this);
new ItemPackets().register(this);
}
@Override
public void init(UserConnection user) {
// Register ClientWorld
if (!user.has(ClientWorld.class))
user.put(new ClientWorld(user));
// Register EntityTracker if it doesn't exist yet.
if (!user.has(EntityTracker.class))
user.put(new EntityTracker(user));
// Init protocol in EntityTracker
user.get(EntityTracker.class).initProtocol(this);
}
}

View File

@ -0,0 +1,354 @@
/*
* Copyright (c) 2016 Matsv
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package nl.matsv.viabackwards.protocol.protocol1_11to1_11_1.packets;
import nl.matsv.viabackwards.ViaBackwards;
import nl.matsv.viabackwards.api.entities.AbstractEntityType;
import nl.matsv.viabackwards.api.exceptions.RemovedValueException;
import nl.matsv.viabackwards.api.rewriters.EntityRewriter;
import nl.matsv.viabackwards.api.storage.EntityData;
import nl.matsv.viabackwards.api.v2.MetaStorage;
import nl.matsv.viabackwards.protocol.protocol1_11to1_11_1.Protocol1_11To1_11_1;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.remapper.PacketHandler;
import us.myles.ViaVersion.api.remapper.PacketRemapper;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.types.version.Types1_9;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import java.util.Optional;
import static nl.matsv.viabackwards.api.entities.EntityType1_11.*;
public class EntityPackets extends EntityRewriter<Protocol1_11To1_11_1> {
@Override
protected void registerPackets(Protocol1_11To1_11_1 protocol) {
// Spawn Object
protocol.registerOutgoing(State.PLAY, 0x00, 0x00, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity id
map(Type.UUID); // 1 - UUID
map(Type.BYTE); // 2 - Type
map(Type.DOUBLE); // 3 - x
map(Type.DOUBLE); // 4 - y
map(Type.DOUBLE); // 5 - z
map(Type.BYTE); // 6 - Pitch
map(Type.BYTE); // 7 - Yaw
map(Type.INT); // 8 - data
// Track Entity
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
addTrackedEntity(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
getTypeFromId(wrapper.get(Type.BYTE, 0), true)
);
}
});
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Optional<ObjectType> type = ObjectType.findById(wrapper.get(Type.BYTE, 0));
if (type.isPresent()) {
Optional<EntityData> optEntDat = getObjectData(type.get());
if (optEntDat.isPresent()) {
EntityData data = optEntDat.get();
wrapper.set(Type.BYTE, 0, ((Integer) data.getReplacementId()).byteValue());
if (data.getObjectData() != -1)
wrapper.set(Type.INT, 0, data.getObjectData());
}
} else {
if (Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().warning("Could not find Entity Type" + wrapper.get(Type.BYTE, 0));
}
}
}
});
}
});
// Spawn Experience Orb
protocol.registerOutgoing(State.PLAY, 0x01, 0x01, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity id
// Track entity
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
addTrackedEntity(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
ObjectType.THROWN_EXP_BOTTLE.getType()
);
}
});
}
});
// Spawn Global Entity
protocol.registerOutgoing(State.PLAY, 0x02, 0x02, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Type.BYTE); // 1 - Type
// Track entity
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
addTrackedEntity(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
EntityType.WEATHER // Always thunder according to wiki.vg
);
}
});
}
});
// Spawn Mob
protocol.registerOutgoing(State.PLAY, 0x03, 0x03, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity id
map(Type.UUID); // 1 - UUID
map(Type.VAR_INT); // 2 - Entity Type
map(Type.DOUBLE); // 3 - X
map(Type.DOUBLE); // 4 - Y
map(Type.DOUBLE); // 5 - Z
map(Type.BYTE); // 6 - Yaw
map(Type.BYTE); // 7 - Pitch
map(Type.BYTE); // 8 - Head Pitch
map(Type.SHORT); // 9 - Velocity X
map(Type.SHORT); // 10 - Velocity Y
map(Type.SHORT); // 11 - Velocity Z
map(Types1_9.METADATA_LIST); // 12 - Metadata
// Track entity
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
addTrackedEntity(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
getTypeFromId(wrapper.get(Type.VAR_INT, 1), false)
);
}
});
// Rewrite entity type / metadata
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int entityId = wrapper.get(Type.VAR_INT, 0);
AbstractEntityType type = getEntityType(wrapper.user(), entityId);
MetaStorage storage = new MetaStorage(wrapper.get(Types1_9.METADATA_LIST, 0));
handleMeta(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
storage
);
Optional<EntityData> optEntDat = getEntityData(type);
if (optEntDat.isPresent()) {
EntityData data = optEntDat.get();
wrapper.set(Type.UNSIGNED_BYTE, 0, ((Integer) data.getReplacementId()).shortValue());
if (data.hasBaseMeta())
data.getDefaultMeta().handle(storage);
}
// Rewrite Metadata
wrapper.set(
Types1_9.METADATA_LIST,
0,
storage.getMetaDataList()
);
}
});
}
});
// Spawn Painting
protocol.registerOutgoing(State.PLAY, 0x04, 0x04, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
// Track entity
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
addTrackedEntity(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
EntityType.PAINTING
);
}
});
}
});
// Join game
protocol.registerOutgoing(State.PLAY, 0x23, 0x23, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // 0 - Entity ID
map(Type.UNSIGNED_BYTE); // 1 - Gamemode
map(Type.INT); // 2 - Dimension
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
addTrackedEntity(
wrapper.user(),
wrapper.get(Type.INT, 0),
EntityType.PLAYER
);
}
});
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
int dimensionId = wrapper.get(Type.INT, 1);
clientWorld.setEnvironment(dimensionId);
}
});
}
});
// Respawn Packet (save dimension id)
protocol.registerOutgoing(State.PLAY, 0x33, 0x33, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // 0 - Dimension ID
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
int dimensionId = wrapper.get(Type.INT, 0);
clientWorld.setEnvironment(dimensionId);
}
});
}
});
// Spawn Player
protocol.registerOutgoing(State.PLAY, 0x05, 0x05, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Type.UUID); // 1 - Player UUID
map(Type.DOUBLE); // 2 - X
map(Type.DOUBLE); // 3 - Y
map(Type.DOUBLE); // 4 - Z
map(Type.BYTE); // 5 - Yaw
map(Type.BYTE); // 6 - Pitch
map(Types1_9.METADATA_LIST); // 7 - Metadata list
// Track Entity
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
addTrackedEntity(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
EntityType.PLAYER
);
}
});
// Rewrite Metadata
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.set(
Types1_9.METADATA_LIST,
0,
handleMeta(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
new MetaStorage(wrapper.get(Types1_9.METADATA_LIST, 0))
).getMetaDataList()
);
}
});
}
});
// Destroy entities
protocol.registerOutgoing(State.PLAY, 0x30, 0x30, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT_ARRAY); // 0 - Entity IDS
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
for (int entity : wrapper.get(Type.VAR_INT_ARRAY, 0))
getEntityTracker(wrapper.user()).removeEntity(entity);
}
});
}
});
// Metadata packet
protocol.registerOutgoing(State.PLAY, 0x39, 0x39, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Types1_9.METADATA_LIST); // 1 - Metadata list
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.set(
Types1_9.METADATA_LIST,
0,
handleMeta(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
new MetaStorage(wrapper.get(Types1_9.METADATA_LIST, 0))
).getMetaDataList()
);
}
});
}
});
}
@Override
protected void registerRewrites() {
// TODO tipped arrows check no particles changes?
// Handle non-existing firework metadata (index 7 entity id for boosting)
registerMetaHandler().filter(EntityType.FIREWORK, 7).handle(e -> {
throw new RemovedValueException();
});
// Handle non-existing pig metadata (index 14 - boost time)
registerMetaHandler().filter(EntityType.PIG, 14).handle(e -> {
throw new RemovedValueException();
});
}
}

View File

@ -0,0 +1,156 @@
/*
* Copyright (c) 2016 Matsv
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package nl.matsv.viabackwards.protocol.protocol1_11to1_11_1.packets;
import nl.matsv.viabackwards.api.rewriters.BlockItemRewriter;
import nl.matsv.viabackwards.protocol.protocol1_11to1_11_1.Protocol1_11To1_11_1;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.minecraft.item.Item;
import us.myles.ViaVersion.api.remapper.PacketHandler;
import us.myles.ViaVersion.api.remapper.PacketRemapper;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.packets.State;
public class ItemPackets extends BlockItemRewriter<Protocol1_11To1_11_1> {
@Override
protected void registerPackets(Protocol1_11To1_11_1 protocol) {
// Set slot packet
protocol.registerOutgoing(State.PLAY, 0x16, 0x16, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.BYTE); // 0 - Window ID
map(Type.SHORT); // 1 - Slot ID
map(Type.ITEM); // 2 - Slot Value
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Item stack = wrapper.get(Type.ITEM, 0);
wrapper.set(Type.ITEM, 0, handleItemToClient(stack));
}
});
}
});
// Window items packet
protocol.registerOutgoing(State.PLAY, 0x14, 0x14, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.ITEM_ARRAY); // 1 - Window Values
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Item[] stacks = wrapper.get(Type.ITEM_ARRAY, 0);
for (int i = 0; i < stacks.length; i++)
stacks[i] = handleItemToClient(stacks[i]);
}
});
}
});
// Entity Equipment Packet
protocol.registerOutgoing(State.PLAY, 0x3C, 0x3C, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Type.VAR_INT); // 1 - Slot ID
map(Type.ITEM); // 2 - Item
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Item stack = wrapper.get(Type.ITEM, 0);
wrapper.set(Type.ITEM, 0, handleItemToClient(stack));
}
});
}
});
// Plugin message Packet -> Trading
protocol.registerOutgoing(State.PLAY, 0x18, 0x18, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING); // 0 - Channel
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
if (wrapper.get(Type.STRING, 0).equalsIgnoreCase("MC|TrList")) {
wrapper.passthrough(Type.INT); // Passthrough Window ID
int size = wrapper.passthrough(Type.BYTE);
for (int i = 0; i < size; i++) {
wrapper.write(Type.ITEM, handleItemToClient(wrapper.read(Type.ITEM))); // Input Item
wrapper.write(Type.ITEM, handleItemToClient(wrapper.read(Type.ITEM))); // Output Item
boolean secondItem = wrapper.passthrough(Type.BOOLEAN); // Has second item
if (secondItem)
wrapper.write(Type.ITEM, handleItemToClient(wrapper.read(Type.ITEM))); // Second Item
wrapper.passthrough(Type.BOOLEAN); // Trade disabled
wrapper.passthrough(Type.INT); // Number of tools uses
wrapper.passthrough(Type.INT); // Maximum number of trade uses
}
}
}
});
}
});
// Click window packet
protocol.registerIncoming(State.PLAY, 0x07, 0x07, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.SHORT); // 1 - Slot
map(Type.BYTE); // 2 - Button
map(Type.SHORT); // 3 - Action number
map(Type.VAR_INT); // 4 - Mode
map(Type.ITEM); // 5 - Clicked Item
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Item item = wrapper.get(Type.ITEM, 0);
handleItemToServer(item);
}
});
}
}
);
// Creative Inventory Action
protocol.registerIncoming(State.PLAY, 0x18, 0x18, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.SHORT); // 0 - Slot
map(Type.ITEM); // 1 - Clicked Item
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Item item = wrapper.get(Type.ITEM, 0);
handleItemToServer(item);
}
});
}
}
);
}
@Override
protected void registerRewrites() {
rewriteItem(452, new Item((short) 265, (byte) 1, (short) 0, getNamedTag("1.11.2 Iron Nugget")));
}
}

View File

@ -1,120 +0,0 @@
/*
* Copyright (c) 2016 Matsv
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.chunks;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import nl.matsv.viabackwards.ViaBackwards;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.minecraft.Environment;
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection;
import us.myles.ViaVersion.api.type.PartialType;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.types.minecraft.BaseChunkType;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import us.myles.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import java.util.Arrays;
import java.util.BitSet;
import java.util.List;
public class Chunk1_10Type extends PartialType<Chunk, ClientWorld> {
public Chunk1_10Type(ClientWorld param) {
super(param, Chunk.class);
}
@Override
public Chunk read(ByteBuf input, ClientWorld world) throws Exception {
int chunkX = input.readInt();
int chunkZ = input.readInt();
boolean groundUp = input.readBoolean();
int primaryBitmask = Type.VAR_INT.read(input);
Type.VAR_INT.read(input);
BitSet usedSections = new BitSet(16);
ChunkSection1_10[] sections = new ChunkSection1_10[16];
// Calculate section count from bitmask
for (int i = 0; i < 16; i++) {
if ((primaryBitmask & (1 << i)) != 0) {
usedSections.set(i);
}
}
// Read sections
for (int i = 0; i < 16; i++) {
if (!usedSections.get(i)) continue; // Section not set
ChunkSection1_10 section = new ChunkSection1_10();
sections[i] = section;
section.readBlocks(input);
section.readBlockLight(input);
if (world.getEnvironment() == Environment.NORMAL) {
section.readSkyLight(input);
}
}
byte[] biomeData = groundUp ? new byte[256] : null;
if (groundUp) {
input.readBytes(biomeData);
}
List<CompoundTag> nbtData = Arrays.asList(Type.NBT_ARRAY.read(input));
// Temp patch for plugins that sent wrong too big chunks TODO find the issue in LibsDisguise and PR it.
if (input.readableBytes() > 0) {
byte[] array = new byte[input.readableBytes()];
input.readBytes(array);
if (Via.getManager().isDebug())
ViaBackwards.getPlatform().getLogger().warning("Found " + array.length + " more bytes than expected while reading the chunk");
}
return new Chunk1_10(chunkX, chunkZ, groundUp, primaryBitmask, sections, biomeData, nbtData);
}
@Override
public void write(ByteBuf output, ClientWorld world, Chunk chunk) throws Exception {
output.writeInt(chunk.getX());
output.writeInt(chunk.getZ());
output.writeBoolean(chunk.isGroundUp());
Type.VAR_INT.write(output, chunk.getBitmask());
ByteBuf buf = Unpooled.buffer();
for (int i = 0; i < 16; i++) {
ChunkSection section = chunk.getSections()[i];
if (section == null) continue; // Section not set
section.writeBlocks(buf);
section.writeBlockLight(buf);
if (!section.hasSkyLight()) continue; // No sky light, we're done here.
section.writeSkyLight(buf);
}
buf.readerIndex(0);
Type.VAR_INT.write(output, buf.readableBytes() + (chunk.isBiomeData() ? 256 : 0));
output.writeBytes(buf);
buf.release(); // release buffer
// Write biome data
if (chunk.isBiomeData()) {
output.writeBytes(chunk.getBiomeData());
}
Type.NBT_ARRAY.write(output, chunk.getBlockEntities().toArray(new CompoundTag[0]));
}
@Override
public Class<? extends Type> getBaseClass() {
return BaseChunkType.class;
}
}

View File

@ -1,306 +0,0 @@
/*
* Copyright (c) 2016 Matsv
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.chunks;
import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection;
import us.myles.ViaVersion.api.minecraft.chunks.NibbleArray;
import us.myles.ViaVersion.api.type.Type;
import java.util.List;
/**
* From the ViaVersion code {@link us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.chunks.ChunkSection1_9_1_2}
*/
public class ChunkSection1_10 implements ChunkSection {
/**
* Size (dimensions) of blocks in a chunks section.
*/
public static final int SIZE = 16 * 16 * 16; // width * depth * height
/**
* Length of the sky and block light nibble arrays.
*/
public static final int LIGHT_LENGTH = 16 * 16 * 16 / 2; // size * size * size / 2 (nibble bit count)
/**
* Length of the block data array.
*/
@Getter
private final List<Integer> palette = Lists.newArrayList();
private final int[] blocks;
private final NibbleArray blockLight;
private NibbleArray skyLight;
public ChunkSection1_10() {
this.blocks = new int[SIZE];
this.blockLight = new NibbleArray(SIZE);
palette.add(0); // AIR
}
/**
* Set a block in the chunks
*
* @param x Block X
* @param y Block Y
* @param z Block Z
* @param type The type of the block
* @param data The data value of the block
*/
public void setBlock(int x, int y, int z, int type, int data) {
setBlock(index(x, y, z), type, data);
}
public int getBlockId(int x, int y, int z) {
int index = blocks[index(x, y, z)];
return palette.get(index) >> 4;
}
/**
* Set a block in the chunks based on the index
*
* @param idx Index
* @param type The type of the block
* @param data The data value of the block
*/
public void setBlock(int idx, int type, int data) {
int hash = type << 4 | (data & 0xF);
int index = palette.indexOf(hash);
if (index == -1) {
index = palette.size();
palette.add(hash);
}
blocks[idx] = index;
}
/**
* Set the block light array
*
* @param data The value to set the block light to
*/
public void setBlockLight(byte[] data) {
blockLight.setHandle(data);
}
/**
* Set the sky light array
*
* @param data The value to set the sky light to
*/
public void setSkyLight(byte[] data) {
if (data.length != LIGHT_LENGTH) throw new IllegalArgumentException("Data length != " + LIGHT_LENGTH);
this.skyLight = new NibbleArray(data);
}
private int index(int x, int y, int z) {
return y << 8 | z << 4 | x;
}
/**
* Read blocks from input stream.
* This reads all the block related data:
* <ul>
* <li>Block length/palette type</li>
* <li>Palette</li>
* <li>Block hashes/palette reference</li>
* </ul>
*
* @param input The buffer to read from.
* @throws Exception If it fails to read
*/
public void readBlocks(ByteBuf input) throws Exception {
palette.clear();
// Reaad bits per block
int bitsPerBlock = input.readUnsignedByte();
long maxEntryValue = (1L << bitsPerBlock) - 1;
if (bitsPerBlock == 0) {
bitsPerBlock = 13;
}
if (bitsPerBlock < 4) {
bitsPerBlock = 4;
}
if (bitsPerBlock > 8) {
bitsPerBlock = 13;
}
int paletteLength = Type.VAR_INT.read(input);
// Read palette
for (int i = 0; i < paletteLength; i++) {
if (bitsPerBlock != 13) {
palette.add(Type.VAR_INT.read(input));
} else {
Type.VAR_INT.read(input);
}
}
// Read blocks
Long[] blockData = Type.LONG_ARRAY.read(input);
if (blockData.length > 0) {
for (int i = 0; i < blocks.length; i++) {
int bitIndex = i * bitsPerBlock;
int startIndex = bitIndex / 64;
int endIndex = ((i + 1) * bitsPerBlock - 1) / 64;
int startBitSubIndex = bitIndex % 64;
int val;
if (startIndex == endIndex) {
val = (int) (blockData[startIndex] >>> startBitSubIndex & maxEntryValue);
} else {
int endBitSubIndex = 64 - startBitSubIndex;
val = (int) ((blockData[startIndex] >>> startBitSubIndex | blockData[endIndex] << endBitSubIndex) & maxEntryValue);
}
if (bitsPerBlock == 13) {
int type = val >> 4;
int data = val & 0xF;
setBlock(i, type, data);
} else {
blocks[i] = val;
}
}
}
}
/**
* Read block light from buffer.
*
* @param input The buffer to read from
*/
public void readBlockLight(ByteBuf input) {
byte[] handle = new byte[LIGHT_LENGTH];
input.readBytes(handle);
blockLight.setHandle(handle);
}
/**
* Read sky light from buffer.
* Note: Only sent in overworld!
*
* @param input The buffer to read from
*/
public void readSkyLight(ByteBuf input) {
byte[] handle = new byte[LIGHT_LENGTH];
input.readBytes(handle);
if (skyLight != null) {
skyLight.setHandle(handle);
return;
}
this.skyLight = new NibbleArray(handle);
}
/**
* Write the blocks to a buffer.
*
* @param output The buffer to write to.
* @throws Exception Throws if it failed to write.
*/
public void writeBlocks(ByteBuf output) throws Exception {
// Write bits per block
int bitsPerBlock = 4;
while (palette.size() > 1 << bitsPerBlock) {
bitsPerBlock += 1;
}
long maxEntryValue = (1L << bitsPerBlock) - 1;
output.writeByte(bitsPerBlock);
// Write pallet (or not)
Type.VAR_INT.write(output, palette.size());
for (int mappedId : palette) {
Type.VAR_INT.write(output, mappedId);
}
int length = (int) Math.ceil(SIZE * bitsPerBlock / 64.0);
Type.VAR_INT.write(output, length);
long[] data = new long[length];
for (int index = 0; index < blocks.length; index++) {
int value = blocks[index];
int bitIndex = index * bitsPerBlock;
int startIndex = bitIndex / 64;
int endIndex = ((index + 1) * bitsPerBlock - 1) / 64;
int startBitSubIndex = bitIndex % 64;
data[startIndex] = data[startIndex] & ~(maxEntryValue << startBitSubIndex) | ((long) value & maxEntryValue) << startBitSubIndex;
if (startIndex != endIndex) {
int endBitSubIndex = 64 - startBitSubIndex;
data[endIndex] = data[endIndex] >>> endBitSubIndex << endBitSubIndex | ((long) value & maxEntryValue) >> endBitSubIndex;
}
}
for (long l : data) {
Type.LONG.write(output, l);
}
}
/**
* Write the block light to a buffer
*
* @param output The buffer to write to
*/
public void writeBlockLight(ByteBuf output) {
output.writeBytes(blockLight.getHandle());
}
/**
* Write the sky light to a buffer
*
* @param output The buffer to write to
*/
public void writeSkyLight(ByteBuf output) {
output.writeBytes(skyLight.getHandle());
}
/**
* Check if sky light is present
*
* @return True if skylight is present
*/
public boolean hasSkyLight() {
return skyLight != null;
}
/**
* Get expected size of this chunks section.
*
* @return Amount of bytes sent by this section
* @throws Exception If it failed to calculate bits properly
*/
public int getExpectedSize() throws Exception {
int bitsPerBlock = palette.size() > 255 ? 16 : 8;
int bytes = 1; // bits per block
bytes += paletteBytes(); // palette
bytes += countBytes(bitsPerBlock == 16 ? SIZE * 2 : SIZE); // block data length
bytes += (palette.size() > 255 ? 2 : 1) * SIZE; // block data
bytes += LIGHT_LENGTH; // block light
bytes += hasSkyLight() ? LIGHT_LENGTH : 0; // sky light
return bytes;
}
private int paletteBytes() throws Exception {
// Count bytes used by pallet
int bytes = countBytes(palette.size());
for (int mappedId : palette) {
bytes += countBytes(mappedId);
}
return bytes;
}
private int countBytes(int value) throws Exception {
// Count amount of bytes that would be sent if the value were sent as a VarInt
ByteBuf buf = Unpooled.buffer();
Type.VAR_INT.write(buf, value);
buf.readerIndex(0);
int bitCount = buf.readableBytes();
buf.release();
return bitCount;
}
}

View File

@ -12,17 +12,18 @@ package nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.packets;
import nl.matsv.viabackwards.api.rewriters.BlockItemRewriter;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.Protocol1_9_4To1_10;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.chunks.Chunk1_10;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.chunks.Chunk1_10Type;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.chunks.ChunkSection1_10;
import nl.matsv.viabackwards.utils.Block;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.minecraft.item.Item;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_9;
import us.myles.ViaVersion.api.remapper.PacketHandler;
import us.myles.ViaVersion.api.remapper.PacketRemapper;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.chunks.Chunk1_9_3_4;
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.chunks.ChunkSection1_9_3_4;
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
public class BlockItemPackets extends BlockItemRewriter<Protocol1_9_4To1_10> {
@ -166,20 +167,21 @@ public class BlockItemPackets extends BlockItemRewriter<Protocol1_9_4To1_10> {
public void handle(PacketWrapper wrapper) throws Exception {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
Chunk1_10Type type = new Chunk1_10Type(clientWorld);
Chunk1_10 chunk = (Chunk1_10) wrapper.passthrough(type);
Chunk1_9_3_4Type type = new Chunk1_9_3_4Type(clientWorld);
Chunk1_9_3_4 chunk = (Chunk1_9_3_4) wrapper.passthrough(type);
for (int i = 0; i < chunk.getSections().length; i++) {
ChunkSection1_10 section = chunk.getSections()[i];
ChunkSection1_9_3_4 section = chunk.getSections()[i];
if (section == null)
continue;
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
int block = section.getBlockId(x, y, z);
if (containsBlock(block)) {
Block b = handleBlock(block);
int block = section.getBlock(x, y, z);
int btype = block >> 4;
if (containsBlock(btype)) {
Block b = handleBlock(btype, block & 15); // Type / data
section.setBlock(x, y, z, b.getId(), b.getData());
}
}
@ -235,8 +237,10 @@ public class BlockItemPackets extends BlockItemRewriter<Protocol1_9_4To1_10> {
}
);
/* Register Metadata */
protocol.getEntityPackets().registerMetaRewriter((type, data) -> {
protocol.getEntityPackets().registerMetaHandler().handle(e -> {
Metadata data = e.getData();
if (data.getMetaType().equals(MetaType1_9.Slot)) // Is Item
data.setValue(handleItemToClient((Item) data.getValue()));
@ -244,16 +248,6 @@ public class BlockItemPackets extends BlockItemRewriter<Protocol1_9_4To1_10> {
});
}
protected int handleBlockID(int idx) {
int type = idx >> 4;
if (!containsBlock(type))
return idx;
Block b = handleBlock(type);
return (b.getId() << 4 | (b.getData() & 15));
}
@Override
protected void registerRewrites() {
rewriteItem(255, new Item((short) 166, (byte) 1, (short) 0, getNamedTag("1.10 Structure Block"))); // Structure block only item since the structure block is in 1.9

View File

@ -10,12 +10,18 @@
package nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.packets;
import nl.matsv.viabackwards.ViaBackwards;
import nl.matsv.viabackwards.api.entities.AbstractEntityType;
import nl.matsv.viabackwards.api.entities.EntityType1_10;
import nl.matsv.viabackwards.api.entities.EntityType1_11;
import nl.matsv.viabackwards.api.exceptions.RemovedValueException;
import nl.matsv.viabackwards.api.rewriters.EntityRewriter;
import nl.matsv.viabackwards.api.storage.EntityData;
import nl.matsv.viabackwards.api.v2.MetaStorage;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.Protocol1_9_4To1_10;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_9;
import us.myles.ViaVersion.api.remapper.PacketHandler;
import us.myles.ViaVersion.api.remapper.PacketRemapper;
@ -24,7 +30,10 @@ import us.myles.ViaVersion.api.type.types.version.Types1_9;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import java.util.Optional;
import static nl.matsv.viabackwards.api.entities.EntityType1_10.EntityType;
import static nl.matsv.viabackwards.api.entities.EntityType1_11.getTypeFromId;
public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
@ -38,6 +47,12 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
map(Type.VAR_INT); // 0 - Entity id
map(Type.UUID); // 1 - UUID
map(Type.BYTE); // 2 - Type
map(Type.DOUBLE); // 3 - x
map(Type.DOUBLE); // 4 - y
map(Type.DOUBLE); // 5 - z
map(Type.BYTE); // 6 - Pitch
map(Type.BYTE); // 7 - Yaw
map(Type.INT); // 8 - data
// Track Entity
handler(new PacketHandler() {
@ -46,10 +61,31 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
addTrackedEntity(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
EntityType1_10.getTypeFromId(wrapper.get(Type.BYTE, 0), true)
getTypeFromId(wrapper.get(Type.BYTE, 0), true)
);
}
});
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Optional<EntityType1_11.ObjectType> type = EntityType1_11.ObjectType.findById(wrapper.get(Type.BYTE, 0));
if (type.isPresent()) {
Optional<EntityData> optEntDat = getObjectData(type.get());
if (optEntDat.isPresent()) {
EntityData data = optEntDat.get();
wrapper.set(Type.BYTE, 0, ((Integer) data.getReplacementId()).byteValue());
if (data.getObjectData() != -1)
wrapper.set(Type.INT, 0, data.getObjectData());
}
} else {
if (Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().warning("Could not find Entity Type" + wrapper.get(Type.BYTE, 0));
}
}
}
});
}
});
@ -124,38 +160,37 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
}
});
// Rewrite entity ids
// Rewrite entity type / metadata
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int entityId = wrapper.get(Type.VAR_INT, 0);
AbstractEntityType type = getEntityType(wrapper.user(), entityId);
short newType = getNewEntityType(type);
// Keep doing what you are doing
if (newType == -1)
return;
MetaStorage storage = new MetaStorage(wrapper.get(Types1_9.METADATA_LIST, 0));
handleMeta(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
storage
);
wrapper.set(Type.UNSIGNED_BYTE, 0, newType);
}
});
Optional<EntityData> optEntDat = getEntityData(type);
if (optEntDat.isPresent()) {
EntityData data = optEntDat.get();
wrapper.set(Type.UNSIGNED_BYTE, 0, ((Integer) data.getReplacementId()).shortValue());
if (data.hasBaseMeta())
data.getDefaultMeta().handle(storage);
}
// Rewrite metadata
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
// Rewrite Metadata
wrapper.set(
Types1_9.METADATA_LIST,
0,
handleMeta(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
wrapper.get(Types1_9.METADATA_LIST, 0)
)
storage.getMetaDataList()
);
}
});
}
});
@ -260,8 +295,8 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
handleMeta(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
wrapper.get(Types1_9.METADATA_LIST, 0)
)
new MetaStorage(wrapper.get(Types1_9.METADATA_LIST, 0))
).getMetaDataList()
);
}
});
@ -300,8 +335,8 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
handleMeta(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
wrapper.get(Types1_9.METADATA_LIST, 0)
)
new MetaStorage(wrapper.get(Types1_9.METADATA_LIST, 0))
).getMetaDataList()
);
}
});
@ -311,50 +346,50 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
@Override
protected void registerRewrites() {
rewriteEntityType(EntityType.POLAR_BEAR, 91); // Replace polar bear with sheep
regEntType(EntityType.POLAR_BEAR, EntityType.SHEEP);
// Handle Polar bear
registerMetaRewriter((entityType, data) -> { // Change the sheep color when the polar bear is standing up
if (!entityType.equals(EntityType.POLAR_BEAR))
return data;
// Change the sheep color when the polar bear is standing up (index 13 -> Standing up)
registerMetaHandler().filter(EntityType.POLAR_BEAR, 13).handle((e -> {
Metadata data = e.getData();
boolean b = (boolean) data.getValue();
if (data.getId() == 13) { // is boolean
boolean b = (boolean) data.getValue();
data.setMetaType(MetaType1_9.Byte);
data.setValue(b ? (byte) (14 & 0x0F) : (byte) (0));
data.setId(13);
data.setMetaType(MetaType1_9.Byte);
data.setValue(b ? (byte) (14 & 0x0F) : 0);
}
return data;
});
}));
// Handle Husk
registerMetaRewriter((entityType, data) -> { // Change husk to normal zombie
if (!entityType.equals(EntityType.ZOMBIE))
return data;
if (data.getId() == 13 && data.getMetaType().getTypeID() == 1 && (int) data.getValue() == 6)
// Handle husk (index 13 -> Zombie Type)
registerMetaHandler().filter(EntityType.ZOMBIE, 13).handle(e -> {
Metadata data = e.getData();
if ((int) data.getValue() == 6) // Is type Husk
data.setValue(0);
return data;
});
// Handle stray
registerMetaRewriter((entityType, data) -> { // Change stray- to normal skeleton
if (!entityType.equals(EntityType.SKELETON))
return data;
// Handle Stray (index 12 -> Skeleton Type)
registerMetaHandler().filter(EntityType.SKELETON, 12).handle(e -> {
Metadata data = e.getData();
if ((int) data.getValue() == 2)
data.setValue(0); // Change to default skeleton
if (data.getId() == 12 && data.getMetaType().getTypeID() == 1 && (int) data.getValue() == 2)
data.setValue(0);
return data;
});
// Handle the missing NoGravity tag
registerMetaRewriter((type, m) -> {
if (m.getId() == 5)
// Handle the missing NoGravity tag for every metadata
registerMetaHandler().handle(e -> {
Metadata data = e.getData();
if (data.getId() == 5)
throw new RemovedValueException();
else if (m.getId() >= 5)
m.setId(m.getId() - 1);
return m;
else if (data.getId() >= 5)
data.setId(data.getId() - 1);
return data;
});
}
}

View File

@ -65,7 +65,7 @@
<dependency>
<groupId>us.myles</groupId>
<artifactId>viaversion</artifactId>
<version>1.0.3</version>
<version>1.0.5-1_12pre5</version>
<scope>provided</scope>
</dependency>
</dependencies>

View File

@ -46,4 +46,10 @@ public class SpongePlugin implements ViaBackwardsPlatform {
public Logger getLogger() {
return logger;
}
// TODO check how to for sponge, site was offline
@Override
public void disable() {
}
}