Compare commits

...
57 Commits
Author SHA1 Message Date
Matsv 9a0686685c Bump version 2017-07-29 14:11:43 +02:00
Matsv ccc63966c6 Change shulkerbox data fixes #15 2017-07-29 14:05:10 +02:00
Matsv 18d8ab068d Remove debug message 2017-07-29 13:32:03 +02:00
Matsv 227396d08a Format replacement items differently 2017-07-29 13:24:17 +02:00
Matsv dbc92572fd Fix NPE for unknown beds & keep original NBT data 2017-07-29 13:19:59 +02:00
Matsv ea2f603cf7 Possibility to hide warning using suppressMetadataErrors fixes #14 2017-07-04 21:12:09 +02:00
Matsv a5aa9e7281 Handle nulls in EntityRewriter (#11) 2017-06-21 19:30:48 +02:00
Matsv 0e5ee7063f Back to snapshot 2017-06-14 17:57:12 +02:00
Matsv d95630c4d0 Bump version 2017-06-14 17:31:32 +02:00
Matsv 451202335d Add supported versions to README 2017-06-14 16:27:42 +02:00
Matsv 36be58f775 Change sout to logger 2017-06-14 15:41:36 +02:00
Matsv a23204a86c Use a hanging bat for sitting parrot 2017-06-14 15:16:52 +02:00
Matsv 4928dab3f0 Fix achievement popup "Open Inventory" visible forever 2017-06-14 14:59:48 +02:00
Matsv b6bf2cd950 Handle observer facing position 2017-06-13 21:06:07 +02:00
Matsv 469936308c Implement shoulder indication 2017-06-13 20:48:02 +02:00
Matsv d330b64bba Modify pitch instead of changing volume (-: 2017-06-13 19:34:30 +02:00
Matsv 258ca46428 Remap 1_12 sounds 2017-06-13 19:30:36 +02:00
Matsv e4998e267e Remove some todos 2017-06-13 17:10:56 +02:00
Matsv adc84452d5 Fix invisible illusionator 2017-06-13 16:56:47 +02:00
Matsv ce89d1c724 Store Parrot tamed data 2017-06-13 16:32:43 +02:00
Matsv 354660a374 Change ShulkerBoxes to EnderChests to fix breaking/picking it up 2017-06-13 15:38:16 +02:00
Matsv a47e845847 Fix Llama inventory offset, replacement sounds for 1.11 & fix NPE 2017-06-13 15:33:43 +02:00
Matsv da84e30936 Rename some classes 2017-06-13 13:59:48 +02:00
Matsv 0f52fdf3b6 Let the knowledge book glow (: 2017-06-13 13:55:48 +02:00
Matsv dfe8c90da4 Patch signs not empty in 1.9-1.9.2 2017-06-13 13:40:28 +02:00
Matsv 9ed4a15b32 Implement a color variable for item names 2017-06-12 21:50:21 +02:00
Matsv 961991a316 Fix null translate chat message fields 2017-06-12 21:28:26 +02:00
Matsv e9878f68b9 Basic advancements handling 2017-06-12 21:06:30 +02:00
Matsv 95532bcdd5 Show entity names when replaced 2017-06-12 19:18:44 +02:00
Matsv a8e81935cc Handle FallingBlocks in 1.9.4-1.11.2 2017-06-10 16:34:08 +02:00
Matsv 2a1f6602ba Fix the Item Rewriter, implement 1.12 block rewrites & handle fallingblocks 2017-06-10 16:15:37 +02:00
Matsv d113e11c3b Metadata change voor illagers (Should be changed @ wiki.vg) 2017-06-08 19:35:26 +02:00
Matsv 5a4dd8bb6a ILLUSION_ILLAGER -> EVOCATION_ILLAGER (Better suggestions are welcome, bow will be invisible with the current entity.) 2017-06-08 18:43:23 +02:00
Matsv 85286095d7 Parrot -> Bat 2017-06-08 18:29:38 +02:00
Matsv 34d9ccbd5b Let PAaaS generate the sound changes 2017-06-08 17:27:58 +02:00
Matsv d98a511757 Bump viaversion & handle metadata changes 2017-06-08 17:07:55 +02:00
Matsv cb93950785 Map Packet ID changes for 1.12 2017-06-08 16:29:01 +02:00
Matsv ddf5324a82 Rename disabled llama slots & bump viaversion 2017-06-08 15:39:10 +02:00
Matsv 67d3eef37a Handle new Llama inventory 2017-06-08 15:31:34 +02:00
Matsv 7fda9dba0d Woops, forgot the new Shulker Shell item 2017-06-03 12:39:35 +02:00
Matsv da2e802e29 Handle chested horse metadata correctly 2017-06-03 12:22:47 +02:00
Matsv 347d449f51 Fix invisible shulkerboxes 2017-06-03 12:05:37 +02:00
Matsv 41d1ceb7cd Play Guardian animation when Totem of Undying is used. 2017-06-03 11:54:05 +02:00
Matsv 2060a698bd Fix Spawn eggs 2017-06-03 11:47:08 +02:00
Matsv ff73405d92 Rewrite Entity Type for spawners 2017-06-01 20:26:10 +02:00
Matsv 878230ebb1 Cleanup BlockItemRewriter & EntityRewriter 2017-06-01 19:09:48 +02:00
Matsv f33c694dd3 Cancel Shulker Decleration @ Update Block Entity & rewrite some sounds 2017-06-01 15:03:27 +02:00
Matsv 5ef109c037 Rewrite SoundRewriter and generate placeholders for 1.11 2017-05-31 21:02:34 +02:00
Matsv 373f519464 Cleanup 2017-05-31 14:09:50 +02:00
Matsv 51c502486e Continue 1.11 update. 2017-05-31 00:03:42 +02:00
Matsv 168803ae8a Update ViaVersion 2016-12-26 13:36:07 +01:00
Matsv a22ab7f625 Update ViaVersion 2016-12-26 13:34:55 +01:00
Matsv 4e5a12a514 Remove the instanceof check since it's no longer required. 2016-11-19 15:57:08 +01:00
Matsv 6cf94fce66 Change the way how EntityTrackers work to work correctly with multiple versions (WIP) 2016-11-19 15:51:38 +01:00
Matsv 0549cb5c3a Merge branches 'dev' and 'master' of https://github.com/Matsv/ViaBackwards into dev 2016-11-19 12:01:57 +01:00
Matsv 58810243dc Start working on the 1.11 update (Far from stable) 2016-11-19 12:01:22 +01:00
Matsv 04508e8c5c Back to snapshot 2016-11-19 10:57:55 +01:00
60 changed files with 5525 additions and 844 deletions

No files matched your search

+4 -1
View File
@@ -1,7 +1,10 @@
# ViaBackwards
Allows 1.9.x on a 1.10 Spigot server
Allows older Minecraft versions on a newer Minecraft server
Requires [ViaVersion](http://viaversion.com) to be installed
**Spigot page:** https://www.spigotmc.org/resources/viabackwards.27448/
### Supported versions:
![supported_versions](http://i.imgur.com/gXCifhK.png)
-9
View File
@@ -1,9 +0,0 @@
#!/usr/bin/env bash
cd .. &&
echo "Start maven build" &&
mvn clean install &&
echo "Copying" &&
cd ./all/ &&
cp ./target/viabackwards-all-2.0-DEV.jar /home/adr/mc/Spigot/TestServers/BungeeCord/plugins/ &&
echo "Done."
+1 -1
View File
@@ -15,7 +15,7 @@
<parent>
<artifactId>viabackwards-parent</artifactId>
<groupId>nl.matsv</groupId>
<version>2.0</version>
<version>2.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+2 -2
View File
@@ -15,7 +15,7 @@
<parent>
<artifactId>viabackwards-parent</artifactId>
<groupId>nl.matsv</groupId>
<version>2.0</version>
<version>2.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -32,7 +32,7 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.10.2-R0.1-SNAPSHOT</version>
<version>1.11-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -10,6 +10,7 @@
package nl.matsv.viabackwards;
import nl.matsv.viabackwards.api.ViaBackwardsPlatform;
import org.bukkit.plugin.java.JavaPlugin;
public class BukkitPlugin extends JavaPlugin implements ViaBackwardsPlatform {
@@ -17,4 +18,9 @@ public class BukkitPlugin extends JavaPlugin implements ViaBackwardsPlatform {
public void onEnable() {
this.init();
}
@Override
public void disable() {
getPluginLoader().disablePlugin(this);
}
}
+2 -2
View File
@@ -15,7 +15,7 @@
<parent>
<artifactId>viabackwards-parent</artifactId>
<groupId>nl.matsv</groupId>
<version>2.0</version>
<version>2.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -34,7 +34,7 @@
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.10-SNAPSHOT</version>
<version>1.11-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@@ -11,6 +11,7 @@
package nl.matsv.viabackwards;
import net.md_5.bungee.api.plugin.Plugin;
import nl.matsv.viabackwards.api.ViaBackwardsPlatform;
public class BungeePlugin extends Plugin implements ViaBackwardsPlatform {
@@ -18,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() {
}
}
+1 -1
View File
@@ -15,7 +15,7 @@
<parent>
<artifactId>viabackwards-parent</artifactId>
<groupId>nl.matsv</groupId>
<version>2.0</version>
<version>2.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -12,6 +12,7 @@ package nl.matsv.viabackwards;
import com.google.common.base.Preconditions;
import lombok.Getter;
import nl.matsv.viabackwards.api.ViaBackwardsPlatform;
public class ViaBackwards {
@Getter
@@ -22,4 +23,5 @@ public class ViaBackwards {
ViaBackwards.platform = platform;
}
}
@@ -0,0 +1,74 @@
/*
* 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;
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_12to1_11_1.Protocol1_11_1To1_12;
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 java.util.Collections;
import java.util.logging.Logger;
public interface ViaBackwardsPlatform {
/**
* Initialize ViaBackwards
*/
default void init() {
ViaBackwards.init(this);
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());
ProtocolRegistry.registerProtocol(new Protocol1_11_1To1_12(), Collections.singletonList(ProtocolVersion.v1_11_1.getId()), ProtocolVersion.v1_12.getId());
}
}
/**
* Logger provided by the platform
*
* @return logger instance
*/
Logger getLogger();
// TODO remove or better implement later
default boolean isOutdated() {
Class<?> clazz = null;
try {
clazz = Class.forName("us.myles.ViaVersion.api.type.types.version.Types1_12");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (clazz == null) {
getLogger().severe("================================");
getLogger().severe("YOUR VIAVERSION IS OUTDATED");
getLogger().severe("PLEASE USE THE LATEST VERSION");
getLogger().severe("LINK: https://viaversion.com");
getLogger().severe("VIABACKWARDS WILL NOW DISABLE");
getLogger().severe("================================");
disable();
return true;
}
return false;
}
/**
* Disable the plugin
*/
void disable();
}
@@ -0,0 +1,72 @@
/*
* 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.entities.blockitem;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import nl.matsv.viabackwards.utils.Block;
import us.myles.ViaVersion.api.minecraft.item.Item;
import us.myles.viaversion.libs.opennbt.tag.builtin.CompoundTag;
@RequiredArgsConstructor
@Getter
public class BlockItemSettings {
private final int id;
private Item repItem;
private Block repBlock;
private BlockEntityHandler blockEntityHandler;
private ItemHandler itemHandler;
public BlockItemSettings repItem(Item item) {
this.repItem = item;
return this;
}
public BlockItemSettings repBlock(Block block) {
this.repBlock = block;
return this;
}
public BlockItemSettings blockEntityHandler(BlockEntityHandler handler) {
this.blockEntityHandler = handler;
return this;
}
public BlockItemSettings itemHandler(ItemHandler handler) {
this.itemHandler = handler;
return this;
}
public boolean hasRepItem() {
return repItem != null;
}
public boolean hasRepBlock() {
return repBlock != null;
}
public boolean hasEntityHandler() {
return blockEntityHandler != null;
}
public boolean hasItemTagHandler() {
return itemHandler != null;
}
public interface BlockEntityHandler {
CompoundTag handleOrNewCompoundTag(int block, CompoundTag tag);
}
public interface ItemHandler {
Item handle(Item i);
}
}
@@ -8,11 +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.entities.meta;
import nl.matsv.viabackwards.api.exceptions.RemovedValueException;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
public interface MetaRewriter {
Metadata handleMetadata(boolean isObject, int entityType, Metadata data) throws RemovedValueException;
public interface MetaHandler {
Metadata handle(MetaHandlerEvent e) throws RemovedValueException;
}
@@ -0,0 +1,42 @@
/*
* 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.entities.meta;
import lombok.AllArgsConstructor;
import lombok.Getter;
import nl.matsv.viabackwards.api.entities.storage.EntityTracker;
import nl.matsv.viabackwards.api.entities.storage.MetaStorage;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import java.util.Optional;
@Getter
@AllArgsConstructor
public class MetaHandlerEvent {
private UserConnection user;
private EntityTracker.StoredEntity entity;
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();
}
}
@@ -0,0 +1,102 @@
/*
* 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.entities.meta;
import lombok.Getter;
import lombok.ToString;
import nl.matsv.viabackwards.api.entities.types.AbstractEntityType;
import nl.matsv.viabackwards.api.exceptions.RemovedValueException;
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 void handleIndexChange(final int newIndex) {
handle(e -> {
Metadata data = e.getData();
data.setId(newIndex);
return data;
});
}
public void removed() {
handle(e -> {
throw new RemovedValueException();
});
}
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;
}
}
return !(hasIndex() && metadata.getId() != getFilterIndex());
}
return false;
}
}
@@ -0,0 +1,45 @@
/*
* 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.entities.storage;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
@RequiredArgsConstructor
@Getter
@ToString
public class EntityData {
private final int id;
private final boolean isObject;
private String mobName;
private final int replacementId;
private final int objectData;
private MetaCreator defaultMeta;
public EntityData mobName(String name) {
this.mobName = name;
return this;
}
public void spawnMetadata(MetaCreator handler) {
this.defaultMeta = handler;
}
public boolean hasBaseMeta() {
return this.defaultMeta != null;
}
public interface MetaCreator {
void handle(MetaStorage storage);
}
}
@@ -0,0 +1,14 @@
/*
* 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.entities.storage;
public class EntityStorage {
}
@@ -0,0 +1,106 @@
/*
* 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.entities.storage;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import nl.matsv.viabackwards.api.BackwardsProtocol;
import nl.matsv.viabackwards.api.entities.types.AbstractEntityType;
import us.myles.ViaVersion.api.data.StoredObject;
import us.myles.ViaVersion.api.data.UserConnection;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
public class EntityTracker extends StoredObject {
private Map<BackwardsProtocol, ProtocolEntityTracker> trackers = new ConcurrentHashMap<>();
public EntityTracker(UserConnection user) {
super(user);
}
public void initProtocol(BackwardsProtocol protocol) {
trackers.put(protocol, new ProtocolEntityTracker());
}
public ProtocolEntityTracker get(BackwardsProtocol protocol) {
return trackers.get(protocol);
}
public class ProtocolEntityTracker {
private Map<Integer, StoredEntity> entityMap = new ConcurrentHashMap<>();
public void trackEntityType(int id, AbstractEntityType type) {
if (entityMap.containsKey(id))
return;
entityMap.put(id, new StoredEntity(id, type));
}
public void removeEntity(int id) {
entityMap.remove(id);
}
public AbstractEntityType getEntityType(int id) {
if (containsEntity(id))
return getEntity(id).get().getType();
return null;
}
public Optional<StoredEntity> getEntity(int id) {
return Optional.ofNullable(entityMap.get(id));
}
public boolean containsEntity(int id) {
return entityMap.containsKey(id);
}
}
@RequiredArgsConstructor
@Getter
@ToString
public class StoredEntity {
private final int entityId;
private final AbstractEntityType type;
Map<Class<? extends EntityStorage>, EntityStorage> storedObjects = new ConcurrentHashMap<>();
/**
* Get an object from the storage
*
* @param objectClass The class of the object to get
* @param <T> The type of the class you want to get.
* @return The requested object
*/
public <T extends EntityStorage> T get(Class<T> objectClass) {
return (T) storedObjects.get(objectClass);
}
/**
* Check if the storage has an object
*
* @param objectClass The object class to check
* @return True if the object is in the storage
*/
public boolean has(Class<? extends EntityStorage> objectClass) {
return storedObjects.containsKey(objectClass);
}
/**
* Put an object into the stored objects based on class
*
* @param object The object to store.
*/
public void put(EntityStorage object) {
storedObjects.put(object.getClass(), object);
}
}
}
@@ -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.entities.storage;
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);
}
}
@@ -8,28 +8,31 @@
* 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 lombok.AllArgsConstructor;
import lombok.Data;
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
import us.myles.viaversion.libs.opennbt.tag.builtin.CompoundTag;
package nl.matsv.viabackwards.api.entities.types;
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;
public interface AbstractEntityType {
@Override
public boolean isBiomeData() {
return biomeData != null;
}
}
/**
* Get the metadata id
*
* @return the metadata index
*/
int getId();
/**
* Get the parent class of the entity
*
* @return parent EntityType
*/
AbstractEntityType getParent();
boolean is(AbstractEntityType... types);
boolean is(AbstractEntityType type);
boolean isOrHasParent(AbstractEntityType type);
List<AbstractEntityType> getParents();
}
@@ -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;
package nl.matsv.viabackwards.api.entities.types;
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 java.util.Collections;
import java.util.logging.Logger;
public interface ViaBackwardsPlatform {
public interface AbstractObjectType {
/**
* Initialize ViaBackwards
*/
default void init() {
ViaBackwards.init(this);
ProtocolRegistry.registerProtocol(new Protocol1_9_4To1_10(), Collections.singletonList(ProtocolVersion.v1_9_3.getId()), ProtocolVersion.v1_10.getId());
}
/**
* Logger provided by the platform
* Get the metadata id
*
* @return logger instance
* @return the metadata index
*/
Logger getLogger();
int getId();
/**
* Get the entity type
*
* @return Entity type
*/
AbstractEntityType getType();
}
@@ -0,0 +1,240 @@
/*
* 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.entities.types;
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 {
public static EntityType getTypeFromId(int typeID, boolean isObject) {
Optional<EntityType> type;
if (isObject)
type = ObjectType.getPCEntity(typeID);
else
type = EntityType.findById(typeID);
if (!type.isPresent()) {
ViaBackwards.getPlatform().getLogger().severe("[EntityType1_10] Could not find type id " + typeID + " isObject=" + isObject);
return EntityType.ENTITY; // Fall back to the basic ENTITY
}
return type.get();
}
@AllArgsConstructor
@Getter
public enum EntityType implements AbstractEntityType {
ENTITY(-1),
DROPPED_ITEM(1, EntityType.ENTITY),
EXPERIENCE_ORB(2, EntityType.ENTITY),
LEASH_HITCH(8, EntityType.ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata
PAINTING(9, EntityType.ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata
ARROW(10, EntityType.ENTITY),
SNOWBALL(11, EntityType.ENTITY), // Actually EntityProjectile
FIREBALL(12, EntityType.ENTITY),
SMALL_FIREBALL(13, EntityType.ENTITY),
ENDER_PEARL(14, EntityType.ENTITY), // Actually EntityProjectile
ENDER_SIGNAL(15, EntityType.ENTITY),
THROWN_EXP_BOTTLE(17, EntityType.ENTITY),
ITEM_FRAME(18, EntityType.ENTITY), // Actually EntityHanging
WITHER_SKULL(19, EntityType.ENTITY),
PRIMED_TNT(20, EntityType.ENTITY),
FALLING_BLOCK(21, EntityType.ENTITY),
FIREWORK(22, EntityType.ENTITY),
TIPPED_ARROW(23, EntityType.ARROW),
SPECTRAL_ARROW(24, EntityType.ARROW),
SHULKER_BULLET(25, EntityType.ENTITY),
DRAGON_FIREBALL(26, EntityType.FIREBALL),
ENTITY_LIVING(-1, ENTITY),
ENTITY_INSENTIENT(-1, ENTITY_LIVING),
ENTITY_AGEABLE(-1, ENTITY_INSENTIENT),
ENTITY_TAMEABLE_ANIMAL(-1, ENTITY_AGEABLE),
ENTITY_HUMAN(-1, ENTITY_LIVING),
ARMOR_STAND(30, EntityType.ENTITY_LIVING),
// Vehicles
MINECART_ABSTRACT(-1, ENTITY),
MINECART_COMMAND(40, MINECART_ABSTRACT),
BOAT(41, ENTITY),
MINECART_RIDEABLE(42, MINECART_ABSTRACT),
MINECART_CHEST(43, MINECART_ABSTRACT),
MINECART_FURNACE(44, MINECART_ABSTRACT),
MINECART_TNT(45, MINECART_ABSTRACT),
MINECART_HOPPER(46, MINECART_ABSTRACT),
MINECART_MOB_SPAWNER(47, MINECART_ABSTRACT),
CREEPER(50, ENTITY_INSENTIENT),
SKELETON(51, ENTITY_INSENTIENT),
SPIDER(52, ENTITY_INSENTIENT),
GIANT(53, ENTITY_INSENTIENT),
ZOMBIE(54, ENTITY_INSENTIENT),
SLIME(55, ENTITY_INSENTIENT),
GHAST(56, ENTITY_INSENTIENT),
PIG_ZOMBIE(57, ZOMBIE),
ENDERMAN(58, ENTITY_INSENTIENT),
CAVE_SPIDER(59, SPIDER),
SILVERFISH(60, ENTITY_INSENTIENT),
BLAZE(61, ENTITY_INSENTIENT),
MAGMA_CUBE(62, SLIME),
ENDER_DRAGON(63, ENTITY_INSENTIENT),
WITHER(64, ENTITY_INSENTIENT),
BAT(65, ENTITY_INSENTIENT),
WITCH(66, ENTITY_INSENTIENT),
ENDERMITE(67, ENTITY_INSENTIENT),
GUARDIAN(68, ENTITY_INSENTIENT),
IRON_GOLEM(99, ENTITY_INSENTIENT), // moved up to avoid illegal forward references
SHULKER(69, EntityType.IRON_GOLEM),
PIG(90, ENTITY_AGEABLE),
SHEEP(91, ENTITY_AGEABLE),
COW(92, ENTITY_AGEABLE),
CHICKEN(93, ENTITY_AGEABLE),
SQUID(94, ENTITY_INSENTIENT),
WOLF(95, ENTITY_TAMEABLE_ANIMAL),
MUSHROOM_COW(96, COW),
SNOWMAN(97, EntityType.IRON_GOLEM),
OCELOT(98, ENTITY_TAMEABLE_ANIMAL),
HORSE(100, ENTITY_AGEABLE),
RABBIT(101, ENTITY_AGEABLE),
POLAR_BEAR(102, ENTITY_AGEABLE),
VILLAGER(120, ENTITY_AGEABLE),
ENDER_CRYSTAL(200, ENTITY),
SPLASH_POTION(-1, ENTITY),
LINGERING_POTION(-1, SPLASH_POTION),
AREA_EFFECT_CLOUD(-1, ENTITY),
EGG(-1, ENTITY),
FISHING_HOOK(-1, ENTITY),
LIGHTNING(-1, ENTITY),
WEATHER(-1, ENTITY),
PLAYER(-1, ENTITY_HUMAN),
COMPLEX_PART(-1, ENTITY);
private final int id;
private final EntityType parent;
EntityType(int id) {
this.id = id;
this.parent = null;
}
public static Optional<EntityType> findById(int id) {
if (id == -1) // Check if this is called
return Optional.empty();
for (EntityType ent : EntityType.values())
if (ent.getId() == id)
return Optional.of(ent);
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 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),
SNOWBALL(61, EntityType.SNOWBALL),
EGG(62, EntityType.EGG),
FIREBALL(63, EntityType.FIREBALL),
SMALL_FIREBALL(64, EntityType.SMALL_FIREBALL),
ENDER_PEARL(65, EntityType.ENDER_PEARL),
WITHER_SKULL(66, EntityType.WITHER_SKULL),
SHULKER_BULLET(67, EntityType.SHULKER_BULLET),
FALLING_BLOCK(70, EntityType.FALLING_BLOCK),
ITEM_FRAME(71, EntityType.ITEM_FRAME),
ENDER_SIGNAL(72, EntityType.ENDER_SIGNAL),
POTION(73, EntityType.SPLASH_POTION),
THROWN_EXP_BOTTLE(75, EntityType.THROWN_EXP_BOTTLE),
FIREWORK(76, EntityType.FIREWORK),
LEASH(77, EntityType.LEASH_HITCH),
ARMOR_STAND(78, EntityType.ARMOR_STAND),
FISHIHNG_HOOK(90, EntityType.FISHING_HOOK),
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private final int id;
private final EntityType type;
public static Optional<ObjectType> findById(int id) {
if (id == -1)
return Optional.empty();
for (ObjectType ent : ObjectType.values())
if (ent.getId() == id)
return Optional.of(ent);
return Optional.empty();
}
public static Optional<EntityType> getPCEntity(int id) {
Optional<ObjectType> output = findById(id);
if (!output.isPresent())
return Optional.empty();
return Optional.of(output.get().getType());
}
}
}
@@ -0,0 +1,269 @@
/*
* 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.entities.types;
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) throws Exception {
Optional<EntityType> type;
if (isObject)
type = ObjectType.getPCEntity(typeID);
else
type = EntityType.findById(typeID);
if (!type.isPresent()) {
ViaBackwards.getPlatform().getLogger().severe("[EntityType1_11] Could not find type id " + typeID + " isObject=" + isObject);
return EntityType.ENTITY; // Fall back to the basic ENTITY
}
return type.get();
}
@AllArgsConstructor
@Getter
public enum EntityType implements AbstractEntityType {
ENTITY(-1),
DROPPED_ITEM(1, ENTITY),
EXPERIENCE_ORB(2, ENTITY),
LEASH_HITCH(8, ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata
PAINTING(9, ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata
ARROW(10, ENTITY),
SNOWBALL(11, ENTITY), // Actually EntityProjectile
FIREBALL(12, ENTITY),
SMALL_FIREBALL(13, ENTITY),
ENDER_PEARL(14, ENTITY), // Actually EntityProjectile
ENDER_SIGNAL(15, ENTITY),
THROWN_EXP_BOTTLE(17, ENTITY),
ITEM_FRAME(18, ENTITY), // Actually EntityHanging
WITHER_SKULL(19, ENTITY),
PRIMED_TNT(20, ENTITY),
FALLING_BLOCK(21, ENTITY),
FIREWORK(22, ENTITY),
SPECTRAL_ARROW(24, ARROW),
SHULKER_BULLET(25, ENTITY),
DRAGON_FIREBALL(26, FIREBALL),
EVOCATION_FANGS(33, ENTITY),
ENTITY_LIVING(-1, ENTITY),
ENTITY_INSENTIENT(-1, ENTITY_LIVING),
ENTITY_AGEABLE(-1, ENTITY_INSENTIENT),
ENTITY_TAMEABLE_ANIMAL(-1, ENTITY_AGEABLE),
ENTITY_HUMAN(-1, ENTITY_LIVING),
ARMOR_STAND(30, ENTITY_LIVING),
EVOCATION_ILLAGER(34, ENTITY_INSENTIENT),
VEX(35, ENTITY_INSENTIENT),
VINDICATION_ILLAGER(36, ENTITY_INSENTIENT),
// Vehicles
MINECART_ABSTRACT(-1, ENTITY),
MINECART_COMMAND(40, MINECART_ABSTRACT),
BOAT(41, ENTITY),
MINECART_RIDEABLE(42, MINECART_ABSTRACT),
MINECART_CHEST(43, MINECART_ABSTRACT),
MINECART_FURNACE(44, MINECART_ABSTRACT),
MINECART_TNT(45, MINECART_ABSTRACT),
MINECART_HOPPER(46, MINECART_ABSTRACT),
MINECART_MOB_SPAWNER(47, MINECART_ABSTRACT),
CREEPER(50, ENTITY_INSENTIENT),
ABSTRACT_SKELETON(-1, ENTITY_INSENTIENT),
SKELETON(51, ABSTRACT_SKELETON),
WITHER_SKELETON(5, ABSTRACT_SKELETON),
STRAY(6, ABSTRACT_SKELETON),
SPIDER(52, ENTITY_INSENTIENT),
GIANT(53, ENTITY_INSENTIENT),
ZOMBIE(54, ENTITY_INSENTIENT),
HUSK(23, ZOMBIE),
ZOMBIE_VILLAGER(27, ZOMBIE),
SLIME(55, ENTITY_INSENTIENT),
GHAST(56, ENTITY_INSENTIENT),
PIG_ZOMBIE(57, ZOMBIE),
ENDERMAN(58, ENTITY_INSENTIENT),
CAVE_SPIDER(59, SPIDER),
SILVERFISH(60, ENTITY_INSENTIENT),
BLAZE(61, ENTITY_INSENTIENT),
MAGMA_CUBE(62, SLIME),
ENDER_DRAGON(63, ENTITY_INSENTIENT),
WITHER(64, ENTITY_INSENTIENT),
BAT(65, ENTITY_INSENTIENT),
WITCH(66, ENTITY_INSENTIENT),
ENDERMITE(67, ENTITY_INSENTIENT),
GUARDIAN(68, ENTITY_INSENTIENT),
ELDER_GUARDIAN(4, EntityType.GUARDIAN), // Moved down to avoid illegal forward reference
IRON_GOLEM(99, ENTITY_INSENTIENT), // moved up to avoid illegal forward references
SHULKER(69, EntityType.IRON_GOLEM),
PIG(90, ENTITY_AGEABLE),
SHEEP(91, ENTITY_AGEABLE),
COW(92, ENTITY_AGEABLE),
CHICKEN(93, ENTITY_AGEABLE),
SQUID(94, ENTITY_INSENTIENT),
WOLF(95, ENTITY_TAMEABLE_ANIMAL),
MUSHROOM_COW(96, COW),
SNOWMAN(97, EntityType.IRON_GOLEM),
OCELOT(98, ENTITY_TAMEABLE_ANIMAL),
ABSTRACT_HORSE(-1, ENTITY_AGEABLE),
HORSE(100, ABSTRACT_HORSE),
SKELETON_HORSE(28, ABSTRACT_HORSE),
ZOMBIE_HORSE(29, ABSTRACT_HORSE),
CHESTED_HORSE(-1, ABSTRACT_HORSE),
DONKEY(31, CHESTED_HORSE),
MULE(32, CHESTED_HORSE),
LIAMA(103, CHESTED_HORSE),
RABBIT(101, ENTITY_AGEABLE),
POLAR_BEAR(102, ENTITY_AGEABLE),
VILLAGER(120, ENTITY_AGEABLE),
ENDER_CRYSTAL(200, ENTITY),
SPLASH_POTION(-1, ENTITY),
LINGERING_POTION(-1, SPLASH_POTION),
AREA_EFFECT_CLOUD(-1, ENTITY),
EGG(-1, ENTITY),
FISHING_HOOK(-1, ENTITY),
LIGHTNING(-1, ENTITY),
WEATHER(-1, ENTITY),
PLAYER(-1, ENTITY_HUMAN),
COMPLEX_PART(-1, ENTITY),
LIAMA_SPIT(-1, ENTITY);
private final int id;
private final EntityType parent;
EntityType(int id) {
this.id = id;
this.parent = null;
}
public static Optional<EntityType> findById(int id) {
if (id == -1) // Check if this is called
return Optional.empty();
for (EntityType ent : EntityType.values())
if (ent.getId() == id)
return Optional.of(ent);
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 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.ARROW),
SNOWBALL(61, EntityType.SNOWBALL),
EGG(62, EntityType.EGG),
FIREBALL(63, EntityType.FIREBALL),
SMALL_FIREBALL(64, EntityType.SMALL_FIREBALL),
ENDER_PEARL(65, EntityType.ENDER_PEARL),
WITHER_SKULL(66, EntityType.WITHER_SKULL),
SHULKER_BULLET(67, EntityType.SHULKER_BULLET),
LIAMA_SPIT(68, EntityType.LIAMA_SPIT),
FALLING_BLOCK(70, EntityType.FALLING_BLOCK),
ITEM_FRAME(71, EntityType.ITEM_FRAME),
ENDER_SIGNAL(72, EntityType.ENDER_SIGNAL),
POTION(73, EntityType.SPLASH_POTION),
THROWN_EXP_BOTTLE(75, EntityType.THROWN_EXP_BOTTLE),
FIREWORK(76, EntityType.FIREWORK),
LEASH(77, EntityType.LEASH_HITCH),
ARMOR_STAND(78, EntityType.ARMOR_STAND),
EVOCATION_FANGS(79, EntityType.EVOCATION_FANGS),
FISHIHNG_HOOK(90, EntityType.FISHING_HOOK),
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private final int id;
private final EntityType type;
public static Optional<ObjectType> findById(int id) {
if (id == -1)
return Optional.empty();
for (ObjectType ent : ObjectType.values())
if (ent.getId() == id)
return Optional.of(ent);
return Optional.empty();
}
public static Optional<EntityType> getPCEntity(int id) {
Optional<ObjectType> output = findById(id);
if (!output.isPresent())
return Optional.empty();
return Optional.of(output.get().getType());
}
}
}
@@ -0,0 +1,272 @@
/*
* 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.entities.types;
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_12 {
public static EntityType getTypeFromId(int typeID, boolean isObject) throws Exception {
Optional<EntityType> type;
if (isObject)
type = ObjectType.getPCEntity(typeID);
else
type = EntityType.findById(typeID);
if (!type.isPresent()) {
ViaBackwards.getPlatform().getLogger().severe("[EntityType1_12] Could not find type id " + typeID + " isObject=" + isObject);
return EntityType.ENTITY; // Fall back to the basic ENTITY
}
return type.get();
}
@AllArgsConstructor
@Getter
public enum EntityType implements AbstractEntityType {
ENTITY(-1),
DROPPED_ITEM(1, ENTITY),
EXPERIENCE_ORB(2, ENTITY),
LEASH_HITCH(8, ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata
PAINTING(9, ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata
ARROW(10, ENTITY),
SNOWBALL(11, ENTITY), // Actually EntityProjectile
FIREBALL(12, ENTITY),
SMALL_FIREBALL(13, ENTITY),
ENDER_PEARL(14, ENTITY), // Actually EntityProjectile
ENDER_SIGNAL(15, ENTITY),
THROWN_EXP_BOTTLE(17, ENTITY),
ITEM_FRAME(18, ENTITY), // Actually EntityHanging
WITHER_SKULL(19, ENTITY),
PRIMED_TNT(20, ENTITY),
FALLING_BLOCK(21, ENTITY),
FIREWORK(22, ENTITY),
SPECTRAL_ARROW(24, ARROW),
SHULKER_BULLET(25, ENTITY),
DRAGON_FIREBALL(26, FIREBALL),
EVOCATION_FANGS(33, ENTITY),
ENTITY_LIVING(-1, ENTITY),
ENTITY_INSENTIENT(-1, ENTITY_LIVING),
ENTITY_AGEABLE(-1, ENTITY_INSENTIENT),
ENTITY_TAMEABLE_ANIMAL(-1, ENTITY_AGEABLE),
ENTITY_HUMAN(-1, ENTITY_LIVING),
ARMOR_STAND(30, ENTITY_LIVING),
ENTITY_ILLAGER_ABSTRACT(-1, ENTITY_INSENTIENT),
EVOCATION_ILLAGER(34, ENTITY_ILLAGER_ABSTRACT),
VEX(35, ENTITY_INSENTIENT),
VINDICATION_ILLAGER(36, ENTITY_ILLAGER_ABSTRACT),
ILLUSION_ILLAGER(37, EVOCATION_ILLAGER),
// Vehicles
MINECART_ABSTRACT(-1, ENTITY),
MINECART_COMMAND(40, MINECART_ABSTRACT),
BOAT(41, ENTITY),
MINECART_RIDEABLE(42, MINECART_ABSTRACT),
MINECART_CHEST(43, MINECART_ABSTRACT),
MINECART_FURNACE(44, MINECART_ABSTRACT),
MINECART_TNT(45, MINECART_ABSTRACT),
MINECART_HOPPER(46, MINECART_ABSTRACT),
MINECART_MOB_SPAWNER(47, MINECART_ABSTRACT),
CREEPER(50, ENTITY_INSENTIENT),
ABSTRACT_SKELETON(-1, ENTITY_INSENTIENT),
SKELETON(51, ABSTRACT_SKELETON),
WITHER_SKELETON(5, ABSTRACT_SKELETON),
STRAY(6, ABSTRACT_SKELETON),
SPIDER(52, ENTITY_INSENTIENT),
GIANT(53, ENTITY_INSENTIENT),
ZOMBIE(54, ENTITY_INSENTIENT),
HUSK(23, ZOMBIE),
ZOMBIE_VILLAGER(27, ZOMBIE),
SLIME(55, ENTITY_INSENTIENT),
GHAST(56, ENTITY_INSENTIENT),
PIG_ZOMBIE(57, ZOMBIE),
ENDERMAN(58, ENTITY_INSENTIENT),
CAVE_SPIDER(59, SPIDER),
SILVERFISH(60, ENTITY_INSENTIENT),
BLAZE(61, ENTITY_INSENTIENT),
MAGMA_CUBE(62, SLIME),
ENDER_DRAGON(63, ENTITY_INSENTIENT),
WITHER(64, ENTITY_INSENTIENT),
BAT(65, ENTITY_INSENTIENT),
WITCH(66, ENTITY_INSENTIENT),
ENDERMITE(67, ENTITY_INSENTIENT),
GUARDIAN(68, ENTITY_INSENTIENT),
ELDER_GUARDIAN(4, EntityType.GUARDIAN), // Moved down to avoid illegal forward reference
IRON_GOLEM(99, ENTITY_INSENTIENT), // moved up to avoid illegal forward references
SHULKER(69, EntityType.IRON_GOLEM),
PIG(90, ENTITY_AGEABLE),
SHEEP(91, ENTITY_AGEABLE),
COW(92, ENTITY_AGEABLE),
CHICKEN(93, ENTITY_AGEABLE),
SQUID(94, ENTITY_INSENTIENT),
WOLF(95, ENTITY_TAMEABLE_ANIMAL),
MUSHROOM_COW(96, COW),
SNOWMAN(97, EntityType.IRON_GOLEM),
OCELOT(98, ENTITY_TAMEABLE_ANIMAL),
PARROT(105, ENTITY_TAMEABLE_ANIMAL),
ABSTRACT_HORSE(-1, ENTITY_AGEABLE),
HORSE(100, ABSTRACT_HORSE),
SKELETON_HORSE(28, ABSTRACT_HORSE),
ZOMBIE_HORSE(29, ABSTRACT_HORSE),
CHESTED_HORSE(-1, ABSTRACT_HORSE),
DONKEY(31, CHESTED_HORSE),
MULE(32, CHESTED_HORSE),
LIAMA(103, CHESTED_HORSE),
RABBIT(101, ENTITY_AGEABLE),
POLAR_BEAR(102, ENTITY_AGEABLE),
VILLAGER(120, ENTITY_AGEABLE),
ENDER_CRYSTAL(200, ENTITY),
SPLASH_POTION(-1, ENTITY),
LINGERING_POTION(-1, SPLASH_POTION),
AREA_EFFECT_CLOUD(-1, ENTITY),
EGG(-1, ENTITY),
FISHING_HOOK(-1, ENTITY),
LIGHTNING(-1, ENTITY),
WEATHER(-1, ENTITY),
PLAYER(-1, ENTITY_HUMAN),
COMPLEX_PART(-1, ENTITY),
LIAMA_SPIT(-1, ENTITY);
private final int id;
private final EntityType parent;
EntityType(int id) {
this.id = id;
this.parent = null;
}
public static Optional<EntityType> findById(int id) {
if (id == -1) // Check if this is called
return Optional.empty();
for (EntityType ent : EntityType.values())
if (ent.getId() == id)
return Optional.of(ent);
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 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.ARROW),
SNOWBALL(61, EntityType.SNOWBALL),
EGG(62, EntityType.EGG),
FIREBALL(63, EntityType.FIREBALL),
SMALL_FIREBALL(64, EntityType.SMALL_FIREBALL),
ENDER_PEARL(65, EntityType.ENDER_PEARL),
WITHER_SKULL(66, EntityType.WITHER_SKULL),
SHULKER_BULLET(67, EntityType.SHULKER_BULLET),
LIAMA_SPIT(68, EntityType.LIAMA_SPIT),
FALLING_BLOCK(70, EntityType.FALLING_BLOCK),
ITEM_FRAME(71, EntityType.ITEM_FRAME),
ENDER_SIGNAL(72, EntityType.ENDER_SIGNAL),
POTION(73, EntityType.SPLASH_POTION),
THROWN_EXP_BOTTLE(75, EntityType.THROWN_EXP_BOTTLE),
FIREWORK(76, EntityType.FIREWORK),
LEASH(77, EntityType.LEASH_HITCH),
ARMOR_STAND(78, EntityType.ARMOR_STAND),
EVOCATION_FANGS(79, EntityType.EVOCATION_FANGS),
FISHIHNG_HOOK(90, EntityType.FISHING_HOOK),
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private final int id;
private final EntityType type;
public static Optional<ObjectType> findById(int id) {
if (id == -1)
return Optional.empty();
for (ObjectType ent : ObjectType.values())
if (ent.getId() == id)
return Optional.of(ent);
return Optional.empty();
}
public static Optional<EntityType> getPCEntity(int id) {
Optional<ObjectType> output = findById(id);
if (!output.isPresent())
return Optional.empty();
return Optional.of(output.get().getType());
}
}
}
@@ -10,46 +10,80 @@
package nl.matsv.viabackwards.api.rewriters;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import net.md_5.bungee.api.ChatColor;
import nl.matsv.viabackwards.api.BackwardsProtocol;
import nl.matsv.viabackwards.api.entities.blockitem.BlockItemSettings;
import nl.matsv.viabackwards.protocol.protocol1_12to1_11_1.data.BlockColors;
import nl.matsv.viabackwards.utils.Block;
import nl.matsv.viabackwards.utils.ItemUtil;
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection;
import us.myles.ViaVersion.api.minecraft.item.Item;
import us.myles.viaversion.libs.opennbt.conversion.builtin.CompoundTagConverter;
import us.myles.viaversion.libs.opennbt.tag.builtin.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public abstract class BlockItemRewriter<T extends BackwardsProtocol> extends Rewriter<T> {
private static final CompoundTagConverter converter = new CompoundTagConverter();
private final Map<Short, Item> itemRewriter = new ConcurrentHashMap<>();
private final Map<Integer, Block> blockRewriter = new ConcurrentHashMap<>();
private final Map<Integer, BlockItemSettings> replacementData = new ConcurrentHashMap<>();
protected void rewriteItem(int oldItem, Item newItem) {
itemRewriter.put((short) oldItem, newItem);
protected BlockItemSettings rewrite(int itemId) {
BlockItemSettings settings = new BlockItemSettings(itemId);
replacementData.put(itemId, settings);
return settings;
}
protected void rewriteBlockItem(int oldId, Item newItem, Block newBlock) {
itemRewriter.put((short) oldId, newItem);
blockRewriter.put(oldId, newBlock);
}
protected Item handleItemToClient(Item item) {
if (item == null)
protected Item handleItemToClient(Item i) {
if (i == null)
return null;
if (!itemRewriter.containsKey(item.getId()))
return item;
Item i = ItemUtil.copyItem(itemRewriter.get(item.getId()));
if (!replacementData.containsKey((int) i.getId()))
return i;
BlockItemSettings data = replacementData.get((int) i.getId());
if (i.getTag() == null)
i.setTag(new CompoundTag(""));
i.getTag().put(createViaNBT(item));
Item original = ItemUtil.copyItem(i);
if (data.hasRepItem()) {
i = ItemUtil.copyItem(data.getRepItem());
if (item.getTag() != null)
for (Tag ai : item.getTag())
i.getTag().put(ai);
if (i.getTag() == null)
i.setTag(new CompoundTag(""));
// Backup data for toServer
i.getTag().put(createViaNBT(original));
// Keep original data
if (original.getTag() != null)
for (Tag ai : original.getTag())
i.getTag().put(ai);
// Handle colors
if (i.getTag().contains("display")) {
CompoundTag tag = i.getTag().get("display");
if (tag.contains("Name")) {
String value = (String) tag.get("Name").getValue();
tag.put(new StringTag("Name",
value.replaceAll("%viabackwards_color%", BlockColors.get((int) original.getData()))));
}
}
i.setAmount(original.getAmount());
// Keep original data when -1
if (i.getData() == -1)
i.setData(original.getData());
}
if (data.hasItemTagHandler()) {
if (!i.getTag().contains("ViaBackwards|" + getProtocolName()))
i.getTag().put(createViaNBT(original));
data.getItemHandler().handle(i);
}
i.setAmount(item.getAmount());
return i;
}
@@ -57,8 +91,8 @@ public abstract class BlockItemRewriter<T extends BackwardsProtocol> extends Rew
if (item == null || item.getTag() == null)
return null;
CompoundTag tag = item.getTag();
if (tag.contains("ViaBackwards")) {
CompoundTag via = tag.get("ViaBackwards");
if (tag.contains("ViaBackwards|" + getProtocolName())) {
CompoundTag via = tag.get("ViaBackwards|" + getProtocolName());
short id = (short) via.get("id").getValue();
short data = (short) via.get("data").getValue();
@@ -70,24 +104,97 @@ public abstract class BlockItemRewriter<T extends BackwardsProtocol> extends Rew
item.setAmount(amount);
item.setTag(converter.convert("", converter.convert(extras)));
// Remove data tag
tag.remove("ViaBackwards");
tag.remove("ViaBackwards|" + getProtocolName());
}
return item;
}
protected Block handleBlock(int block) {
public 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));
}
public Block handleBlock(int block, int data) {
if (!containsBlock(block))
return null;
return blockRewriter.get(block);
Block b = replacementData.get(block).getRepBlock().clone();
// For some blocks, the data can still be useful (:
if (b.getData() == -1)
b.setData(data);
return b;
}
protected void handleChunk(Chunk chunk) {
// Map Block Entities
Map<Pos, CompoundTag> tags = new HashMap<>();
for (CompoundTag tag : chunk.getBlockEntities()) {
if (!(tag.contains("x") && tag.contains("y") && tag.contains("z")))
continue;
Pos pos = new Pos(
(int) tag.get("x").getValue() % 16,
(int) tag.get("y").getValue(),
(int) tag.get("z").getValue() % 16);
tags.put(pos, tag);
}
for (int i = 0; i < chunk.getSections().length; i++) {
ChunkSection 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.getBlock(x, y, z);
int btype = block >> 4;
int meta = block & 15;
if (containsBlock(btype)) {
Block b = handleBlock(btype, meta); // Type / data
section.setBlock(x, y, z, b.getId(), b.getData());
}
// Entity Tags
if (hasBlockEntityHandler(btype)) {
Pos pos = new Pos(x, (y + (i << 4)), z);
CompoundTag tag = null;
if (tags.containsKey(pos)) {
tag = tags.get(pos);
} else {
tag = new CompoundTag("");
tag.put(new IntTag("x", x + (chunk.getX() << 4)));
tag.put(new IntTag("y", y + (i << 4)));
tag.put(new IntTag("z", z + (chunk.getZ() << 4)));
chunk.getBlockEntities().add(tag);
}
replacementData.get(btype).getBlockEntityHandler().handleOrNewCompoundTag(block, tag);
}
}
}
}
}
}
protected boolean containsBlock(int block) {
return blockRewriter.containsKey(block);
return replacementData.containsKey(block) && replacementData.get(block).hasRepBlock();
}
protected boolean hasBlockEntityHandler(int block) {
return replacementData.containsKey(block) && replacementData.get(block).hasEntityHandler();
}
protected boolean hasItemTagHandler(int block) {
return replacementData.containsKey(block) && replacementData.get(block).hasItemTagHandler();
}
private CompoundTag createViaNBT(Item i) {
CompoundTag tag = new CompoundTag("ViaBackwards");
CompoundTag tag = new CompoundTag("ViaBackwards|" + getProtocolName());
tag.put(new ShortTag("id", i.getId()));
tag.put(new ShortTag("data", i.getData()));
tag.put(new ByteTag("amount", i.getAmount()));
@@ -101,7 +208,19 @@ public abstract class BlockItemRewriter<T extends BackwardsProtocol> extends Rew
protected CompoundTag getNamedTag(String text) {
CompoundTag tag = new CompoundTag("");
tag.put(new CompoundTag("display"));
((CompoundTag) tag.get("display")).put(new StringTag("Name", text));
((CompoundTag) tag.get("display")).put(new StringTag("Name", ChatColor.RESET + text));
return tag;
}
private String getProtocolName() {
return getProtocol().getClass().getSimpleName();
}
@Data
@AllArgsConstructor
@ToString
@EqualsAndHashCode
private class Pos {
private int x, y, z;
}
}
@@ -10,108 +10,150 @@
package nl.matsv.viabackwards.api.rewriters;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import nl.matsv.viabackwards.ViaBackwards;
import nl.matsv.viabackwards.api.BackwardsProtocol;
import nl.matsv.viabackwards.api.MetaRewriter;
import nl.matsv.viabackwards.api.entities.meta.MetaHandlerEvent;
import nl.matsv.viabackwards.api.entities.meta.MetaHandlerSettings;
import nl.matsv.viabackwards.api.entities.storage.EntityData;
import nl.matsv.viabackwards.api.entities.storage.EntityTracker;
import nl.matsv.viabackwards.api.entities.storage.MetaStorage;
import nl.matsv.viabackwards.api.entities.types.AbstractEntityType;
import nl.matsv.viabackwards.api.entities.types.AbstractObjectType;
import nl.matsv.viabackwards.api.exceptions.RemovedValueException;
import nl.matsv.viabackwards.api.storage.EntityTracker;
import nl.matsv.viabackwards.api.storage.EntityType;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.minecraft.metadata.MetaType;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_9;
import us.myles.ViaVersion.exception.CancelException;
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<Short, Short> entityTypes = new ConcurrentHashMap<>();
private final Map<Short, Short> objectTypes = new ConcurrentHashMap<>();
private final Map<AbstractEntityType, EntityData> entityTypes = new ConcurrentHashMap<>();
private final Map<AbstractObjectType, EntityData> objectTypes = new ConcurrentHashMap<>();
private final List<MetaHandlerSettings> metaHandlers = new ArrayList<>();
private final List<MetaRewriter> metaRewriters = new ArrayList<>();
@Getter(AccessLevel.PROTECTED)
@Setter(AccessLevel.PROTECTED)
private MetaType displayNameMetaType = MetaType1_9.String;
@Getter(AccessLevel.PROTECTED)
@Setter(AccessLevel.PROTECTED)
private int displayNameIndex = 2;
protected short getNewEntityType(UserConnection connection, int id) {
EntityType type = getEntityType(connection, id);
if (type.isObject()) {
return getNewObjectId(type.getEntityType());
} else {
return getNewEntityId(type.getEntityType());
protected AbstractEntityType getEntityType(UserConnection connection, int id) {
return getEntityTracker(connection).getEntityType(id);
}
protected void addTrackedEntity(UserConnection connection, int entityId, AbstractEntityType type) {
getEntityTracker(connection).trackEntityType(entityId, type);
}
protected Optional<EntityData> getEntityData(AbstractEntityType type) {
if (!entityTypes.containsKey(type))
return Optional.empty();
return Optional.of(entityTypes.get(type));
}
protected Optional<EntityData> getObjectData(AbstractObjectType type) {
if (!objectTypes.containsKey(type))
return Optional.empty();
return Optional.of(objectTypes.get(type));
}
protected EntityData regEntType(AbstractEntityType oldEnt, AbstractEntityType replacement) {
return regEntType(oldEnt, (short) replacement.getId());
}
private EntityData regEntType(AbstractEntityType oldEnt, short replacementId) {
EntityData data = new EntityData(oldEnt.getId(), false, replacementId, -1);
entityTypes.put(oldEnt, data);
return data;
}
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 {
Optional<EntityTracker.StoredEntity> optEntity = getEntityTracker(user).getEntity(entityId);
if (!optEntity.isPresent()) {
if (!Via.getConfig().isSuppressMetadataErrors())
ViaBackwards.getPlatform().getLogger().warning("Metadata for entity id: " + entityId + " not sent because the entity doesn't exist. " + storage);
throw new CancelException();
}
}
protected EntityType getEntityType(UserConnection connection, int id) {
return connection.get(EntityTracker.class).getEntityType(id);
}
EntityTracker.StoredEntity entity = optEntity.get();
AbstractEntityType type = entity.getType();
protected void addTrackedEntity(UserConnection connection, int entityId, boolean isObject, short typeId) {
connection.get(EntityTracker.class).trackEntityType(entityId, new EntityType(isObject, typeId));
}
List<Metadata> newList = new CopyOnWriteArrayList<>();
protected void rewriteEntityId(int oldId, int newId) {
entityTypes.put((short) oldId, (short) newId);
}
for (MetaHandlerSettings settings : metaHandlers) {
for (Metadata md : storage.getMetaDataList()) {
Metadata nmd = md;
try {
if (settings.isGucci(type, nmd))
nmd = settings.getHandler().handle(new MetaHandlerEvent(user, entity, nmd.getId(), nmd, storage));
protected boolean isRewriteEntityId(short id) {
return entityTypes.containsKey(id);
}
protected short getNewEntityId(short oldId) {
if (!isRewriteEntityId(oldId))
return oldId;
return entityTypes.get(oldId);
}
protected void rewriteObjectId(int oldId, int newId) {
objectTypes.put((short) oldId, (short) newId);
}
protected boolean isRewriteObjectId(short id) {
return objectTypes.containsKey(id);
}
protected short getNewObjectId(short oldId) {
if (!isRewriteObjectId(oldId))
return oldId;
return objectTypes.get(oldId);
}
public void registerMetaRewriter(MetaRewriter rewriter) {
metaRewriters.add(rewriter);
}
protected List<Metadata> handleMeta(UserConnection userConnection, int entityId, List<Metadata> metaData) {
EntityTracker tracker = userConnection.get(EntityTracker.class);
EntityType type = tracker.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.isObject(), type.getEntityType(), nmd);
else
nmd = rewriter.handleMetadata(false, -1, nmd);
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;
// Handle Entity Name
Optional<Metadata> opMd = storage.get(getDisplayNameIndex());
if (opMd.isPresent()) {
Optional<EntityData> opEd = getEntityData(type);
if (opEd.isPresent()) {
Metadata data = opMd.get();
EntityData entData = opEd.get();
if (entData.getMobName() != null &&
(data.getValue() == null || ((String) data.getValue()).isEmpty()) &&
data.getMetaType().getTypeID() == getDisplayNameMetaType().getTypeID())
data.setValue(entData.getMobName());
}
}
return storage;
}
protected EntityTracker.ProtocolEntityTracker getEntityTracker(UserConnection user) {
return user.get(EntityTracker.class).get(getProtocol());
}
}
@@ -10,9 +10,12 @@
package nl.matsv.viabackwards.api.rewriters;
import lombok.Getter;
import nl.matsv.viabackwards.api.BackwardsProtocol;
public abstract class Rewriter<T extends BackwardsProtocol> {
@Getter
private T protocol;
/**
* Register everything
@@ -20,6 +23,7 @@ public abstract class Rewriter<T extends BackwardsProtocol> {
* @param protocol Protocol instance
*/
public void register(T protocol) {
this.protocol = protocol;
registerPackets(protocol);
registerRewrites();
}
@@ -1,51 +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.api.rewriters;
import nl.matsv.viabackwards.api.BackwardsProtocol;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public abstract class SoundIdRewriter<T extends BackwardsProtocol> extends Rewriter<T> {
private Map<Integer, Integer> soundRewriter = new ConcurrentHashMap<>();
private Map<Integer, Float> pitchRewriter = new ConcurrentHashMap<>();
protected void rewriteSound(int newId, int oldId) {
soundRewriter.put(newId, oldId);
}
protected void rewriteSound(int newId, int oldId, float newPitch) {
rewriteSound(newId, oldId);
pitchRewriter.put(newId, newPitch);
}
public int handleSounds(int soundId) {
int newSoundId = soundId;
if (soundRewriter.containsKey(soundId))
newSoundId = soundId = soundRewriter.get(soundId);
for (Integer i : soundRewriter.keySet()) {
if (soundId > i)
newSoundId--;
}
return newSoundId;
}
public boolean hasPitch(int soundId) {
return pitchRewriter.containsKey(soundId);
}
public float handlePitch(int soundId) {
if (pitchRewriter.containsKey(soundId))
return pitchRewriter.get(soundId);
return -1;
}
}
@@ -0,0 +1,75 @@
/*
* 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.rewriters;
import lombok.AllArgsConstructor;
import lombok.Data;
import nl.matsv.viabackwards.api.BackwardsProtocol;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public abstract class SoundRewriter<T extends BackwardsProtocol> extends Rewriter<T> {
private Map<Integer, SoundData> soundRewrites = new ConcurrentHashMap<>();
public SoundData added(int id, int replacement) {
return added(id, replacement, -1);
}
public SoundData added(int id, int replacement, float newPitch) {
SoundData data = new SoundData(replacement, true, newPitch, true);
soundRewrites.put(id, data);
return data;
}
public SoundData removed(int id) {
SoundData data = new SoundData(-1, false, -1, false);
soundRewrites.put(id, data);
return data;
}
public int handleSounds(int soundId) {
int newSoundId = soundId;
if (soundRewrites.containsKey(soundId))
return soundRewrites.get(soundId).getReplacementSound();
for (Map.Entry<Integer, SoundData> entry : soundRewrites.entrySet()) {
if (soundId > entry.getKey()) {
if (entry.getValue().isAdded()) {
newSoundId--;
} else {
newSoundId++;
}
}
}
return newSoundId;
}
public boolean hasPitch(int soundId) {
if (soundRewrites.containsKey(soundId))
return soundRewrites.get(soundId).isChangePitch();
return false;
}
public float handlePitch(int soundId) {
if (soundRewrites.containsKey(soundId))
return soundRewrites.get(soundId).getNewPitch();
return 1f;
}
@Data
@AllArgsConstructor
public class SoundData {
private int replacementSound;
private boolean changePitch = false;
private float newPitch = 1f;
private boolean added;
}
}
@@ -0,0 +1,144 @@
/*
* 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_10to1_11;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import us.myles.ViaVersion.api.minecraft.item.Item;
import us.myles.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import us.myles.viaversion.libs.opennbt.tag.builtin.StringTag;
/*
Copied from ViaVersion //TODO implement in EntityTypes?
*/
public class EntityTypeNames {
private static BiMap<String, String> newToOldNames = HashBiMap.create();
static {
add("AreaEffectCloud", "minecraft:area_effect_cloud");
add("ArmorStand", "minecraft:armor_stand");
add("Arrow", "minecraft:arrow");
add("Bat", "minecraft:bat");
add("Blaze", "minecraft:blaze");
add("Boat", "minecraft:boat");
add("CaveSpider", "minecraft:cave_spider");
add("Chicken", "minecraft:chicken");
add("Cow", "minecraft:cow");
add("Creeper", "minecraft:creeper");
add("Donkey", "minecraft:donkey");
add("DragonFireball", "minecraft:dragon_fireball");
add("ElderGuardian", "minecraft:elder_guardian");
add("EnderCrystal", "minecraft:ender_crystal");
add("EnderDragon", "minecraft:ender_dragon");
add("Enderman", "minecraft:enderman");
add("Endermite", "minecraft:endermite");
add("EntityHorse", "minecraft:horse");
add("EyeOfEnderSignal", "minecraft:eye_of_ender_signal");
add("FallingSand", "minecraft:falling_block");
add("Fireball", "minecraft:fireball");
add("FireworksRocketEntity", "minecraft:fireworks_rocket");
add("Ghast", "minecraft:ghast");
add("Giant", "minecraft:giant");
add("Guardian", "minecraft:guardian");
add("Husk", "minecraft:husk");
add("Item", "minecraft:item");
add("ItemFrame", "minecraft:item_frame");
add("LavaSlime", "minecraft:magma_cube");
add("LeashKnot", "minecraft:leash_knot");
add("MinecartChest", "minecraft:chest_minecart");
add("MinecartCommandBlock", "minecraft:commandblock_minecart");
add("MinecartFurnace", "minecraft:furnace_minecart");
add("MinecartHopper", "minecraft:hopper_minecart");
add("MinecartRideable", "minecraft:minecart");
add("MinecartSpawner", "minecraft:spawner_minecart");
add("MinecartTNT", "minecraft:tnt_minecart");
add("Mule", "minecraft:mule");
add("MushroomCow", "minecraft:mooshroom");
add("Ozelot", "minecraft:ocelot");
add("Painting", "minecraft:painting");
add("Pig", "minecraft:pig");
add("PigZombie", "minecraft:zombie_pigman");
add("PolarBear", "minecraft:polar_bear");
add("PrimedTnt", "minecraft:tnt");
add("Rabbit", "minecraft:rabbit");
add("Sheep", "minecraft:sheep");
add("Shulker", "minecraft:shulker");
add("ShulkerBullet", "minecraft:shulker_bullet");
add("Silverfish", "minecraft:silverfish");
add("Skeleton", "minecraft:skeleton");
add("SkeletonHorse", "minecraft:skeleton_horse");
add("Slime", "minecraft:slime");
add("SmallFireball", "minecraft:small_fireball");
add("Snowball", "minecraft:snowball");
add("SnowMan", "minecraft:snowman");
add("SpectralArrow", "minecraft:spectral_arrow");
add("Spider", "minecraft:spider");
add("Squid", "minecraft:squid");
add("Stray", "minecraft:stray");
add("ThrownEgg", "minecraft:egg");
add("ThrownEnderpearl", "minecraft:ender_pearl");
add("ThrownExpBottle", "minecraft:xp_bottle");
add("ThrownPotion", "minecraft:potion");
add("Villager", "minecraft:villager");
add("VillagerGolem", "minecraft:villager_golem");
add("Witch", "minecraft:witch");
add("WitherBoss", "minecraft:wither");
add("WitherSkeleton", "minecraft:wither_skeleton");
add("WitherSkull", "minecraft:wither_skull");
add("Wolf", "minecraft:wolf");
add("XPOrb", "minecraft:xp_orb");
add("Zombie", "minecraft:zombie");
add("ZombieHorse", "minecraft:zombie_horse");
add("ZombieVillager", "minecraft:zombie_villager");
}
// Other way around (-:
private static void add(String oldName, String newName) {
newToOldNames.put(newName, oldName);
}
public static void toClient(CompoundTag tag) {
if (tag.get("id") instanceof StringTag) {
StringTag id = tag.get("id");
if (newToOldNames.containsKey(id.getValue())) {
id.setValue(newToOldNames.get(id.getValue()));
}
}
}
public static void toClientSpawner(CompoundTag tag) {
if (tag != null && tag.contains("SpawnData")) {
CompoundTag spawnData = tag.get("SpawnData");
if (spawnData != null && spawnData.contains("id"))
toClient(spawnData);
}
}
public static void toClientItem(Item item) {
if (hasEntityTag(item)) {
CompoundTag entityTag = item.getTag().get("EntityTag");
toClient(entityTag);
}
}
private static boolean hasEntityTag(Item item) {
if (item != null && item.getId() == 383) { // Monster Egg
CompoundTag tag = item.getTag();
if (tag != null && tag.contains("EntityTag") && tag.get("EntityTag") instanceof CompoundTag) {
if (((CompoundTag) tag.get("EntityTag")).get("id") instanceof StringTag) {
return true;
}
}
}
return false;
}
}
@@ -0,0 +1,54 @@
/*
* 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_10to1_11;
import lombok.Getter;
import nl.matsv.viabackwards.api.BackwardsProtocol;
import nl.matsv.viabackwards.api.entities.storage.EntityTracker;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.packets.BlockItemPackets1_11;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.packets.EntityPackets1_11;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.packets.PlayerPackets1_11;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.packets.SoundPackets1_11;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.storage.WindowTracker;
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 EntityPackets1_11 entityPackets; // Required for the item rewriter
@Getter
private BlockItemPackets1_11 blockItemPackets;
@Override
protected void registerPackets() {
(entityPackets = new EntityPackets1_11()).register(this);
new PlayerPackets1_11().register(this);
(blockItemPackets = new BlockItemPackets1_11()).register(this);
new SoundPackets1_11().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));
if (!user.has(WindowTracker.class))
user.put(new WindowTracker(user));
// Init protocol in EntityTracker
user.get(EntityTracker.class).initProtocol(this);
}
}
@@ -0,0 +1,489 @@
/*
* 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_10to1_11.packets;
import net.md_5.bungee.api.ChatColor;
import nl.matsv.viabackwards.api.entities.storage.EntityTracker;
import nl.matsv.viabackwards.api.entities.types.EntityType1_11;
import nl.matsv.viabackwards.api.rewriters.BlockItemRewriter;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.EntityTypeNames;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.Protocol1_10To1_11;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.storage.ChestedHorseStorage;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.storage.WindowTracker;
import nl.matsv.viabackwards.protocol.protocol1_12to1_11_1.data.BlockColors;
import nl.matsv.viabackwards.utils.Block;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.data.UserConnection;
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.types.Chunk1_9_3_4Type;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import us.myles.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import us.myles.viaversion.libs.opennbt.tag.builtin.StringTag;
import java.util.Arrays;
import java.util.Optional;
public class BlockItemPackets1_11 extends BlockItemRewriter<Protocol1_10To1_11> {
@Override
protected void registerPackets(Protocol1_10To1_11 protocol) {
/* Item packets */
// 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));
}
});
// Handle Llama
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
if (isLlama(wrapper.user())) {
Optional<ChestedHorseStorage> horse = getChestedHorse(wrapper.user());
if (!horse.isPresent())
return;
ChestedHorseStorage storage = horse.get();
int currentSlot = wrapper.get(Type.SHORT, 0);
wrapper.set(Type.SHORT, 0, ((Integer) (currentSlot = getNewSlotId(storage, currentSlot))).shortValue());
wrapper.set(Type.ITEM, 0, getNewItem(storage, currentSlot, wrapper.get(Type.ITEM, 0)));
}
}
});
}
});
// 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]);
if (isLlama(wrapper.user())) {
Optional<ChestedHorseStorage> horse = getChestedHorse(wrapper.user());
if (!horse.isPresent())
return;
ChestedHorseStorage storage = horse.get();
stacks = Arrays.copyOf(stacks, !storage.isChested() ? 38 : 53);
for (int i = stacks.length - 1; i >= 0; i--) {
stacks[getNewSlotId(storage, i)] = stacks[i];
stacks[i] = getNewItem(storage, i, stacks[i]);
}
wrapper.set(Type.ITEM_ARRAY, 0, stacks);
}
}
});
}
});
// 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);
}
});
// Llama slot
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
if (isLlama(wrapper.user())) {
Optional<ChestedHorseStorage> horse = getChestedHorse(wrapper.user());
if (!horse.isPresent())
return;
ChestedHorseStorage storage = horse.get();
int clickSlot = wrapper.get(Type.SHORT, 0);
int correctSlot = getOldSlotId(storage, clickSlot);
wrapper.set(Type.SHORT, 0, ((Integer) correctSlot).shortValue());
}
}
});
}
}
);
// 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);
}
});
}
}
);
/* Block packets */
// Chunk packet
protocol.registerOutgoing(State.PLAY, 0x20, 0x20, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
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);
handleChunk(chunk);
// only patch it for signs for now, TODO-> Find all the block entities old/new to replace ids and implement in ViaVersion
chunk.getBlockEntities().stream()
.filter(tag -> tag.contains("id") && tag.get("id") instanceof StringTag)
.forEach(tag -> {
String id = (String) tag.get("id").getValue();
if (id.equals("minecraft:sign")) {
((StringTag) tag.get("id")).setValue("Sign");
}
});
}
});
}
}
);
// Block Change Packet
protocol.registerOutgoing(State.PLAY, 0x0B, 0x0B, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION); // 0 - Block Position
map(Type.VAR_INT); // 1 - Block
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int idx = wrapper.get(Type.VAR_INT, 0);
wrapper.set(Type.VAR_INT, 0, handleBlockID(idx));
}
});
}
}
);
// Multi Block Change Packet
protocol.registerOutgoing(State.PLAY, 0x10, 0x10, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // 0 - Chunk X
map(Type.INT); // 1 - Chunk Z
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int count = wrapper.passthrough(Type.VAR_INT); // Array length
for (int i = 0; i < count; i++) {
wrapper.passthrough(Type.UNSIGNED_BYTE); // Horizontal position
wrapper.passthrough(Type.UNSIGNED_BYTE); // Y coords
int id = wrapper.read(Type.VAR_INT); // Block ID
wrapper.write(Type.VAR_INT, handleBlockID(id));
}
}
});
}
}
);
// Update Block Entity
protocol.registerOutgoing(State.PLAY, 0x09, 0x09, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION); // 0 - Position
map(Type.UNSIGNED_BYTE); // 1 - Action
map(Type.NBT); // 2 - NBT
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
// Remove on shulkerbox decleration
if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 10) {
wrapper.cancel();
}
// Handler Spawners
if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 1) {
CompoundTag tag = wrapper.get(Type.NBT, 0);
EntityTypeNames.toClientSpawner(tag);
}
}
});
}
});
// Open window packet
protocol.registerOutgoing(State.PLAY, 0x13, 0x13, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.STRING); // 1 - Window Type
map(Type.STRING); // 2 - Title
map(Type.UNSIGNED_BYTE); // 3 - Slots
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int entityId = -1;
// Passthrough Entity ID
if (wrapper.get(Type.STRING, 0).equals("EntityHorse"))
entityId = wrapper.passthrough(Type.INT);
// Track Inventory
String inventory = wrapper.get(Type.STRING, 0);
WindowTracker windowTracker = wrapper.user().get(WindowTracker.class);
windowTracker.setInventory(inventory);
windowTracker.setEntityId(entityId);
// Change llama slotcount to the donkey one
if (isLlama(wrapper.user()))
wrapper.set(Type.UNSIGNED_BYTE, 1, (short) 17);
}
});
}
});
// Close Window Packet
protocol.registerOutgoing(State.PLAY, 0x12, 0x12, new PacketRemapper() {
@Override
public void registerMap() {
// Inventory tracking
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
WindowTracker windowTracker = wrapper.user().get(WindowTracker.class);
windowTracker.setInventory(null);
windowTracker.setEntityId(-1);
}
});
}
});
// Close Window Incoming Packet
protocol.registerIncoming(State.PLAY, 0x08, 0x08, new PacketRemapper() {
@Override
public void registerMap() {
// Inventory tracking
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
WindowTracker windowTracker = wrapper.user().get(WindowTracker.class);
windowTracker.setInventory(null);
windowTracker.setEntityId(-1);
}
});
}
});
protocol.getEntityPackets().registerMetaHandler().handle(e -> {
Metadata data = e.getData();
if (data.getMetaType().equals(MetaType1_9.Slot)) // Is Item
data.setValue(handleItemToClient((Item) data.getValue()));
return data;
});
}
@Override
protected void registerRewrites() {
// ShulkerBoxes to EnderChest
for (int i = 219; i < 235; i++)
rewrite(i)
.repItem(new Item((short) 130, (byte) 1, (short) 0, getNamedTag("1.11 " + BlockColors.get(i - 219) + " Shulker Box")))
.repBlock(new Block(130, 4)) // TODO investigate this
.blockEntityHandler((block, tag) -> {
tag.remove("id");
tag.put(new StringTag("id", "minecraft:chest"));
return tag;
});
// Observer to Dispenser
rewrite(218).repItem(new Item((short) 23, (byte) 1, (short) 0, getNamedTag("1.11 Observer"))).repBlock(new Block(23, -1));
// Handle spawner block entity
rewrite(52).blockEntityHandler((b, tag) -> {
EntityTypeNames.toClientSpawner(tag);
return tag;
});
// Rewrite spawn eggs
rewrite(383).itemHandler((i) -> {
EntityTypeNames.toClientItem(i);
return i;
});
// Totem of Undying to Dead Bush
rewrite(449).repItem(new Item((short) 32, (byte) 1, (short) 0, getNamedTag("1.11 Totem of Undying")));
// Shulker shell to Popped Chorus Fruit
rewrite(450).repItem(new Item((short) 433, (byte) 1, (short) 0, getNamedTag("1.11 Shulker Shell")));
}
private boolean isLlama(UserConnection user) {
WindowTracker tracker = user.get(WindowTracker.class);
if (tracker.getInventory() != null && tracker.getInventory().equals("EntityHorse")) {
EntityTracker.ProtocolEntityTracker entTracker = user.get(EntityTracker.class).get(getProtocol());
Optional<EntityTracker.StoredEntity> optEntity = entTracker.getEntity(tracker.getEntityId());
if (optEntity.isPresent() && optEntity.get().getType().is(EntityType1_11.EntityType.LIAMA))
return true;
}
return false;
}
private Optional<ChestedHorseStorage> getChestedHorse(UserConnection user) {
WindowTracker tracker = user.get(WindowTracker.class);
if (tracker.getInventory() != null && tracker.getInventory().equals("EntityHorse")) {
EntityTracker.ProtocolEntityTracker entTracker = user.get(EntityTracker.class).get(getProtocol());
Optional<EntityTracker.StoredEntity> optEntity = entTracker.getEntity(tracker.getEntityId());
if (optEntity.isPresent())
return Optional.of(optEntity.get().get(ChestedHorseStorage.class));
}
return Optional.empty();
}
// TODO improve the llama inventory part
private int getNewSlotId(ChestedHorseStorage storage, int slotId) {
int totalSlots = !storage.isChested() ? 38 : 53;
int strength = storage.isChested() ? storage.getLiamaStrength() : 0;
int startNonExistingFormula = 2 + 3 * strength;
int offsetForm = 15 - (3 * strength);
if (slotId >= startNonExistingFormula && totalSlots > (slotId + offsetForm))
return offsetForm + slotId;
if (slotId == 1)
return 0;
return slotId;
}
private int getOldSlotId(ChestedHorseStorage storage, int slotId) {
int strength = storage.isChested() ? storage.getLiamaStrength() : 0;
int startNonExistingFormula = 2 + 3 * strength;
int endNonExistingFormula = 2 + 3 * (storage.isChested() ? 5 : 0);
int offsetForm = endNonExistingFormula - startNonExistingFormula;
if (slotId == 1 || slotId >= startNonExistingFormula && slotId < endNonExistingFormula)
return 0;
if (slotId >= endNonExistingFormula)
return slotId - offsetForm;
if (slotId == 0)
return 1;
return slotId;
}
private Item getNewItem(ChestedHorseStorage storage, int slotId, Item current) {
int strength = storage.isChested() ? storage.getLiamaStrength() : 0;
int startNonExistingFormula = 2 + 3 * strength;
int endNonExistingFormula = 2 + 3 * (storage.isChested() ? 5 : 0);
if (slotId >= startNonExistingFormula && slotId < endNonExistingFormula)
return new Item((short) 166, (byte) 1, (short) 0, getNamedTag(ChatColor.RED + "SLOT DISABLED"));
if (slotId == 1)
return null;
return current;
}
}
@@ -0,0 +1,599 @@
/*
* 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_10to1_11.packets;
import nl.matsv.viabackwards.ViaBackwards;
import nl.matsv.viabackwards.api.entities.storage.EntityData;
import nl.matsv.viabackwards.api.entities.storage.MetaStorage;
import nl.matsv.viabackwards.api.entities.types.AbstractEntityType;
import nl.matsv.viabackwards.api.entities.types.EntityType1_12;
import nl.matsv.viabackwards.api.exceptions.RemovedValueException;
import nl.matsv.viabackwards.api.rewriters.EntityRewriter;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.Protocol1_10To1_11;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.storage.ChestedHorseStorage;
import nl.matsv.viabackwards.utils.Block;
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;
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.types.EntityType1_11.*;
public class EntityPackets1_11 extends EntityRewriter<Protocol1_10To1_11> {
@Override
protected void registerPackets(Protocol1_10To1_11 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));
}
}
}
});
// Handle FallingBlock blocks
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Optional<EntityType1_12.ObjectType> type = EntityType1_12.ObjectType.findById(wrapper.get(Type.BYTE, 0));
if (type.isPresent() && type.get().equals(EntityType1_12.ObjectType.FALLING_BLOCK)) {
int objectData = wrapper.get(Type.INT, 0);
int objType = objectData & 4095;
int data = objectData >> 12 & 15;
Block block = getProtocol().getBlockItemPackets().handleBlock(objType, data);
if (block == null)
return;
wrapper.set(Type.INT, 0, block.getId() | block.getData() << 12);
}
}
});
}
});
// 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, Type.UNSIGNED_BYTE); // 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.UNSIGNED_BYTE, 0), 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()
);
}
});
}
});
// Entity Status
protocol.registerOutgoing(State.PLAY, 0x1B, 0x1B, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // 0 - Entity ID
map(Type.BYTE); // 1 - Entity Status
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
byte b = wrapper.get(Type.BYTE, 0);
if (b == 35) {
wrapper.clearPacket();
wrapper.setId(0x1E); // Change Game State
wrapper.write(Type.UNSIGNED_BYTE, (short) 10); // Play Elder Guardian animation
wrapper.write(Type.FLOAT, 0F);
}
}
});
}
});
}
@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).mobName("Evoker");
regEntType(EntityType.VEX, EntityType.BAT).mobName("Vex");
regEntType(EntityType.VINDICATION_ILLAGER, EntityType.VILLAGER).mobName("Vindicator").spawnMetadata(storage -> storage.add(new Metadata(13, MetaType1_9.VarInt, 4))); // Base Profession
regEntType(EntityType.LIAMA, EntityType.HORSE).mobName("Llama").spawnMetadata(storage -> storage.add(getHorseMetaType(1)));
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.getEntity().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).handleIndexChange(13);
/*
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((int) data.getValue() == 1 ? 2 : 4);
return data;
});
/*
HORSES
*/
// Handle horse flags
registerMetaHandler().filter(EntityType.ABSTRACT_HORSE, true, 13).handle(e -> {
Metadata data = e.getData();
byte b = (byte) data.getValue();
if (e.getEntity().has(ChestedHorseStorage.class) &&
e.getEntity().get(ChestedHorseStorage.class).isChested()) {
b |= 0x08; // Chested
data.setValue(b);
}
return data;
});
// Create chested horse storage TODO create on mob spawn?
registerMetaHandler().filter(EntityType.CHESTED_HORSE, true).handle(e -> {
if (!e.getEntity().has(ChestedHorseStorage.class))
e.getEntity().put(new ChestedHorseStorage());
return e.getData();
});
// Handle Horse (Correct owner)
registerMetaHandler().filter(EntityType.ABSTRACT_HORSE, true, 14).handleIndexChange(16);
// Handle horse armor
registerMetaHandler().filter(EntityType.HORSE, 16).handleIndexChange(17);
// Handle chested horse
registerMetaHandler().filter(EntityType.CHESTED_HORSE, true, 15).handle(e -> {
ChestedHorseStorage storage = e.getEntity().get(ChestedHorseStorage.class);
boolean b = (boolean) e.getData().getValue();
storage.setChested(b);
throw new RemovedValueException();
});
// Get rid of Liama metadata
registerMetaHandler().filter(EntityType.LIAMA).handle(e -> {
Metadata data = e.getData();
ChestedHorseStorage storage = e.getEntity().get(ChestedHorseStorage.class);
int index = e.getIndex();
// Store them for later (:
switch (index) {
case 16:
storage.setLiamaStrength((int) data.getValue());
throw new RemovedValueException();
case 17:
storage.setLiamaCarpetColor((int) data.getValue());
throw new RemovedValueException();
case 18:
storage.setLiamaVariant((int) data.getValue());
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).removed();
}
/*
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);
}
}
@@ -0,0 +1,98 @@
/*
* 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_10to1_11.packets;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.Protocol1_10To1_11;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.remapper.PacketHandler;
import us.myles.ViaVersion.api.remapper.PacketRemapper;
import us.myles.ViaVersion.api.remapper.ValueTransformer;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.protocols.protocol1_11to1_10.Protocol1_11To1_10;
public class PlayerPackets1_11 {
private static final ValueTransformer<Short, Float> toNewFloat = new ValueTransformer<Short, Float>(Type.FLOAT) {
@Override
public Float transform(PacketWrapper wrapper, Short inputValue) throws Exception {
return (float) (inputValue / 16);
}
};
public void register(Protocol1_10To1_11 protocol) {
/* Outgoing packets */
// Title packet
protocol.registerOutgoing(State.PLAY, 0x45, 0x45, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Action
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int action = wrapper.get(Type.VAR_INT, 0);
// Handle the new ActionBar
if (action == 2) {
// Convert to the old actionbar way
PacketWrapper actionbar = new PacketWrapper(0x0F, null, wrapper.user()); // Chat Message packet
actionbar.write(Type.STRING, wrapper.read(Type.STRING));
actionbar.write(Type.BYTE, (byte) 2); // Above hotbar
actionbar.send(Protocol1_11To1_10.class);
wrapper.cancel(); // Cancel the title packet
return;
}
if (action > 2)
wrapper.set(Type.VAR_INT, 0, action - 1); // Move everything one position down
}
});
}
});
// Collect item packet
protocol.registerOutgoing(State.PLAY, 0x48, 0x48, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Collected entity id
map(Type.VAR_INT); // 1 - Collector entity id
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper packetWrapper) throws Exception {
packetWrapper.read(Type.VAR_INT); // Ignore pickup item count
}
});
}
});
/* Incoming packets */
// Block placement packet
protocol.registerIncoming(State.PLAY, 0x1C, 0x1C, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION); // 0 - Location
map(Type.VAR_INT); // 1 - Face
map(Type.VAR_INT); // 2 - Hand
map(Type.UNSIGNED_BYTE, toNewFloat);
map(Type.UNSIGNED_BYTE, toNewFloat);
map(Type.UNSIGNED_BYTE, toNewFloat);
}
});
}
}
@@ -0,0 +1,112 @@
/*
* 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_10to1_11.packets;
import nl.matsv.viabackwards.api.rewriters.SoundRewriter;
import nl.matsv.viabackwards.protocol.protocol1_10to1_11.Protocol1_10To1_11;
import us.myles.ViaVersion.api.PacketWrapper;
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 SoundPackets1_11 extends SoundRewriter<Protocol1_10To1_11> {
@Override
protected void registerPackets(Protocol1_10To1_11 protocol) {
// Named sound effect
protocol.registerOutgoing(State.PLAY, 0x19, 0x19, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING); // 0 - Sound name
map(Type.VAR_INT); // 1 - Sound Category
map(Type.INT); // 2 - x
map(Type.INT); // 3 - y
map(Type.INT); // 4 - z
map(Type.FLOAT); // 5 - Volume
map(Type.FLOAT); // 6 - Pitch
}
});
// Sound effect
protocol.registerOutgoing(State.PLAY, 0x46, 0x46, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Sound name
map(Type.VAR_INT); // 1 - Sound Category
map(Type.INT); // 2 - x
map(Type.INT); // 3 - y
map(Type.INT); // 4 - z
map(Type.FLOAT); // 5 - Volume
map(Type.FLOAT); // 6 - Pitch
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int oldId = wrapper.get(Type.VAR_INT, 0);
int newId = handleSounds(oldId);
if (newId == -1)
wrapper.cancel();
else {
if (hasPitch(oldId))
wrapper.set(Type.FLOAT, 1, handlePitch(oldId));
wrapper.set(Type.VAR_INT, 0, newId);
}
}
});
}
});
}
@Override
protected void registerRewrites() {
// Sound replacements, suggestions are always welcome
// Automatically generated from PAaaS
added(85, 121, 0.5f); // block.shulker_box.close -> block.wooden_trapdoor.close
added(86, 122, 0.5f); // block.shulker_box.open -> block.wooden_trapdoor.open
added(176, 227); // entity.elder_guardian.flop -> entity.guardian.flop
removed(196); // entity.experience_orb.touch
added(197, 402, 1.8f); // entity.evocation_fangs.attack -> entity.zombie.attack_iron_door
added(198, 370, 0.4f); // entity.evocation_illager.ambient -> entity.villager.ambient
added(199, 255, 1.3f); // entity.evocation_illager.cast_spell -> entity.irongolem.hurt
added(200, 418, 1.3f); // entity.evocation_illager.death -> entity.zombie_villager.death
added(201, 372, 1.3f); // entity.evocation_illager.hurt -> entity.villager.hurt
added(202, 137, 0.8f); // entity.evocation_illager.prepare_attack -> entity.elder_guardian.curse
added(203, 78, 2f); // entity.evocation_illager.prepare_summon -> block.portal.trigger
added(204, 376, 0.6f); // entity.evocation_illager.prepare_wololo -> entity.witch.ambient
added(279, 230, 1.5f); // entity.llama.ambient -> entity.horse.ambient
added(280, 231, 1.6f); // entity.llama.angry -> entity.horse.angry
added(281, 164); // entity.llama.chest -> entity.donkey.chest
added(282, 165, 1.2f); // entity.llama.death -> entity.donkey.death
added(283, 235, 1.1f); // entity.llama.eat -> entity.horse.eat
added(284, 166); // entity.llama.hurt -> entity.donkey.hurt
added(285, 323, 1.7f); // entity.llama.spit -> entity.shulker.shoot
added(286, 241, 0.8f); // entity.llama.step -> entity.horse.step
added(287, 423, 0.5f); // entity.llama.swag -> item.armor.equip_generic
added(296, 164); // entity.mule.chest -> entity.donkey.chest
added(390, 233, 0.1f); // entity.vex.ambient -> entity.horse.breathe
added(391, 168, 2f); // entity.vex.charge -> entity.elder_guardian.ambient
added(392, 144, 0.5f); // entity.vex.death -> entity.cat.death
added(393, 146, 2f); // entity.vex.hurt -> entity.cat.hurt
added(400, 370, 0.7f); // entity.vindication_illager.ambient -> entity.villager.ambient
added(401, 371, 0.8f); // entity.vindication_illager.death -> entity.villager.death
added(402, 372, 0.7f); // entity.vindication_illager.hurt -> entity.villager.hurt
added(450, 423, 1.1f); // item.armor.equip_elytra -> item.armor.equip_generic
added(455, 427, 1.1f); // item.bottle.empty -> item.bottle.fill
added(470, 2, 0.5f); // item.totem.use -> block.anvil.destroy
}
}
@@ -0,0 +1,27 @@
/*
* 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_10to1_11.storage;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import nl.matsv.viabackwards.api.entities.storage.EntityStorage;
@Getter
@Setter
@ToString
public class ChestedHorseStorage extends EntityStorage {
private boolean chested = false;
private int liamaStrength = 0;
private int liamaCarpetColor = -1;
private int liamaVariant = 0;
}
@@ -8,36 +8,23 @@
* 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;
package nl.matsv.viabackwards.protocol.protocol1_10to1_11.storage;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import us.myles.ViaVersion.api.data.StoredObject;
import us.myles.ViaVersion.api.data.UserConnection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Getter
@ToString
@Setter
public class WindowTracker extends StoredObject {
private String inventory;
private int entityId = -1;
public class EntityTracker extends StoredObject {
private Map<Integer, EntityType> entityMap = new ConcurrentHashMap<>();
public EntityTracker(UserConnection user) {
public WindowTracker(UserConnection user) {
super(user);
}
public void trackEntityType(int id, EntityType type) {
if (entityMap.containsKey(id))
return;
entityMap.put(id, type);
}
public void removeEntity(int id) {
entityMap.remove(id);
}
public EntityType getEntityType(int id) {
return entityMap.get(id);
}
public boolean containsEntity(int id) {
return entityMap.containsKey(id);
}
}
@@ -0,0 +1,44 @@
/*
* 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 lombok.Getter;
import nl.matsv.viabackwards.api.BackwardsProtocol;
import nl.matsv.viabackwards.api.entities.storage.EntityTracker;
import nl.matsv.viabackwards.protocol.protocol1_11to1_11_1.packets.EntityPackets1_11_1;
import nl.matsv.viabackwards.protocol.protocol1_11to1_11_1.packets.ItemPackets1_11_1;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
@Getter
public class Protocol1_11To1_11_1 extends BackwardsProtocol {
private EntityPackets1_11_1 entityPackets;
@Override
protected void registerPackets() {
(entityPackets = new EntityPackets1_11_1()).register(this);
new ItemPackets1_11_1().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);
}
}
@@ -8,14 +8,16 @@
* 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.packets;
package nl.matsv.viabackwards.protocol.protocol1_11to1_11_1.packets;
import nl.matsv.viabackwards.api.exceptions.RemovedValueException;
import nl.matsv.viabackwards.ViaBackwards;
import nl.matsv.viabackwards.api.entities.storage.EntityData;
import nl.matsv.viabackwards.api.entities.storage.MetaStorage;
import nl.matsv.viabackwards.api.entities.types.AbstractEntityType;
import nl.matsv.viabackwards.api.rewriters.EntityRewriter;
import nl.matsv.viabackwards.api.storage.EntityTracker;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.Protocol1_9_4To1_10;
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.metadata.types.MetaType1_9;
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;
@@ -23,11 +25,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;
public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
import java.util.Optional;
import static nl.matsv.viabackwards.api.entities.types.EntityType1_11.*;
public class EntityPackets1_11_1 extends EntityRewriter<Protocol1_11To1_11_1> {
@Override
protected void registerPackets(Protocol1_9_4To1_10 protocol) {
protected void registerPackets(Protocol1_11To1_11_1 protocol) {
// Spawn Object
protocol.registerOutgoing(State.PLAY, 0x00, 0x00, new PacketRemapper() {
@Override
@@ -35,6 +40,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() {
@@ -43,11 +54,31 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
addTrackedEntity(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
true,
wrapper.get(Type.BYTE, 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));
}
}
}
});
}
});
@@ -64,8 +95,7 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
addTrackedEntity(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
true,
(short) 2
ObjectType.THROWN_EXP_BOTTLE.getType()
);
}
});
@@ -86,8 +116,7 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
addTrackedEntity(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
true,
wrapper.get(Type.BYTE, 0)
EntityType.WEATHER // Always thunder according to wiki.vg
);
}
});
@@ -100,7 +129,7 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity id
map(Type.UUID); // 1 - UUID
map(Type.UNSIGNED_BYTE); // 2 - Entity Type
map(Type.VAR_INT); // 2 - Entity Type
map(Type.DOUBLE); // 3 - X
map(Type.DOUBLE); // 4 - Y
map(Type.DOUBLE); // 5 - Z
@@ -119,38 +148,39 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
addTrackedEntity(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
false,
wrapper.get(Type.UNSIGNED_BYTE, 0)
getTypeFromId(wrapper.get(Type.VAR_INT, 1), false)
);
}
});
// Rewrite entity ids
// Rewrite entity type / metadata
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.set(Type.UNSIGNED_BYTE, 0,
getNewEntityType(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0)
));
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.VAR_INT, 1, data.getReplacementId());
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()
);
}
});
@@ -170,8 +200,7 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
addTrackedEntity(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
true,
(short) 9
EntityType.PAINTING
);
}
});
@@ -192,8 +221,7 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
addTrackedEntity(
wrapper.user(),
wrapper.get(Type.INT, 0),
false,
(short) -12
EntityType.PLAYER
);
}
});
@@ -245,8 +273,7 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
addTrackedEntity(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
false,
(short) -12
EntityType.PLAYER
);
}
});
@@ -261,8 +288,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()
);
}
});
@@ -279,7 +306,7 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
for (int entity : wrapper.get(Type.VAR_INT_ARRAY, 0))
wrapper.user().get(EntityTracker.class).removeEntity(entity);
getEntityTracker(wrapper.user()).removeEntity(entity);
}
});
}
@@ -301,8 +328,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()
);
}
});
@@ -312,50 +339,10 @@ public class EntityPackets extends EntityRewriter<Protocol1_9_4To1_10> {
@Override
protected void registerRewrites() {
rewriteEntityId(102, 91); // Replace polar bear with sheep
// Handle non-existing firework metadata (index 7 entity id for boosting)
registerMetaHandler().filter(EntityType.FIREWORK, 7).removed();
// Handle Polar bear
registerMetaRewriter((isObject, entityType, data) -> { // Change the sheep color when the polar bear is stending up
if (!isObject && entityType != 102)
return data;
if (data.getId() == 13) { // is boolean
boolean b = (boolean) data.getValue();
data.setId(13);
data.setMetaType(MetaType1_9.Byte);
data.setValue(b ? (byte) (14 & 0x0F) : 0);
}
return data;
});
// Handle Husk
registerMetaRewriter((isObject, entityType, data) -> { // Change husk to normal zombie
if (isObject || entityType != 54)
return data;
if (data.getId() == 13 && data.getMetaType().getTypeID() == 1 && (int) data.getValue() == 6)
data.setValue(0);
return data;
});
// Handle stray
registerMetaRewriter((isObject, entityType, data) -> { // Change stray- to normal skeleton
if (isObject || entityType != 51)
return data;
if (data.getId() == 12 && data.getMetaType().getTypeID() == 1 && (int) data.getValue() == 2)
data.setValue(0);
return data;
});
// Handle the missing NoGravity tag
registerMetaRewriter((isObject, entityType, m) -> {
if (m.getId() == 5)
throw new RemovedValueException();
else if (m.getId() >= 5)
m.setId(m.getId() - 1);
return m;
});
// Handle non-existing pig metadata (index 14 - boost time)
registerMetaHandler().filter(EntityType.PIG, 14).removed();
}
}
@@ -0,0 +1,168 @@
/*
* 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.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;
public class ItemPackets1_11_1 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);
}
});
}
}
);
// Handle item metadata
protocol.getEntityPackets().registerMetaHandler().handle(e -> {
Metadata data = e.getData();
if (data.getMetaType().equals(MetaType1_9.Slot)) // Is Item
data.setValue(handleItemToClient((Item) data.getValue()));
return data;
});
}
@Override
protected void registerRewrites() {
rewrite(452).repItem(new Item((short) 265, (byte) 1, (short) 0, getNamedTag("1.11.2 Iron Nugget")));
}
}
@@ -0,0 +1,51 @@
/*
* 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_12to1_11_1;
import lombok.Getter;
import nl.matsv.viabackwards.api.BackwardsProtocol;
import nl.matsv.viabackwards.api.entities.storage.EntityTracker;
import nl.matsv.viabackwards.protocol.protocol1_12to1_11_1.data.ShoulderTracker;
import nl.matsv.viabackwards.protocol.protocol1_12to1_11_1.packets.*;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
@Getter
public class Protocol1_11_1To1_12 extends BackwardsProtocol {
// TODO store all rewriters and make them easy accessible?
private EntityPackets1_12 entityPackets;
private BlockItemPackets1_12 blockItemPackets;
@Override
protected void registerPackets() {
new ChangedPacketIds1_12().register(this);
(entityPackets = new EntityPackets1_12()).register(this);
(blockItemPackets = new BlockItemPackets1_12()).register(this);
new SoundPackets1_12().register(this);
new ChatPackets1_12().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));
user.put(new ShoulderTracker(user));
// Init protocol in EntityTracker
user.get(EntityTracker.class).initProtocol(this);
}
}
@@ -0,0 +1,150 @@
/*
* 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_12to1_11_1.data;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class AdvancementTranslations {
private static final Map<String, String> advancements = new ConcurrentHashMap<>();
static {
add("advancements.nether.get_wither_skull.title", "Spooky Scary Skeleton");
add("advancements.husbandry.break_diamond_hoe.description", "Completely use up a diamond hoe, and then reevaluate your life choices");
add("advancements.nether.fast_travel.description", "Use the Nether to travel 7km in the Overworld");
add("advancements.story.enter_the_end.description", "Enter the End Portal");
add("advancements.story.follow_ender_eye.title", "Eye Spy");
add("advancements.toast.task", "Advancement Made!");
add("advancements.nether.find_fortress.description", "Break your way into a Nether Fortress");
add("advancements.story.form_obsidian.description", "Form and mine a block of Obsidian");
add("advancements.adventure.sniper_duel.description", "Kill a skeleton with an arrow from more than 50 meters");
add("advancements.end.root.description", "Or the beginning?");
add("advancements.adventure.kill_a_mob.title", "Monster Hunter");
add("advancements.end.elytra.description", "Find an Elytra");
add("advancements.end.dragon_breath.description", "Collect dragon's breath in a glass bottle");
add("advancements.story.enter_the_nether.title", "We Need to Go Deeper");
add("advancements.story.upgrade_tools.title", "Getting an Upgrade");
add("advancements.story.lava_bucket.title", "Hot Stuff");
add("advancements.story.shiny_gear.title", "Cover Me With Diamonds");
add("advancements.story.smelt_iron.description", "Smelt an iron ingot");
add("chat.type.advancement.goal", "%s has reached the goal %s");
add("advancements.husbandry.break_diamond_hoe.title", "Serious Dedication");
add("advancements.story.iron_tools.description", "Upgrade your pickaxe");
add("advancements.end.respawn_dragon.title", "The End... Again...");
add("advancements.husbandry.tame_an_animal.description", "Tame an animal");
add("advancements.end.levitate.description", "Levitate up 50 blocks from the attacks of a Shulker");
add("advancements.adventure.shoot_arrow.description", "Shoot something with a bow and arrow");
add("advancements.nether.root.description", "Bring summer clothes");
add("advancements.story.enchant_item.description", "Enchant an item at an Enchanting Table");
add("advancements.adventure.root.title", "Adventure");
add("advancements.adventure.trade.title", "What a Deal!");
add("advancements.husbandry.breed_all_animals.title", "Two by Two");
add("advancements.nether.find_fortress.title", "A Terrible Fortress");
add("advancements.nether.create_full_beacon.title", "Beaconator");
add("advancements.story.cure_zombie_villager.description", "Weaken and then cure a zombie villager");
add("advancements.toast.challenge", "Challenge Complete!");
add("advancements.nether.create_full_beacon.description", "Bring a beacon to full power");
add("advancements.story.follow_ender_eye.description", "Follow an Ender Eye");
add("advancements.end.find_end_city.title", "The City at the End of the Game");
add("chat.type.advancement.challenge", "%s has completed the challenge %s");
add("advancements.story.deflect_arrow.title", "Not Today, Thank You");
add("advancements.adventure.kill_all_mobs.description", "Kill one of every hostile monster");
add("advancements.story.smelt_iron.title", "Acquire Hardware");
add("advancements.end.levitate.title", "Great View From Up Here");
add("advancements.end.kill_dragon.title", "Free the End");
add("advancements.end.kill_dragon.description", "Good luck");
add("advancements.nether.brew_potion.title", "Local Brewery");
add("advancements.story.enchant_item.title", "Enchanter");
add("advancements.end.respawn_dragon.description", "Respawn the ender dragon");
add("advancements.nether.uneasy_alliance.title", "Uneasy Alliance");
add("advancements.nether.root.title", "Nether");
add("advancements.nether.brew_potion.description", "Brew a potion");
add("advancements.nether.obtain_blaze_rod.title", "Into Fire");
add("advancements.nether.summon_wither.title", "Withering Heights");
add("advancements.story.root.title", "Minecraft");
add("advancements.husbandry.balanced_diet.description", "Eat everything that is edible, even if it's not good for you");
add("advancements.nether.uneasy_alliance.description", "Rescue a Ghast from the Nether, bring it safely home to the Overworld... and then kill it.");
add("advancements.husbandry.breed_all_animals.description", "Breed all the animals!");
add("advancements.adventure.kill_all_mobs.title", "Monsters Hunted");
add("advancements.story.cure_zombie_villager.title", "Zombie Doctor");
add("advancements.husbandry.plant_seed.title", "A Seedy Place");
add("advancements.end.dragon_breath.title", "You Need a Mint");
add("advancements.story.mine_stone.title", "Stone Age");
add("advancements.end.find_end_city.description", "Go on in, what could happen?");
add("advancements.nether.create_beacon.description", "Construct and place a Beacon");
add("advancements.adventure.summon_iron_golem.title", "Hired Help");
add("advancements.end.elytra.title", "Sky's the Limit");
add("chat.type.advancement.task", "%s has made the advancement %s");
add("advancements.story.deflect_arrow.description", "Deflect an arrow with a shield");
add("advancements.nether.all_effects.description", "Have every effect applied at the same time");
add("advancements.story.enter_the_nether.description", "Build, light and enter a Nether Portal");
add("advancements.story.mine_diamond.title", "Diamonds!");
add("advancements.husbandry.balanced_diet.title", "A Balanced Diet");
add("advancements.husbandry.root.title", "Husbandry");
add("advancements.story.root.description", "The heart and story of the game");
add("advancements.story.upgrade_tools.description", "Construct a better pickaxe");
add("advancements.nether.all_effects.title", "How Did We Get Here?");
add("advancements.end.enter_end_gateway.title", "Remote Getaway");
add("advancements.story.mine_stone.description", "Mine stone with your new pickaxe");
add("advancements.husbandry.root.description", "The world is full of friends and food");
add("advancements.end.dragon_egg.title", "The Next Generation");
add("advancements.toast.goal", "Goal Reached!");
add("advancements.empty", "There doesn't seem to be anything here...");
add("advancements.husbandry.tame_an_animal.title", "Best Friends Forever");
add("advancements.end.root.title", "The End");
add("advancements.husbandry.breed_an_animal.title", "The Parrots and the Bats");
add("advancements.story.mine_diamond.description", "Acquire diamonds");
add("advancements.adventure.sleep_in_bed.title", "Sweet dreams");
add("advancements.nether.return_to_sender.title", "Return to Sender");
add("advancements.story.obtain_armor.title", "Suit Up");
add("advancements.adventure.kill_a_mob.description", "Kill any hostile monster");
add("advancements.nether.all_potions.description", "Have every potion effect applied at the same time");
add("advancements.story.iron_tools.title", "Isn't It Iron Pick");
add("advancements.adventure.sleep_in_bed.description", "Change your respawn point");
add("advancements.husbandry.plant_seed.description", "Plant a seed and watch it grow");
add("advancements.husbandry.breed_an_animal.description", "Breed two animals together");
add("advancements.adventure.shoot_arrow.title", "Take Aim");
add("advancements.adventure.adventuring_time.description", "Discover every biome");
add("advancements.adventure.adventuring_time.title", "Adventuring Time");
add("advancements.nether.get_wither_skull.description", "Obtain a wither skeleton's skull");
add("advancements.adventure.summon_iron_golem.description", "Summon an Iron Golem to help defend a village");
add("advancements.nether.return_to_sender.description", "Destroy a Ghast with a fireball");
add("advancements.adventure.trade.description", "Successfully trade with a Villager");
add("advancements.story.obtain_armor.description", "Protect yourself with a piece of iron armor");
add("advancements.adventure.root.description", "Adventure, exploration and combat");
add("advancements.nether.create_beacon.title", "Bring Home the Beacon");
add("advancements.end.dragon_egg.description", "Hold the Dragon Egg");
add("advancements.nether.obtain_blaze_rod.description", "Relieve a Blaze of its rod");
add("advancements.story.lava_bucket.description", "Fill a bucket with lava");
add("advancements.story.form_obsidian.title", "Ice Bucket Challenge");
add("advancements.story.enter_the_end.title", "The End?");
add("advancements.nether.fast_travel.title", "Subspace Bubble");
add("advancements.end.enter_end_gateway.description", "Escape the island");
add("advancements.adventure.totem_of_undying.title", "Postmortal");
add("advancements.nether.all_potions.title", "A Furious Cocktail");
add("advancements.adventure.sniper_duel.title", "Sniper duel");
add("advancements.nether.summon_wither.description", "Summon the Wither");
add("advancements.adventure.totem_of_undying.description", "Use a Totem of Undying to cheat death");
add("advancements.story.shiny_gear.description", "Diamond armor saves lives");
}
private static void add(String key, String value) {
advancements.put(key, value);
}
public static boolean has(String key) {
return advancements.containsKey(key);
}
public static String get(String key) {
return advancements.get(key);
}
}
@@ -0,0 +1,50 @@
/*
* 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_12to1_11_1.data;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class BlockColors {
private static Map<Integer, String> colors = new ConcurrentHashMap<>();
private static int count = 0;
static {
add("White");
add("Orange");
add("Magenta");
add("Light Blue");
add("Yellow");
add("Lime");
add("Pink");
add("Gray");
add("Light Gray");
add("Cyan");
add("Purple");
add("Blue");
add("Brown");
add("Green");
add("Red");
add("Black");
}
private static void add(String value) {
colors.put(count++, value);
}
public static boolean has(Integer key) {
return colors.containsKey(key);
}
public static String get(Integer key) {
return colors.getOrDefault(key, "Unknown color");
}
}
@@ -8,16 +8,13 @@
* 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;
package nl.matsv.viabackwards.protocol.protocol1_12to1_11_1.data;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import nl.matsv.viabackwards.api.entities.storage.EntityStorage;
@Data
@AllArgsConstructor
@EqualsAndHashCode
public class EntityType {
private boolean object;
private short entityType;
public class ParrotStorage extends EntityStorage {
private boolean tamed = true;
private boolean sitting = true;
}
@@ -0,0 +1,88 @@
/*
* 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_12to1_11_1.data;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import net.md_5.bungee.api.ChatColor;
import nl.matsv.viabackwards.ViaBackwards;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.data.StoredObject;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.protocols.protocol1_12to1_11_1.Protocol1_12To1_11_1;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
@Getter
@Setter
@ToString
public class ShoulderTracker extends StoredObject {
private int entityId;
private String leftShoulder;
private String rightShoulder;
public ShoulderTracker(UserConnection user) {
super(user);
}
public void update() {
PacketWrapper wrapper = new PacketWrapper(0x0F, null, getUser());
wrapper.write(Type.STRING, Protocol1_9TO1_8.fixJson(generateString()));
wrapper.write(Type.BYTE, (byte) 2);
try {
wrapper.send(Protocol1_12To1_11_1.class);
} catch (Exception e) {
ViaBackwards.getPlatform().getLogger().severe("Failed to send the shoulder indication");
e.printStackTrace();
}
}
// Does actionbar not support json colors? :(
private String generateString() {
StringBuilder builder = new StringBuilder();
// Empty spaces because the non-json formatting is weird
builder.append(" ");
if (leftShoulder == null)
builder.append(ChatColor.RED).append(ChatColor.BOLD).append("Nothing");
else
builder.append(ChatColor.DARK_GREEN).append(ChatColor.BOLD).append(getName(leftShoulder));
builder.append(ChatColor.DARK_GRAY).append(ChatColor.BOLD).append(" <- ")
.append(ChatColor.GRAY).append(ChatColor.BOLD).append("Shoulders")
.append(ChatColor.DARK_GRAY).append(ChatColor.BOLD).append(" -> ");
if (rightShoulder == null)
builder.append(ChatColor.RED).append(ChatColor.BOLD).append("Nothing");
else
builder.append(ChatColor.DARK_GREEN).append(ChatColor.BOLD).append(getName(rightShoulder));
return builder.toString();
}
private String getName(String current) {
if (current.startsWith("minecraft:"))
current = current.substring(10);
String[] array = current.split("_");
StringBuilder builder = new StringBuilder();
for (String s : array) {
builder.append(s.substring(0, 1).toUpperCase())
.append(s.substring(1))
.append(" ");
}
return builder.toString();
}
}
@@ -0,0 +1,307 @@
/*
* 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_12to1_11_1.packets;
import nl.matsv.viabackwards.api.rewriters.BlockItemRewriter;
import nl.matsv.viabackwards.protocol.protocol1_12to1_11_1.Protocol1_11_1To1_12;
import nl.matsv.viabackwards.protocol.protocol1_12to1_11_1.data.BlockColors;
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_12;
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.types.Chunk1_9_3_4Type;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import us.myles.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import us.myles.viaversion.libs.opennbt.tag.builtin.ListTag;
import java.util.Collections;
public class BlockItemPackets1_12 extends BlockItemRewriter<Protocol1_11_1To1_12> {
@Override
protected void registerPackets(Protocol1_11_1To1_12 protocol) {
/* Item packets */
// 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, 0x3E, 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, 0x08, 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, 0x1B, 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);
}
});
}
}
);
/* Block packets */
// Chunk packet
protocol.registerOutgoing(State.PLAY, 0x20, 0x20, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
Chunk1_9_3_4Type type = new Chunk1_9_3_4Type(clientWorld); // Use the 1.9.4 Chunk type since nothing changed.
Chunk1_9_3_4 chunk = (Chunk1_9_3_4) wrapper.passthrough(type);
handleChunk(chunk);
}
});
}
}
);
// Block Change Packet
protocol.registerOutgoing(State.PLAY, 0x0B, 0x0B, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION); // 0 - Block Position
map(Type.VAR_INT); // 1 - Block
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int idx = wrapper.get(Type.VAR_INT, 0);
wrapper.set(Type.VAR_INT, 0, handleBlockID(idx));
}
});
}
}
);
// Multi Block Change Packet
protocol.registerOutgoing(State.PLAY, 0x10, 0x10, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // 0 - Chunk X
map(Type.INT); // 1 - Chunk Z
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int count = wrapper.passthrough(Type.VAR_INT); // Array length
for (int i = 0; i < count; i++) {
wrapper.passthrough(Type.UNSIGNED_BYTE); // Horizontal position
wrapper.passthrough(Type.UNSIGNED_BYTE); // Y coords
int id = wrapper.read(Type.VAR_INT); // Block ID
wrapper.write(Type.VAR_INT, handleBlockID(id));
}
}
});
}
}
);
// Update Block Entity
protocol.registerOutgoing(State.PLAY, 0x09, 0x09, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION); // 0 - Position
map(Type.UNSIGNED_BYTE); // 1 - Action
map(Type.NBT); // 2 - NBT
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
// Remove bed color
if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 11)
wrapper.cancel();
}
});
}
});
protocol.getEntityPackets().registerMetaHandler().handle(e -> {
Metadata data = e.getData();
if (data.getMetaType().equals(MetaType1_12.Slot)) // Is Item
data.setValue(handleItemToClient((Item) data.getValue()));
return data;
});
// Client Status
protocol.registerIncoming(State.PLAY, 0x04, 0x03, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // Action ID
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
// Open Inventory
if (wrapper.get(Type.VAR_INT, 0) == 2)
wrapper.cancel(); // TODO is this replaced by something else?
}
});
}
});
}
@Override
protected void registerRewrites() {
// Concrete -> Stained clay? (Also got a new name Terracota?)
rewrite(251)
.repItem(new Item((short) 159, (byte) 1, (short) -1, getNamedTag("1.12 %viabackwards_color% Concrete")))
.repBlock(new Block(159, -1));
// Concrete Powder -> Wool
rewrite(252)
.repItem(new Item((short) 35, (byte) 1, (short) -1, getNamedTag("1.12 %viabackwards_color% Concrete Powder")))
.repBlock(new Block(35, -1));
// Knowledge book -> book
rewrite(453)
.repItem(new Item((short) 340, (byte) 1, (short) 0, getNamedTag("1.12 Knowledge Book")))
.itemHandler(i -> {
CompoundTag tag = i.getTag();
if (!tag.contains("ench"))
tag.put(new ListTag("ench", Collections.emptyList()));
return i;
});
// Glazed Terracotta -> Stained Clay
for (int i = 235; i < 251; i++) {
rewrite(i).repItem(new Item((short) 159, (byte) 1, (short) (i - 235), getNamedTag("1.12 " + BlockColors.get(i - 235) + " Glazed Terracotta")))
.repBlock(new Block(159, (i - 235)));
}
// Handle beds
rewrite(355).repItem(new Item((short) 355, (byte) 1, (short) 0, getNamedTag("1.12 %viabackwards_color% Bed")));
}
}
@@ -0,0 +1,128 @@
/*
* 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_12to1_11_1.packets;
import nl.matsv.viabackwards.api.rewriters.Rewriter;
import nl.matsv.viabackwards.protocol.protocol1_12to1_11_1.Protocol1_11_1To1_12;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.remapper.PacketHandler;
import us.myles.ViaVersion.api.remapper.PacketRemapper;
import us.myles.ViaVersion.packets.State;
public class ChangedPacketIds1_12 extends Rewriter<Protocol1_11_1To1_12> {
@Override
protected void registerPackets(Protocol1_11_1To1_12 p) {
p.registerOutgoing(State.PLAY, 0x25, 0x28); // Entity
p.registerOutgoing(State.PLAY, 0x26, 0x25); // Entity Relative Move
p.registerOutgoing(State.PLAY, 0x27, 0x26); // Entity Look and Relative Move
p.registerOutgoing(State.PLAY, 0x28, 0x27); // Entity Look
p.registerOutgoing(State.PLAY, 0x30, -1, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.cancel();
}
});
}
}); // Unlock Recipes TODO does ViaVersion cancel the packet if the new id is -1?
// 0x31 -> 0x30 Destroy Entities handled in EntityPackets1_12.java
p.registerOutgoing(State.PLAY, 0x32, 0x31); // Remove Entity Effect
p.registerOutgoing(State.PLAY, 0x33, 0x32); // Resource Pack Send
// 0x34 -> 0x33 Respawn handled in EntityPackets1_12.java
p.registerOutgoing(State.PLAY, 0x35, 0x34); // Entity Head Look
p.registerOutgoing(State.PLAY, 0x36, -1, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.cancel();
}
});
}
}); // Advancement Progress
p.registerOutgoing(State.PLAY, 0x37, 0x35); // World Border
p.registerOutgoing(State.PLAY, 0x38, 0x36); //Camera
p.registerOutgoing(State.PLAY, 0x39, 0x37); // Held Item Change (ClientBound)
p.registerOutgoing(State.PLAY, 0x3A, 0x38); // Display Scoreboard
// 0x3B -> 0x39 Entity Metadata handled in EntityPackets1_12.java
p.registerOutgoing(State.PLAY, 0x3C, 0x3A); // Attach Entity
p.registerOutgoing(State.PLAY, 0x3D, 0x3B); // Entity Velocity
// 0x3E -> 0x3C Entity Equipment handled in BlockItemPackets1_12.java
p.registerOutgoing(State.PLAY, 0x3F, 0x3D); // Set Experience
p.registerOutgoing(State.PLAY, 0x40, 0x3E); // Update Health
p.registerOutgoing(State.PLAY, 0x41, 0x3F); // ScoreBoard Objective
p.registerOutgoing(State.PLAY, 0x42, 0x40); // Set Passengers
p.registerOutgoing(State.PLAY, 0x43, 0x41); // Teams
p.registerOutgoing(State.PLAY, 0x44, 0x42); // Update Score
p.registerOutgoing(State.PLAY, 0x45, 0x43); // Spawn Position
p.registerOutgoing(State.PLAY, 0x46, 0x44); // Time Update
p.registerOutgoing(State.PLAY, 0x47, 0x45); // Title
// 0x48 -> 0x46 Sound Effect handled in SoundPackets1_12.java
p.registerOutgoing(State.PLAY, 0x49, 0x47); // Player List Header And Footer
p.registerOutgoing(State.PLAY, 0x4A, 0x48); // Collect Item
p.registerOutgoing(State.PLAY, 0x4B, 0x49); // Entity Teleport
p.registerOutgoing(State.PLAY, 0x4C, -1, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.cancel();
}
});
}
}); // Advancements
p.registerOutgoing(State.PLAY, 0x4D, 0x4A); // Entity Properties
p.registerOutgoing(State.PLAY, 0x4E, 0x4B); // Entity Effect
p.registerIncoming(State.PLAY, 0x01, -1); // Prepare Crafting Grid
p.registerIncoming(State.PLAY, 0x02, 0x01); // Tab-Complete (Serverbound)
p.registerIncoming(State.PLAY, 0x03, 0x02); // Chat Message (Serverbound)
// 0x04->0x03 Client Status handled in BlockItemPackets1_12.java
p.registerIncoming(State.PLAY, 0x05, 0x04); // Client Settings
p.registerIncoming(State.PLAY, 0x06, 0x05); // Confirm Transaction (Serverbound)
p.registerIncoming(State.PLAY, 0x07, 0x06); // Enchant Item
// 0x08 -> 0x07 Click Window handled in BlockItemPackets1_12.java
p.registerIncoming(State.PLAY, 0x09, 0x08); // Close Window (Serverbound)
p.registerIncoming(State.PLAY, 0x0A, 0x09); // Plugin message (Serverbound)
p.registerIncoming(State.PLAY, 0x0B, 0x0A); // Use Entity
p.registerIncoming(State.PLAY, 0x0C, 0x0B); // Keep Alive (Serverbound)
p.registerIncoming(State.PLAY, 0x0D, 0x0F); // Player
p.registerIncoming(State.PLAY, 0x0E, 0x0C); // Player Position
p.registerIncoming(State.PLAY, 0x0F, 0x0D); // Player Position And Look (ServerBound)
p.registerIncoming(State.PLAY, 0x10, 0x0E); // Player Look
p.registerIncoming(State.PLAY, 0x11, 0x10); // Vehicle Move
p.registerIncoming(State.PLAY, 0x12, 0x11); // Steer Boat
p.registerIncoming(State.PLAY, 0x13, 0x12); // Player Abilities (Serverbound)
p.registerIncoming(State.PLAY, 0x14, 0x13); // Player Digging
p.registerIncoming(State.PLAY, 0x15, 0x14); // Entity Action
p.registerIncoming(State.PLAY, 0x16, 0x15); // Steer Vehicle
p.registerIncoming(State.PLAY, 0x17, -1); // Crafting Book Data
p.registerIncoming(State.PLAY, 0x18, 0x16); // Resource Pack Status
p.registerIncoming(State.PLAY, 0x19, -1); // Advancement Tab
p.registerIncoming(State.PLAY, 0x1A, 0x17); // Held Item Change (Serverbound)
// 0x1B -> 0x18 Creative Inventory Action handled in BlockItemPackets.java
p.registerIncoming(State.PLAY, 0x1C, 0x19); // Update Sign
p.registerIncoming(State.PLAY, 0x1D, 0x1A); // Animatin (Serverbound)
p.registerIncoming(State.PLAY, 0x1E, 0x1B); // Spectate
p.registerIncoming(State.PLAY, 0x1F, 0x1C); // Player Block Placement
p.registerIncoming(State.PLAY, 0x20, 0x1D); // Use Item
}
@Override
protected void registerRewrites() {
}
}
@@ -0,0 +1,106 @@
/*
* 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_12to1_11_1.packets;
import nl.matsv.viabackwards.ViaBackwards;
import nl.matsv.viabackwards.api.rewriters.Rewriter;
import nl.matsv.viabackwards.protocol.protocol1_12to1_11_1.Protocol1_11_1To1_12;
import nl.matsv.viabackwards.protocol.protocol1_12to1_11_1.data.AdvancementTranslations;
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.packets.State;
import us.myles.viaversion.libs.gson.JsonElement;
import us.myles.viaversion.libs.gson.JsonObject;
import us.myles.viaversion.libs.gson.JsonParser;
import java.util.Map;
public class ChatPackets1_12 extends Rewriter<Protocol1_11_1To1_12> {
@Override
protected void registerPackets(Protocol1_11_1To1_12 protocol) {
// Chat Message (ClientBound)
protocol.registerOutgoing(State.PLAY, 0x0F, 0x0F, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING); // 0 - Json Data
map(Type.BYTE); // 1 - Position
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
JsonParser parser = new JsonParser();
try {
JsonObject object = parser.parse(wrapper.get(Type.STRING, 0)).getAsJsonObject();
// Skip if the root doesn't contain translate
if (object.has("translate"))
handleTranslations(object);
wrapper.set(Type.STRING, 0, object.toString());
} catch (Exception e) {
// Only print if ViaVer debug is enabled
if (Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().severe("Failed to handle translations");
e.printStackTrace();
}
}
}
});
}
});
}
// TODO improve this, not copying will cause ConcurrentModificationException
public void handleTranslations(JsonObject object) {
JsonObject copiedObj = copy(object);
if (object.isJsonObject()) {
for (Map.Entry<String, JsonElement> entry : copiedObj.entrySet()) {
// Get the text that doesn't exist for 1.11 <
if (entry.getKey().equalsIgnoreCase("translate") && AdvancementTranslations.has(entry.getValue().getAsString())) {
String trans = entry.getValue().getAsString();
object.remove("translate");
object.addProperty("translate", AdvancementTranslations.get(trans));
}
// Handle arrays
if (entry.getValue().isJsonArray())
for (JsonElement element : object.get(entry.getKey()).getAsJsonArray())
if (element.isJsonObject())
handleTranslations(element.getAsJsonObject());
// Handle objects
if (entry.getValue().isJsonObject())
handleTranslations(object.get(entry.getKey()).getAsJsonObject());
}
}
}
public JsonObject copy(JsonObject object) {
JsonObject result = new JsonObject();
for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
if (entry.getValue().isJsonObject())
result.add(entry.getKey(), copy(entry.getValue().getAsJsonObject()));
else
result.add(entry.getKey(), entry.getValue());
}
return result;
}
@Override
protected void registerRewrites() {
}
}
@@ -0,0 +1,481 @@
/*
* 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_12to1_11_1.packets;
import nl.matsv.viabackwards.ViaBackwards;
import nl.matsv.viabackwards.api.entities.storage.EntityData;
import nl.matsv.viabackwards.api.entities.storage.MetaStorage;
import nl.matsv.viabackwards.api.entities.types.AbstractEntityType;
import nl.matsv.viabackwards.api.entities.types.EntityType1_12;
import nl.matsv.viabackwards.api.exceptions.RemovedValueException;
import nl.matsv.viabackwards.api.rewriters.EntityRewriter;
import nl.matsv.viabackwards.protocol.protocol1_12to1_11_1.Protocol1_11_1To1_12;
import nl.matsv.viabackwards.protocol.protocol1_12to1_11_1.data.ParrotStorage;
import nl.matsv.viabackwards.protocol.protocol1_12to1_11_1.data.ShoulderTracker;
import nl.matsv.viabackwards.utils.Block;
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_12;
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_12;
import us.myles.ViaVersion.packets.State;
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.Optional;
import static nl.matsv.viabackwards.api.entities.types.EntityType1_12.*;
public class EntityPackets1_12 extends EntityRewriter<Protocol1_11_1To1_12> {
@Override
protected void registerPackets(Protocol1_11_1To1_12 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<EntityType1_12.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));
}
}
}
});
// Handle FallingBlock blocks
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Optional<EntityType1_12.ObjectType> type = ObjectType.findById(wrapper.get(Type.BYTE, 0));
if (type.isPresent() && type.get().equals(ObjectType.FALLING_BLOCK)) {
int objectData = wrapper.get(Type.INT, 0);
int objType = objectData & 4095;
int data = objectData >> 12 & 15;
Block block = getProtocol().getBlockItemPackets().handleBlock(objType, data);
if (block == null)
return;
wrapper.set(Type.INT, 0, block.getId() | block.getData() << 12);
}
}
});
}
});
// 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_12.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_12.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.VAR_INT, 1, data.getReplacementId());
if (data.hasBaseMeta())
data.getDefaultMeta().handle(storage);
}
// Rewrite Metadata
wrapper.set(
Types1_12.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
);
}
});
}
});
// 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_12.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_12.METADATA_LIST,
0,
handleMeta(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
new MetaStorage(wrapper.get(Types1_12.METADATA_LIST, 0))
).getMetaDataList()
);
}
});
}
});
// 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 {
ShoulderTracker tracker = wrapper.user().get(ShoulderTracker.class);
tracker.setEntityId(wrapper.get(Type.INT, 0));
}
});
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);
}
});
// Send fake inventory achievement
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper packetWrapper) throws Exception {
PacketWrapper wrapper = new PacketWrapper(0x07, null, packetWrapper.user());
wrapper.write(Type.VAR_INT, 1);
wrapper.write(Type.STRING, "achievement.openInventory");
wrapper.write(Type.VAR_INT, 1);
wrapper.send(Protocol1_11_1To1_12.class);
}
});
}
});
// Respawn Packet (save dimension id)
protocol.registerOutgoing(State.PLAY, 0x34, 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);
}
});
}
});
// Destroy entities
protocol.registerOutgoing(State.PLAY, 0x31, 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, 0x3B, 0x39, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Types1_12.METADATA_LIST); // 1 - Metadata list
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.set(
Types1_12.METADATA_LIST,
0,
handleMeta(
wrapper.user(),
wrapper.get(Type.VAR_INT, 0),
new MetaStorage(wrapper.get(Types1_12.METADATA_LIST, 0))
).getMetaDataList()
);
}
});
}
});
}
@Override
protected void registerRewrites() {
regEntType(EntityType.PARROT, EntityType.BAT).mobName("Parrot").spawnMetadata(storage -> storage.add(new Metadata(12, MetaType1_12.Byte, (byte) 0x00)));
regEntType(EntityType.ILLUSION_ILLAGER, EntityType.EVOCATION_ILLAGER).mobName("Illusioner");
// Handle Illager
registerMetaHandler().filter(EntityType.EVOCATION_ILLAGER, true, 12).removed();
registerMetaHandler().filter(EntityType.EVOCATION_ILLAGER, true, 13).handleIndexChange(12);
registerMetaHandler().filter(EntityType.ILLUSION_ILLAGER, 0).handle(e -> {
byte mask = (byte) e.getData().getValue();
if ((mask & 0x20) == 0x20)
mask &= ~0x20;
e.getData().setValue(mask);
return e.getData();
});
// Create Parrot storage
registerMetaHandler().filter(EntityType.PARROT, true).handle(e -> {
if (!e.getEntity().has(ParrotStorage.class))
e.getEntity().put(new ParrotStorage());
return e.getData();
});
// Parrot remove animal metadata
registerMetaHandler().filter(EntityType.PARROT, 12).removed(); // Is baby
registerMetaHandler().filter(EntityType.PARROT, 13).handle(e -> {
Metadata data = e.getData();
ParrotStorage storage = e.getEntity().get(ParrotStorage.class);
boolean isSitting = (((byte) data.getValue()) & 0x01) == 0x01;
boolean isTamed = (((byte) data.getValue()) & 0x04) == 0x04;
if (!storage.isTamed() && isTamed) {
// TODO do something to let the user know it's done
}
storage.setTamed(isTamed);
if (isSitting) {
data.setId(12);
data.setValue((byte) 0x01);
storage.setSitting(true);
} else if (storage.isSitting()) {
data.setId(12);
data.setValue((byte) 0x00);
storage.setSitting(false);
} else
throw new RemovedValueException();
return data;
}); // Flags (Is sitting etc, might be useful in the future
registerMetaHandler().filter(EntityType.PARROT, 14).removed(); // Owner
registerMetaHandler().filter(EntityType.PARROT, 15).removed(); // Variant
// Left shoulder entity data
registerMetaHandler().filter(EntityType.PLAYER, 15).handle(e -> {
CompoundTag tag = (CompoundTag) e.getData().getValue();
ShoulderTracker tracker = e.getUser().get(ShoulderTracker.class);
if (tag.isEmpty() && tracker.getLeftShoulder() != null) {
tracker.setLeftShoulder(null);
tracker.update();
} else if (tag.contains("id") && e.getEntity().getEntityId() == tracker.getEntityId()) {
String id = (String) tag.get("id").getValue();
if (tracker.getLeftShoulder() == null || !tracker.getLeftShoulder().equals(id)) {
tracker.setLeftShoulder(id);
tracker.update();
}
}
throw new RemovedValueException();
});
// Right shoulder entity data
registerMetaHandler().filter(EntityType.PLAYER, 16).handle(e -> {
CompoundTag tag = (CompoundTag) e.getData().getValue();
ShoulderTracker tracker = e.getUser().get(ShoulderTracker.class);
if (tag.isEmpty() && tracker.getRightShoulder() != null) {
tracker.setRightShoulder(null);
tracker.update();
} else if (tag.contains("id") && e.getEntity().getEntityId() == tracker.getEntityId()) {
String id = (String) tag.get("id").getValue();
if (tracker.getRightShoulder() == null || !tracker.getRightShoulder().equals(id)) {
tracker.setRightShoulder(id);
tracker.update();
}
}
throw new RemovedValueException();
});
}
}
@@ -0,0 +1,139 @@
/*
* 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_12to1_11_1.packets;
import nl.matsv.viabackwards.api.rewriters.SoundRewriter;
import nl.matsv.viabackwards.protocol.protocol1_12to1_11_1.Protocol1_11_1To1_12;
import us.myles.ViaVersion.api.PacketWrapper;
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 SoundPackets1_12 extends SoundRewriter<Protocol1_11_1To1_12> {
@Override
protected void registerPackets(Protocol1_11_1To1_12 protocol) {
// Named sound effect
protocol.registerOutgoing(State.PLAY, 0x19, 0x19, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING); // 0 - Sound name
map(Type.VAR_INT); // 1 - Sound Category
map(Type.INT); // 2 - x
map(Type.INT); // 3 - y
map(Type.INT); // 4 - z
map(Type.FLOAT); // 5 - Volume
map(Type.FLOAT); // 6 - Pitch
}
});
// Sound effect
protocol.registerOutgoing(State.PLAY, 0x48, 0x46, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Sound name
map(Type.VAR_INT); // 1 - Sound Category
map(Type.INT); // 2 - x
map(Type.INT); // 3 - y
map(Type.INT); // 4 - z
map(Type.FLOAT); // 5 - Volume
map(Type.FLOAT); // 6 - Pitch
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int oldId = wrapper.get(Type.VAR_INT, 0);
int newId = handleSounds(oldId);
if (newId == -1)
wrapper.cancel();
else {
if (hasPitch(oldId))
wrapper.set(Type.FLOAT, 1, handlePitch(oldId));
wrapper.set(Type.VAR_INT, 0, newId);
}
}
});
}
});
}
@Override
protected void registerRewrites() {
// Replacement sounds, suggestions are always welcome
// Automatically generated from PAaaS
added(26, 277, 1.4f); // block.end_portal.spawn -> entity.lightning.thunder
added(27, -1); // block.end_portal_frame.fill
added(72, 70); // block.note.bell -> block.note.harp
added(73, 70); // block.note.chime -> block.note.harp
added(74, 70); // block.note.flute -> block.note.harp
added(75, 70); // block.note.guitar -> block.note.harp
added(80, 70); // block.note.xylophone -> block.note.harp
added(150, -1); // entity.boat.paddle_land
added(151, -1); // entity.boat.paddle_water
added(152, -1); // entity.bobber.retrieve
added(195, -1); // entity.endereye.death
added(274, 198, 0.8f); // entity.illusion_illager.ambient -> entity.evocation_illager.ambient
added(275, 199, 0.8f); // entity.illusion_illager.cast_spell -> entity.evocation_illager.cast_spell
added(276, 200, 0.8f); // entity.illusion_illager.death -> entity.evocation_illager.death
added(277, 201, 0.8f); // entity.illusion_illager.hurt -> entity.evocation_illager.hurt
added(278, 191, 0.9f); // entity.illusion_illager.mirror_move -> entity.endermen.teleport
added(279, 203, 1.5f); // entity.illusion_illager.prepare_blindness -> entity.evocation_illager.prepare_summon
added(280, 202, 0.8f); // entity.illusion_illager.prepare_mirror -> entity.evocation_illager.prepare_attack
added(319, 133, 0.6f); // entity.parrot.ambient -> entity.bat.ambient
added(320, 134, 1.7f); // entity.parrot.death -> entity.bat.death
added(321, 219, 1.5f); // entity.parrot.eat -> entity.generic.eat
added(322, 136, 0.7f); // entity.parrot.fly -> entity.bat.loop
added(323, 135, 1.6f); // entity.parrot.hurt -> entity.bat.hurt
added(324, 138, 1.5f); // entity.parrot.imitate.blaze -> entity.blaze.ambient
added(325, 163, 1.5f); // entity.parrot.imitate.creeper -> entity.creeper.primed
added(326, 170, 1.5f); // entity.parrot.imitate.elder_guardian -> entity.elder_guardian.ambient
added(327, 178, 1.5f); // entity.parrot.imitate.enderdragon -> entity.enderdragon.ambient
added(328, 186, 1.5f); // entity.parrot.imitate.enderman -> entity.endermen.ambient
added(329, 192, 1.5f); // entity.parrot.imitate.endermite -> entity.endermite.ambient
added(330, 198, 1.5f); // entity.parrot.imitate.evocation_illager -> entity.evocation_illager.ambient
added(331, 226, 1.5f); // entity.parrot.imitate.ghast -> entity.ghast.ambient
added(332, 259, 1.5f); // entity.parrot.imitate.husk -> entity.husk.ambient
added(333, 198, 1.3f); // entity.parrot.imitate.illusion_illager -> entity.evocation_illager.ambient
added(334, 291, 1.5f); // entity.parrot.imitate.magmacube -> entity.magmacube.squish
added(335, 321, 1.5f); // entity.parrot.imitate.polar_bear -> entity.polar_bear.ambient
added(336, 337, 1.5f); // entity.parrot.imitate.shulker -> entity.shulker.ambient
added(337, 347, 1.5f); // entity.parrot.imitate.silverfish -> entity.silverfish.ambient
added(338, 351, 1.5f); // entity.parrot.imitate.skeleton -> entity.skeleton.ambient
added(339, 363, 1.5f); // entity.parrot.imitate.slime -> entity.slime.squish
added(340, 376, 1.5f); // entity.parrot.imitate.spider -> entity.spider.ambient
added(341, 385, 1.5f); // entity.parrot.imitate.stray -> entity.stray.ambient
added(342, 390, 1.5f); // entity.parrot.imitate.vex -> entity.vex.ambient
added(343, 400, 1.5f); // entity.parrot.imitate.vindication_illager -> entity.vindication_illager.ambient
added(344, 403, 1.5f); // entity.parrot.imitate.witch -> entity.witch.ambient
added(345, 408, 1.5f); // entity.parrot.imitate.wither -> entity.wither.ambient
added(346, 414, 1.5f); // entity.parrot.imitate.wither_skeleton -> entity.wither_skeleton.ambient
added(347, 418, 1.5f); // entity.parrot.imitate.wolf -> entity.wolf.ambient
added(348, 427, 1.5f); // entity.parrot.imitate.zombie -> entity.zombie.ambient
added(349, 438, 1.5f); // entity.parrot.imitate.zombie_pigman -> entity.zombie_pig.ambient
added(350, 442, 1.5f); // entity.parrot.imitate.zombie_villager -> entity.zombie_villager.ambient
added(351, 155); // entity.parrot.step -> entity.chicken.step
added(368, 316); // entity.player.hurt_drown -> entity.player.hurt
added(369, 316); // entity.player.hurt_on_fire -> entity.player.hurt
// No replacement sounds for these, since it could be confusing, the toast doesn't show up
added(544, -1); // ui.toast.in
added(545, -1); // ui.toast.out
added(546, 317, 1.5f); // ui.toast.challenge_complete
}
}
@@ -12,23 +12,24 @@ package nl.matsv.viabackwards.protocol.protocol1_9_4to1_10;
import lombok.Getter;
import nl.matsv.viabackwards.api.BackwardsProtocol;
import nl.matsv.viabackwards.api.storage.EntityTracker;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.packets.BlockItemPackets;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.packets.ChangedPackets;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.packets.EntityPackets;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.packets.SoundPackets;
import nl.matsv.viabackwards.api.entities.storage.EntityTracker;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.packets.BlockItemPackets1_10;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.packets.ChangedPackets1_10;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.packets.EntityPackets1_10;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.packets.SoundPackets1_10;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
@Getter
public class Protocol1_9_4To1_10 extends BackwardsProtocol {
private EntityPackets entityPackets; // Required for the item rewriter
private EntityPackets1_10 entityPackets; // Required for the item rewriter
private BlockItemPackets1_10 blockItemPackets;
protected void registerPackets() {
new ChangedPackets().register(this);
new SoundPackets().register(this);
(entityPackets = new EntityPackets()).register(this);
new BlockItemPackets().register(this);
new ChangedPackets1_10().register(this);
new SoundPackets1_10().register(this);
(entityPackets = new EntityPackets1_10()).register(this);
(blockItemPackets = new BlockItemPackets1_10()).register(this);
}
public void init(UserConnection user) {
@@ -39,5 +40,8 @@ public class Protocol1_9_4To1_10 extends BackwardsProtocol {
// 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);
}
}
@@ -1,124 +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 input) throws Exception {
if (!(input instanceof Chunk1_10))
throw new Exception("Tried to send the wrong chunk type from 1.9.3-4 chunk: " + input.getClass());
Chunk1_10 chunk = (Chunk1_10) input;
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;
}
}
@@ -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;
}
}
@@ -12,21 +12,20 @@ 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.types.Chunk1_9_3_4Type;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
// TODO REWRITE PLUGINS MESSAGE ITEMS
public class BlockItemPackets extends BlockItemRewriter<Protocol1_9_4To1_10> {
public class BlockItemPackets1_10 extends BlockItemRewriter<Protocol1_9_4To1_10> {
protected void registerPackets(Protocol1_9_4To1_10 protocol) {
/* Item packets */
@@ -167,26 +166,10 @@ 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];
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);
section.setBlock(x, y, z, b.getId(), b.getData());
}
}
}
}
}
handleChunk(chunk);
}
});
}
@@ -236,8 +219,10 @@ public class BlockItemPackets extends BlockItemRewriter<Protocol1_9_4To1_10> {
}
);
/* Register Metadata */
protocol.getEntityPackets().registerMetaRewriter((isObject, entityType, 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()));
@@ -245,23 +230,13 @@ 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
rewriteBlockItem(217, new Item((short) 287, (byte) 1, (short) 0, getNamedTag("1.10 Structure Void")), new Block(287, 0)); // Structure void to string
rewriteBlockItem(213, new Item((short) 159, (byte) 1, (short) 1, getNamedTag("1.10 Magma Block")), new Block(159, 1)); // Magma block to orange clay
rewriteBlockItem(214, new Item((short) 159, (byte) 1, (short) 14, getNamedTag("1.10 Nether Ward Block")), new Block(159, 14)); // Nether wart block to red clay
rewriteBlockItem(215, new Item((short) 112, (byte) 1, (short) 0, getNamedTag("1.10 Red Nether Bricks")), new Block(112, 0)); // Red nether brick to nether brick
rewriteBlockItem(216, new Item((short) 155, (byte) 1, (short) 0, getNamedTag("1.10 Bone Block")), new Block(155, 0)); // Bone block to quartz
rewrite(255).repItem(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
rewrite(217).repItem(new Item((short) 287, (byte) 1, (short) 0, getNamedTag("1.10 Structure Void"))).repBlock(new Block(287, 0)); // Structure void to string
rewrite(213).repItem(new Item((short) 159, (byte) 1, (short) 1, getNamedTag("1.10 Magma Block"))).repBlock(new Block(159, 1)); // Magma block to orange clay
rewrite(214).repItem(new Item((short) 159, (byte) 1, (short) 14, getNamedTag("1.10 Nether Ward Block"))).repBlock(new Block(159, 14)); // Nether wart block to red clay
rewrite(215).repItem(new Item((short) 112, (byte) 1, (short) 0, getNamedTag("1.10 Red Nether Bricks"))).repBlock(new Block(112, 0)); // Red nether brick to nether brick
rewrite(216).repItem(new Item((short) 155, (byte) 1, (short) 0, getNamedTag("1.10 Bone Block"))).repBlock(new Block(155, 0)); // Bone block to quartz
}
}
@@ -15,7 +15,7 @@ import us.myles.ViaVersion.api.remapper.PacketRemapper;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.packets.State;
public class ChangedPackets {
public class ChangedPackets1_10 {
public void register(BackwardsProtocol protocol) {
/* ServerBound packets */
@@ -0,0 +1,416 @@
/*
* 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.packets;
import nl.matsv.viabackwards.ViaBackwards;
import nl.matsv.viabackwards.api.entities.storage.EntityData;
import nl.matsv.viabackwards.api.entities.storage.MetaStorage;
import nl.matsv.viabackwards.api.entities.types.AbstractEntityType;
import nl.matsv.viabackwards.api.entities.types.EntityType1_10;
import nl.matsv.viabackwards.api.entities.types.EntityType1_11;
import nl.matsv.viabackwards.api.entities.types.EntityType1_12;
import nl.matsv.viabackwards.api.exceptions.RemovedValueException;
import nl.matsv.viabackwards.api.rewriters.EntityRewriter;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.Protocol1_9_4To1_10;
import nl.matsv.viabackwards.utils.Block;
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;
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.types.EntityType1_10.EntityType;
import static nl.matsv.viabackwards.api.entities.types.EntityType1_11.getTypeFromId;
public class EntityPackets1_10 extends EntityRewriter<Protocol1_9_4To1_10> {
@Override
protected void registerPackets(Protocol1_9_4To1_10 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<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));
}
}
}
});
// Handle FallingBlock blocks
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Optional<EntityType1_12.ObjectType> type = EntityType1_12.ObjectType.findById(wrapper.get(Type.BYTE, 0));
if (type.isPresent() && type.get().equals(EntityType1_12.ObjectType.FALLING_BLOCK)) {
int objectData = wrapper.get(Type.INT, 0);
int objType = objectData & 4095;
int data = objectData >> 12 & 15;
Block block = getProtocol().getBlockItemPackets().handleBlock(objType, data);
if (block == null)
return;
wrapper.set(Type.INT, 0, block.getId() | block.getData() << 12);
}
}
});
}
});
// 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),
EntityType1_10.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.UNSIGNED_BYTE); // 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),
EntityType1_10.getTypeFromId(wrapper.get(Type.UNSIGNED_BYTE, 0), 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() {
regEntType(EntityType.POLAR_BEAR, EntityType.SHEEP).mobName("Polar Bear");
// 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();
data.setMetaType(MetaType1_9.Byte);
data.setValue(b ? (byte) (14 & 0x0F) : (byte) (0));
return data;
}));
// 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 (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
return data;
});
// Handle the missing NoGravity tag for every metadata
registerMetaHandler().handle(e -> {
Metadata data = e.getData();
if (data.getId() == 5)
throw new RemovedValueException();
else if (data.getId() >= 5)
data.setId(data.getId() - 1);
return data;
});
}
}
@@ -10,7 +10,7 @@
package nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.packets;
import nl.matsv.viabackwards.api.rewriters.SoundIdRewriter;
import nl.matsv.viabackwards.api.rewriters.SoundRewriter;
import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.Protocol1_9_4To1_10;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.remapper.PacketHandler;
@@ -19,7 +19,7 @@ import us.myles.ViaVersion.api.remapper.ValueTransformer;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.packets.State;
public class SoundPackets extends SoundIdRewriter<Protocol1_9_4To1_10> {
public class SoundPackets1_10 extends SoundRewriter<Protocol1_9_4To1_10> {
protected static ValueTransformer<Float, Short> toOldPitch = new ValueTransformer<Float, Short>(Type.UNSIGNED_BYTE) {
public Short transform(PacketWrapper packetWrapper, Float inputValue) throws Exception {
return (short) Math.round(inputValue * 63.5F);
@@ -74,32 +74,33 @@ public class SoundPackets extends SoundIdRewriter<Protocol1_9_4To1_10> {
@Override
protected void registerRewrites() {
rewriteSound(24, -1); // Enchantment table sound
added(24, -1); // Enchantment table sound
// Husk
rewriteSound(249, 400); // Husk -> Zombie ambient
rewriteSound(250, 404); // Husk -> Zombie death
rewriteSound(251, 405); // Husk -> Zombie hurt
rewriteSound(252, 407); // Husk -> Zombie step
added(249, 381); // Husk -> Zombie ambient
added(250, 385); // Husk -> Zombie death
added(251, 386); // Husk -> Zombie hurt
added(252, 388); // Husk -> Zombie step
// Polar bear
rewriteSound(301, 400, .6F); // Polar bear ambient
rewriteSound(302, 400, 1.9F); // Polar baby bear ambient
rewriteSound(303, 404, .7F); // Polar bear death
rewriteSound(304, 320, .6F); // Polar bear hurt
rewriteSound(305, 241, .6F); // Polar bear step
rewriteSound(306, 393, 1.2F); // Polar bear warning
added(301, 381, .6F); // Polar bear ambient -> Zombie ambient
added(302, 381, 1.9F); // Polar baby bear ambient -> Zombie ambient
added(303, 385, .7F); // Polar bear death -> Zombie death
added(304, 309, .6F); // Polar bear hurt -> Shulker hurt
added(305, 240, .6F); // Polar bear step -> Horse step
added(306, 374, 1.2F); // Polar bear warning -> Wolf growl
// Stray
rewriteSound(365, 331); // Stray -> Skeleton ambient
rewriteSound(366, 332); // Stray -> Skeleton death
rewriteSound(367, 333); // Stray -> Skeleton hurt
rewriteSound(368, 335); // Stray -> Skeleton step
added(365, 320); // Stray -> Skeleton ambient
added(366, 321); // Stray -> Skeleton death
added(367, 322); // Stray -> Skeleton hurt
added(368, 324); // Stray -> Skeleton step
// Wither skeleton
rewriteSound(387, 331); // Wither skeleton -> Skeleton ambient
rewriteSound(388, 332); // Wither skeleton -> Skeleton death
rewriteSound(389, 333); // Wither skeleton -> Skeleton hurt
rewriteSound(390, 335); // Wither skeleton -> Skeleton step
added(387, 320); // Wither skeleton -> Skeleton ambient
added(388, 321); // Wither skeleton -> Skeleton death
added(389, 322); // Wither skeleton -> Skeleton hurt
added(390, 324); // Wither skeleton -> Skeleton step
}
}
@@ -20,4 +20,8 @@ import lombok.EqualsAndHashCode;
public class Block {
private int id;
private int data;
public Block clone() {
return new Block(id, data);
}
}
+9 -2
View File
@@ -16,7 +16,7 @@
<groupId>nl.matsv</groupId>
<artifactId>viabackwards-parent</artifactId>
<version>2.0</version>
<version>2.1.1</version>
<packaging>pom</packaging>
<description>Allow newer clients to join older server versions.</description>
@@ -40,6 +40,13 @@
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>viaversion-repo</id>
<url>https://repo.viaversion.com</url>
</repository>
</repositories>
<dependencies>
<!-- Lombok -->
<dependency>
@@ -58,7 +65,7 @@
<dependency>
<groupId>us.myles</groupId>
<artifactId>viaversion</artifactId>
<version>1.0.0</version>
<version>1.1.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
+1 -1
View File
@@ -15,7 +15,7 @@
<parent>
<artifactId>viabackwards-parent</artifactId>
<groupId>nl.matsv</groupId>
<version>2.0</version>
<version>2.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -11,6 +11,7 @@
package nl.matsv.viabackwards;
import com.google.inject.Inject;
import nl.matsv.viabackwards.api.ViaBackwardsPlatform;
import nl.matsv.viabackwards.sponge.VersionInfo;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.game.state.GameAboutToStartServerEvent;
@@ -45,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() {
}
}