diff --git a/LICENSE.txt b/GPL.txt similarity index 100% rename from LICENSE.txt rename to GPL.txt diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..5c7cd960 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,24 @@ +SonarPet is a fork of [EchoPet](https://github.com/DSH105/EchoPet) and inherits its licensing. + +EchoPet is [GPLv3 Licensed](./GPL.txt). Any uses of this project +must comply with the terms of the GPL. +The original code from DSH105 is under that license +and we must comply with it. + +By default, all contributions are licensed + under the (restrictive) GPLv3 license. + +The GPL is somewhat restrictive and prevents inclusion +in proprietary software. + + +I (Techcable) have chosen to release all +my changes under the [MIT License](./MIT.txt). This is retroactive - it includes all +of my changes that I ever contributed to this repository. + +Contributors may also choose to release their changes under +the (permissive) MIT license by adding their names to the following +list: +```` +Techcable , +```` \ No newline at end of file diff --git a/MIT.txt b/MIT.txt new file mode 100644 index 00000000..18b3002d --- /dev/null +++ b/MIT.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Nicholas Schlabach + +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. \ No newline at end of file diff --git a/README.md b/README.md index 7acb7c2c..4067b340 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,29 @@ SonarPet [![Build Status](https://travis-ci.org/TechzoneMC/SonarPet.svg?branch=master)](https://travis-ci.org/TechzoneMC/SonarPet) ======== -A fork of [EchoPet](https://github.com/DSH105/EchoPet) updated to 1.11 +A fork of [EchoPet](https://github.com/DSH105/EchoPet) updated to modern versions -## **NOTE**: Unmaintained -I'm no longer willing to be the primary maintainer of SonarPet, -contact me on IRC if you're willing to take over this job. +## **NOTE**: Inactive +In spite of recent activity, SonarPet is still officially unmaintained. +This is still "officially" unsupported unless I decide to +Contact me on IRC if you're willing to help with maintenance and support. + +### Supported Versions/Servers +SonarPet is undergoing some internal changes: +1. Support for "multiple versions" is being dropped. + - Due to rapid changes to mi + - Supporting 10 versions at once is incredibly draining!!!! +2. This plugin officially requires [Paper](https://papermc.io/)!! + - Spigot and CraftBukkit are unsupported - they will no longer work in the future. + - In the future, I plan to use official Paper APIs to replace most of our NMS code + - Ideally we would have zero-NMS dependencies +3. SonarPet will be completely free, and I will no longer offer paid support. + - SonarPet was previously released as a paid resource on Spigot + (with a portion of all revenue going to the old authors) + - I apologize for dropping support for a paid plugin. I should have realized + full-time development was incompatible with my school schedule. It was misleading, + and I won't do it again. + - Don't give me too hard a time: My code was still better than + 99.9% of all other paid plugins ## Features - All mobs can be pets (even enderdragons) @@ -12,20 +31,32 @@ contact me on IRC if you're willing to take over this job. - Pets are greatly customisable, through the extensive Command Base and PetMenu - A Custom AI makes all Pets focused on specific goals, handled closely by the core of the Plugin - Make your pets attack your enemies -- Supports minecraft 1.6.4-1.11 ## Changes I've made some changes to EchoPet in SonarPet, which are listed below. - I've renamed references from 'EchoPet' to 'SonarPet' - Permissions and class names remain, to retain backwards compatibility and to avoid the need to change permissions - I've added 1.9-1.11 support + - Note: Multiple version support will be dropped in the future!!!! ## Requirements -- Java 8 +- Modern Minecraft + - Don't use old versions! + - Eventually I'll drop multi-version support..... +- [Paper](https://papermc.io/) + - Paper is strictly better than Spigot. Use it! ## Credits - Dsh105 - Creating EchoPet - CaptainBern - Helping out with EchoPet -- Techcable - 1.9-1.11 update and maintinaing SonarPet +- Techcable - 1.9+ updates and maintaining SonarPet + - NOTE: I'm officially inactive/dead. Please do not conduct a seance. ## License +EchoPet was originally licensed under the GPLv3. +This essentially requires us to be an open source project. + +As + +Please respect the contributions of the original authors and maintainers +by releasing your contributions to the public. It's the least you can do :) diff --git a/api/src/main/java/com/dsh105/echopet/compat/api/config/ConfigOptions.java b/api/src/main/java/com/dsh105/echopet/compat/api/config/ConfigOptions.java index 05a0d2b9..8076aa6f 100644 --- a/api/src/main/java/com/dsh105/echopet/compat/api/config/ConfigOptions.java +++ b/api/src/main/java/com/dsh105/echopet/compat/api/config/ConfigOptions.java @@ -156,8 +156,8 @@ public void setDefaults() { int friendlySlot = icon.getSlot() + 1; set("petSelector.menu.slot-" + friendlySlot + ".command", icon.getCommand()); set("petSelector.menu.slot-" + friendlySlot + ".petType", icon.getPetType() == null ? "" : icon.getPetType().toString()); - set("petSelector.menu.slot-" + friendlySlot + ".materialId", icon.getType().getId()); - set("petSelector.menu.slot-" + friendlySlot + ".materialData", icon.getMaterialData().getData()); + // NOTE: Temporarily upgraded from old system + set("petSelector.menu.slot-" + friendlySlot + ".material", MaterialSystem.getInstance().serializeData(icon.getItemData())); set("petSelector.menu.slot-" + friendlySlot + ".name", (icon.getName() == null ? "" : icon.getName()).replace(ChatColor.COLOR_CHAR, '&')); ArrayList lore = new ArrayList(); for (String s : icon.getLore()) { diff --git a/api/src/main/java/com/dsh105/echopet/compat/api/util/inventory/MenuIcon.java b/api/src/main/java/com/dsh105/echopet/compat/api/util/inventory/MenuIcon.java index 1211bc19..db97e518 100644 --- a/api/src/main/java/com/dsh105/echopet/compat/api/util/inventory/MenuIcon.java +++ b/api/src/main/java/com/dsh105/echopet/compat/api/util/inventory/MenuIcon.java @@ -49,11 +49,7 @@ public int getSlot() { } public Material getType() { - return getMaterialData().getItemType(); - } - - public MaterialData getMaterialData() { - return itemData.getMaterialData(); + return itemData.getType(); } public String getName() { diff --git a/api/src/main/java/com/dsh105/echopet/compat/api/util/menu/SelectorItem.java b/api/src/main/java/com/dsh105/echopet/compat/api/util/menu/SelectorItem.java index 8f0c1204..554f5c33 100644 --- a/api/src/main/java/com/dsh105/echopet/compat/api/util/menu/SelectorItem.java +++ b/api/src/main/java/com/dsh105/echopet/compat/api/util/menu/SelectorItem.java @@ -64,17 +64,13 @@ public String getCommand() { } public Material getType() { - return getMaterialData().getItemType(); + return getItemData().getType(); } public int getAmount() { return amount; } - public MaterialData getMaterialData() { - return getItemData().getMaterialData(); - } - public String getName() { return getItemData().getDisplayName().get(); } diff --git a/api/src/main/java/com/dsh105/echopet/compat/api/util/menu/SelectorLayout.java b/api/src/main/java/com/dsh105/echopet/compat/api/util/menu/SelectorLayout.java index 32232990..814de77a 100644 --- a/api/src/main/java/com/dsh105/echopet/compat/api/util/menu/SelectorLayout.java +++ b/api/src/main/java/com/dsh105/echopet/compat/api/util/menu/SelectorLayout.java @@ -22,8 +22,7 @@ import com.dsh105.echopet.compat.api.config.ConfigOptions; import com.dsh105.echopet.compat.api.config.PetItem; import com.dsh105.echopet.compat.api.entity.PetType; -import com.google.common.collect.ImmutableList; - +import net.techcable.sonarpet.item.ItemData; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.event.HandlerList; @@ -35,8 +34,6 @@ import java.util.List; import java.util.Optional; -import net.techcable.sonarpet.item.ItemData; - public class SelectorLayout { private static ArrayList selectorLayout = new ArrayList(); @@ -83,6 +80,14 @@ public static void loadLayout() { if (petType != null && GeneralUtil.isEnumType(PetType.class, petType.toUpperCase())) { pt = PetType.valueOf(petType.toUpperCase()); } + String serializedData = config.getInt(); + if (serializedData != null) { + /* + * Always prefer using the new system of serialization. + * It will gracefully ends our dependence on material ids + * once we update to 1.13 + */ + } int id = config.getInt(s + ".slot-" + i + ".materialId"); int data = config.getInt(s + ".slot-" + i + ".materialData"); String name = config.getString(s + ".slot-" + i + ".name"); @@ -99,8 +104,7 @@ public static void loadLayout() { loreList.add(ChatColor.translateAlternateColorCodes('&', part)); } } - Material type = Material.getMaterial(id); - selectorLayout.add(new SelectorIcon(i - 1, cmd, pt, ItemData.create(type, data).withDisplayName(name.trim().isEmpty() ? Optional.empty() : Optional.of(name)).withLore(loreList))); + selectorLayout.add(new SelectorIcon(i - 1, cmd, pt, basicData.withDisplayName(name.trim().isEmpty() ? Optional.empty() : Optional.of(name)).withLore(loreList))); } selectorMenu = new SelectorMenu(); diff --git a/api/src/main/java/net/techcable/sonarpet/SafeSound.java b/api/src/main/java/net/techcable/sonarpet/SafeSound.java index de46610f..2d0522ea 100644 --- a/api/src/main/java/net/techcable/sonarpet/SafeSound.java +++ b/api/src/main/java/net/techcable/sonarpet/SafeSound.java @@ -9,7 +9,10 @@ /** * A version independent enumeration of sounds. + * + * @deprecated Legacy 1.8.8 compat */ +@Deprecated public enum SafeSound { BLAZE_AMBIENT("ENTITY_BLAZE_AMBIENT", "BLAZE_BREATH"), BLAZE_DEATH("ENTITY_BLAZE_DEATH", "BLAZE_DEATH"), diff --git a/api/src/main/java/net/techcable/sonarpet/block/BlockData.java b/api/src/main/java/net/techcable/sonarpet/block/BlockData.java new file mode 100644 index 00000000..12ee0bfa --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/block/BlockData.java @@ -0,0 +1,36 @@ +package net.techcable.sonarpet.block; + +import org.bukkit.Material; + +/** + * A facade around the modern `BlockData` interface, + * in order to ensure backwards compatibility. + */ +public interface BlockData { + Material getMaterial(); + String getAsString(); + static BlockData createBlockData(Material m) { + return BlockDataFactory.getInstance().createBlockData(m); + } + static BlockData parseBlockData(String s) { + return BlockDataFactory.getInstance().parseBlockData(s); + } + + /** + * Parse the sepcified block data 'leniently', + * making a decent attempt to convert from legacy data. + * + * @param s the data to parse + * @throws IllegalArgumentException if the data is invalid + * @return the resulting block data + */ + static BlockData parseLeniently(String s) { + return BlockDataFactory.getInstance().parseLeniently(s); + } + static BlockData fromLegacyData(String materialName, byte data) { + return BlockDataFactory.getInstance().fromLegacyData(materialName, data); + } + static BlockData fromLegacyData(Material m, byte data) { + return BlockDataFactory.getInstance().fromLegacyData(m, data); + } +} diff --git a/api/src/main/java/net/techcable/sonarpet/block/BlockDataFactory.java b/api/src/main/java/net/techcable/sonarpet/block/BlockDataFactory.java new file mode 100644 index 00000000..ab76418d --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/block/BlockDataFactory.java @@ -0,0 +1,23 @@ +package net.techcable.sonarpet.block; + +import net.techcable.sonarpet.utils.NmsVersion; +import org.bukkit.Material; +import org.bukkit.block.BlockState; + +public interface BlockDataFactory { + BlockData createBlockData(Material m); + BlockData createBlockData(Material m, String data); + BlockData parseBlockData(String s); + + static BlockDataFactory getInstance() { + if (NmsVersion.current().isAtLeast(NmsVersion.v1_13_R2)) { + return new ModernBlockDataFactory(); + } else { + return new LegacyBlockDataFactory(); + } + } + BlockData parseLeniently(String s); + BlockData fromLegacyData(int id, byte data); + BlockData fromLegacyData(String materialName, byte data); + BlockData fromLegacyData(Material m, byte data); +} diff --git a/api/src/main/java/net/techcable/sonarpet/block/LegacyBlockData.java b/api/src/main/java/net/techcable/sonarpet/block/LegacyBlockData.java new file mode 100644 index 00000000..e580dd98 --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/block/LegacyBlockData.java @@ -0,0 +1,21 @@ +package net.techcable.sonarpet.block; + +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import org.bukkit.Material; +import org.bukkit.material.MaterialData; + +@RequiredArgsConstructor(access = AccessLevel.PACKAGE) +public class LegacyBlockData implements BlockData { + private final MaterialData materialData; + + @Override + public Material getMaterial() { + return materialData.getItemType(); + } + + @Override + public String getAsString() { + return "legacy[" + materialData.getItemType().name() + ":" + materialData.getData() + "]"; + } +} diff --git a/api/src/main/java/net/techcable/sonarpet/block/LegacyBlockDataFactory.java b/api/src/main/java/net/techcable/sonarpet/block/LegacyBlockDataFactory.java new file mode 100644 index 00000000..98c1ce92 --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/block/LegacyBlockDataFactory.java @@ -0,0 +1,112 @@ +package net.techcable.sonarpet.block; + +import com.google.common.base.Preconditions; +import lombok.SneakyThrows; +import net.techcable.pineapple.reflection.Reflection; +import net.techcable.sonarpet.utils.NmsVersion; +import org.bukkit.Material; +import org.bukkit.Server; +import org.bukkit.block.BlockState; +import org.bukkit.material.MaterialData; + +import javax.annotation.Nullable; +import java.lang.invoke.MethodHandle; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class LegacyBlockDataFactory implements BlockDataFactory { + /* package */ LegacyBlockDataFactory() { + NmsVersion.ensureBefore(NmsVersion.v1_13_R2); + } + + @Override + public BlockData createBlockData(Material m) { + return new LegacyBlockData(m.getNewData((byte) 0)); + } + + @Override + public BlockData createBlockData(Material m, String data) { + Preconditions.checkNotNull(m, "Null material"); + Preconditions.checkNotNull(data, "Null data"); + ParsedLegacyData parsed = parseLegacyData(data); + Preconditions.checkArgument( + parsed.getType() == m, + "Expected type %s for data %s", + m, data + ); + return new LegacyBlockData(parsed.toLegacyMaterialData()); + } + + @Override + public BlockData parseBlockData(String s) { + return new LegacyBlockData(parseLegacyData(s).toLegacyMaterialData()); + } + + @Override + public BlockData fromState(BlockState state) { + return new LegacyBlockData(state.getData()); + } + + @Override + public BlockData parseLeniently(String s) { + // we do **not* handle data from future versions, so nothing special to do + return parseBlockData(s); + } + + @Override + public BlockData fromLegacyData(int id, byte data) { + Material material = Material.getMaterial(id); + if (material == null) { + throw new IllegalArgumentException("Invalid material id: " + id); + } + return fromLegacyData(material, data); + } + + @Override + public BlockData fromLegacyData(String materialName, byte data) { + Material material = Material.getMaterial(materialName); + if (material == null) { + throw new IllegalArgumentException("Invalid material name: " + materialName); + } + return fromLegacyData(material, data); + } + + @Override + public BlockData fromLegacyData(Material m, byte data) { + return new LegacyBlockData(m.getNewData(data)); + } + + private static final Pattern LEGACY_DATA_PATTERN = Pattern + .compile("legacy\\[(\\w+)(?::(\\d+))?]"); + public static boolean isLegacyData(String data) { + return LEGACY_DATA_PATTERN.matcher(data).matches(); + } + public static ParsedLegacyData parseLegacyData(String data) { + Preconditions.checkNotNull(data, "Null data"); + Matcher matcher = LEGACY_DATA_PATTERN.matcher(data); + String materialName = matcher.group(1); + Material material = Material.getMaterial(materialName); + if (material == null) { + throw new IllegalArgumentException( + "Invalid material " + materialName + + " for legacy data: " + data + ); + } + String legacyDataStr = matcher.group(2); + final byte legacyData; + if (legacyDataStr != null) { + try { + legacyData = Byte.parseByte(legacyDataStr); + } catch (NumberFormatException e) { + throw new IllegalArgumentException( + "Invalid legacyData " + legacyDataStr + + " for legeacy data: " + data, + e + ); + } + } else { + legacyData = 0; + } + return new ParsedLegacyData(material, legacyData); + } +} diff --git a/api/src/main/java/net/techcable/sonarpet/block/ModernBlockData.java b/api/src/main/java/net/techcable/sonarpet/block/ModernBlockData.java new file mode 100644 index 00000000..23a8a0d0 --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/block/ModernBlockData.java @@ -0,0 +1,42 @@ +package net.techcable.sonarpet.block; + +import com.google.common.base.Preconditions; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import net.techcable.pineapple.reflection.Reflection; +import org.bukkit.Material; + +import java.lang.invoke.MethodHandle; +import java.util.Objects; + +public final class ModernBlockData implements BlockData { + private final Object handle; + /* package */ ModernBlockData(Object handle) { + Preconditions.checkNotNull(handle); + this.handle = BLOCK_DATA_CLASS.cast(handle); + } + + @Override + @SneakyThrows + public Material getMaterial() { + return (Material) GET_MATERIAL.invoke(handle); + } + + @Override + @SneakyThrows + public String getAsString() { + return (String) GET_AS_STRING.invoke(this.handle); + } + + private static final Class BLOCK_DATA_CLASS = Objects.requireNonNull( + Reflection.getClass("org.bukkit.block.data.BlockData")); + private static final MethodHandle GET_MATERIAL = Reflection.getMethod( + BLOCK_DATA_CLASS, + "getMaterial" + ); + private static final MethodHandle GET_AS_STRING = Reflection.getMethod( + BLOCK_DATA_CLASS, + "getString" + ); +} diff --git a/api/src/main/java/net/techcable/sonarpet/block/ModernBlockDataFactory.java b/api/src/main/java/net/techcable/sonarpet/block/ModernBlockDataFactory.java new file mode 100644 index 00000000..2fc2c551 --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/block/ModernBlockDataFactory.java @@ -0,0 +1,98 @@ +package net.techcable.sonarpet.block; + +import lombok.SneakyThrows; +import net.techcable.pineapple.reflection.Reflection; +import net.techcable.sonarpet.nms.IModernNMS; +import net.techcable.sonarpet.nms.INMS; +import net.techcable.sonarpet.utils.NmsVersion; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Server; +import org.bukkit.block.BlockState; + +import java.lang.invoke.MethodHandle; + +public class ModernBlockDataFactory implements BlockDataFactory { + /* package */ ModernBlockDataFactory() { + NmsVersion.ensureAtLeast(NmsVersion.v1_13_R2); + } + + @Override + @SneakyThrows + public BlockData createBlockData(Material m) { + return new ModernBlockData(CREATE_BLOCK_DATA_MATERIAL.invoke(m)); + } + + @Override + @SneakyThrows + public BlockData createBlockData(Material m, String data) { + return new ModernBlockData(CREATE_BLOCK_DATA_MATERIAL_STRING.invoke(m, data)); + } + + @Override + @SneakyThrows + public BlockData parseBlockData(String s) { + return new ModernBlockData(CREATE_BLOCK_DATA_STRING.invoke(s)); + } + + + @Override + @SneakyThrows + public BlockData fromState(BlockState state) { + return new ModernBlockData(BLOCK_STATE_GET_DATA.invoke(state)); + } + + @Override + public BlockData parseLeniently(String s) { + if (LegacyBlockDataFactory.isLegacyData(s)) { + ParsedLegacyData parsed = LegacyBlockDataFactory.parseLegacyData(s); + return fromLegacyData(parsed.getType(), parsed.getData()); + } else { + return parseBlockData(s); + } + } + + @Override + public BlockData fromLegacyData(int id, byte data) { + Material m = IModernNMS.getInstance().getMaterialByLegacyId(id); + return fromLegacyData(m, data); + } + + @Override + public BlockData fromLegacyData(String materialName, byte data) { + Material m = Material.getMaterial("LEGACY_" + materialName); + if (m == null) { + throw new IllegalArgumentException("Invalid material name: " + materialName); + } + return fromLegacyData(m, data); + } + + @Override + public BlockData fromLegacyData(Material m, byte data) { + return new ModernBlockData(IModernNMS.getInstance().getBukkitBlockData(m, data)); + } + + private static final MethodHandle CREATE_BLOCK_DATA_STRING = Reflection.getMethod( + Server.class, + "createBlockData", + String.class + ); + + private static final MethodHandle CREATE_BLOCK_DATA_MATERIAL = Reflection.getMethod( + Server.class, + "createBlockData", + Material.class + ); + + private static final MethodHandle CREATE_BLOCK_DATA_MATERIAL_STRING = Reflection.getMethod( + Server.class, + "createBlockData", + Material.class, + String.class + ); + + private static final MethodHandle BLOCK_STATE_GET_DATA = Reflection.getMethod( + BlockState.class, + "getBlockData" + ); +} diff --git a/api/src/main/java/net/techcable/sonarpet/block/ParsedLegacyData.java b/api/src/main/java/net/techcable/sonarpet/block/ParsedLegacyData.java new file mode 100644 index 00000000..e7cafa73 --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/block/ParsedLegacyData.java @@ -0,0 +1,19 @@ +package net.techcable.sonarpet.block; + +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import org.bukkit.Material; +import org.bukkit.material.MaterialData; + +@RequiredArgsConstructor +@Getter +/* package */ class ParsedLegacyData { + @NonNull + private final Material type; + private final byte data; + + public MaterialData toLegacyMaterialData() { + return type.getNewData(this.data); + } +} diff --git a/api/src/main/java/net/techcable/sonarpet/item/DyeItemData.java b/api/src/main/java/net/techcable/sonarpet/item/DyeItemData.java index 872639c5..dd7e6323 100644 --- a/api/src/main/java/net/techcable/sonarpet/item/DyeItemData.java +++ b/api/src/main/java/net/techcable/sonarpet/item/DyeItemData.java @@ -7,31 +7,16 @@ import org.bukkit.Material; import org.bukkit.inventory.meta.ItemMeta; -public class DyeItemData extends ItemData implements ColoredItemData { +public interface DyeItemData extends ItemData, ColoredItemData { + DyeColor getColor(); - protected DyeItemData(byte rawData, ItemMeta meta) { - super(Material.INK_SACK, rawData, meta); - } - - @SuppressWarnings("deprecation") - public DyeColor getColor() { - return DyeColor.getByDyeData(getRawData()); - } - - @SuppressWarnings("deprecation") - public DyeItemData withColor(DyeColor color) { - return withRawData(Preconditions.checkNotNull(color, "Null color").getDyeData()); - } - - public DyeItemData withRawData(int rawData) { - return (DyeItemData) super.withRawData(rawData); - } + DyeItemData withColor(DyeColor color); - public static DyeItemData create(DyeColor color) { + static DyeItemData create(DyeColor color) { return create(color, Bukkit.getItemFactory().getItemMeta(Material.INK_SACK)); } - public static DyeItemData create(DyeColor color, ItemMeta meta) { - return new DyeItemData(Preconditions.checkNotNull(color, "Null color").getDyeData(), meta); + static DyeItemData create(DyeColor color, ItemMeta meta) { + return ItemDataFactory.getInstance().createDye(color, meta); } } diff --git a/api/src/main/java/net/techcable/sonarpet/item/ItemData.java b/api/src/main/java/net/techcable/sonarpet/item/ItemData.java index 98898ada..11d06105 100644 --- a/api/src/main/java/net/techcable/sonarpet/item/ItemData.java +++ b/api/src/main/java/net/techcable/sonarpet/item/ItemData.java @@ -1,149 +1,77 @@ package net.techcable.sonarpet.item; -import lombok.*; - -import java.util.List; -import java.util.Optional; - -import net.techcable.sonarpet.nms.INMS; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; - +import net.techcable.sonarpet.block.BlockData; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.material.MaterialData; - -@Getter -public class ItemData { - @NonNull - private final Material type; - private final byte rawData; - @Getter(AccessLevel.NONE) // Doesn't make a defensive copy, which is nessicary as it is mutable - private final ItemMeta meta; - - protected ItemData(Material type, byte rawData, ItemMeta meta) { - this.type = Preconditions.checkNotNull(type, "Null type"); - this.rawData = rawData; - Preconditions.checkNotNull(meta, "Null metadata"); - this.meta = Bukkit.getItemFactory().asMetaFor(meta, type).clone(); // Not guarnteed to copy ;) - } - - public static ItemData create(MaterialData materialData) { - Preconditions.checkNotNull(materialData, "Null material data"); - return create(materialData.getItemType(), materialData.getData()); - } - - - public static ItemData create(MaterialData materialData, ItemMeta meta) { - Preconditions.checkNotNull(materialData, "Null material data"); - return create(materialData.getItemType(), materialData.getData(), meta); - } - - public static ItemData create(Material type) { - return create(type, 0); - } - - public static ItemData create(Material type, ItemMeta meta) { - return create(type, 0, meta); - } - public static ItemData create(Material type, int rawData) { - Preconditions.checkNotNull(type, "Null type"); - return create(type, rawData, Bukkit.getItemFactory().getItemMeta(type)); - } - - public static ItemData create(Material type, int rawData, ItemMeta meta) { - Preconditions.checkNotNull(type, "Null type"); - Preconditions.checkArgument((byte) rawData == rawData, "Raw data doesn't fit in byte: %s", rawData); - Preconditions.checkNotNull(meta, "Null item meta"); - switch (type) { - case INK_SACK: - return new DyeItemData((byte) rawData, meta); - case SKULL_ITEM: - return new SkullItemData((byte) rawData, meta); - case MONSTER_EGG: - return INMS.getInstance().createSpawnEggData((byte) rawData, meta); - case STAINED_CLAY: - return new StainedClayItemData((byte) rawData, meta); - case WOOL: - return new StainedClayItemData((byte) rawData, meta); - default: - return new ItemData(type, (byte) rawData, meta); - } - } - - public MaterialData getMaterialData() { - return type.getNewData(rawData); - } +import javax.annotation.Nullable; +import java.util.List; +import java.util.Optional; - public ItemData withType(Material type) { - Preconditions.checkNotNull(type, "Null material"); - return withMaterialData(new MaterialData(type, getRawData())); - } +public interface ItemData { + Material getType(); + ItemMeta getMeta(); + /** + * Serialize this ItemData into a string, + * which can be deserialized by {@link ItemDataFactory#parseFromString(String)}. + * + * This is not guarenteed to preserve all the items properties + * and is only 'best-effort'. + * + * @return the serialized string + */ + String serializeAsString(); - public ItemData withRawData(int rawData) { - Preconditions.checkArgument((byte) rawData == rawData, "Raw data doesn't fit into byte: %s", rawData); - return withMaterialData(new MaterialData(getType(), (byte) rawData)); - } + ItemDataFactory getFactory(); - public ItemData withMaterialData(MaterialData data) { - Preconditions.checkNotNull(data, "Material data"); - return this.withType(data.getItemType()).withRawData(data.getData()); + static ItemData create(Material type) { + return create(type, Bukkit.getItemFactory().getItemMeta(type)); } - public ItemData withMeta(ItemMeta meta) { - Preconditions.checkNotNull(meta, "Null metadata"); - return meta.equals(this.meta) ? this : create(getType(), getRawData(), meta); + static ItemData create(Material type, ItemMeta meta) { + return ItemDataFactory.getInstance().create(type, meta); } - public ItemData withPlainMeta() { - return create(getType(), getRawData()); - } + ItemData withMeta(ItemMeta meta); - public ItemMeta getMeta() { - return meta.clone(); - } + ItemData withPlainMeta(); - public ImmutableList getLore() { - if (meta.hasLore()) { - return ImmutableList.copyOf(meta.getLore()); + default ImmutableList getLore() { + if (getMeta().hasLore()) { + return ImmutableList.copyOf(getMeta().getLore()); } else { return ImmutableList.of(); } } - public Optional getDisplayName() { - return meta.hasDisplayName() ? Optional.of(meta.getDisplayName()) : Optional.empty(); + default Optional getDisplayName() { + return getMeta().hasDisplayName() ? Optional.of(getMeta().getDisplayName()) : Optional.empty(); } - public ItemData withDisplayName(Optional name) { - Preconditions.checkNotNull(name, "Null optional"); + default ItemData withDisplayName(@Nullable String name) { ItemMeta meta = getMeta(); // Returns a copy ;) - if (name.isPresent()) { - Preconditions.checkArgument(!name.get().trim().isEmpty(), "Empty name '%s'", name.get()); - meta.setDisplayName(name.get()); + if (name != null) { + Preconditions.checkArgument(!name.trim().isEmpty(), "Empty name '%s'", name); + meta.setDisplayName(name); } else { meta.setDisplayName(null); // Undocumented behavior of awesomeness } return withMeta(meta); } - public ItemData withDisplayName(String name) { - return withDisplayName(Optional.of(Preconditions.checkNotNull(name, "Null name"))); - } - - public ItemData withLore(List lore) { + default ItemData withLore(List lore) { ItemMeta meta = getMeta(); // Returns a copy ;) meta.setLore(ImmutableList.copyOf(lore)); // Copy lore :D return withMeta(meta); } - public ItemStack createStack(int amount) { - ItemStack stack = new ItemStack(getType(), amount, getRawData()); - stack.setItemMeta(this.meta.clone()); - return stack; - } + ItemStack createStack(int amount); + + @Nullable + BlockData getBlockData(); } diff --git a/api/src/main/java/net/techcable/sonarpet/item/ItemDataFactory.java b/api/src/main/java/net/techcable/sonarpet/item/ItemDataFactory.java new file mode 100644 index 00000000..a2e4611f --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/item/ItemDataFactory.java @@ -0,0 +1,36 @@ +package net.techcable.sonarpet.item; + +import net.techcable.sonarpet.nms.INMS; +import net.techcable.sonarpet.utils.ModernSpawnEggs; +import net.techcable.sonarpet.utils.PlayerProfile; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.EntityType; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.material.SpawnEgg; + +public interface ItemDataFactory { + ItemData create(Material type, ItemMeta meta); + + DyeItemData createDye(DyeColor color, ItemMeta meta); + StainedClayItemData createStainedClay(DyeColor color, ItemMeta meta); + WoolItemData createWool(DyeColor color, ItemMeta meta); + + /** + * Parse an `ItemData` from its serialized string form. + * This is the deserializer counterpart to {@link ItemData#serializeAsString()} + * + * @param s the serialized string to parse + * @throws IllegalArgumentException if the data is invalid + * @return the deserialized data + */ + ItemData parseFromString(String s); + + static ItemDataFactory getInstance() { + return INMS.getInstance().getItemDataFactory(); + } + + SkullItemData createHumanSkull(PlayerProfile owner, ItemMeta rawData); + SkullItemData createSkull(SkullItemData.SkullType skullType, ItemMeta rawData); + SpawnEggItemData createSpawnEggData(EntityType entityType, ItemMeta meta); +} diff --git a/api/src/main/java/net/techcable/sonarpet/item/SkullItemData.java b/api/src/main/java/net/techcable/sonarpet/item/SkullItemData.java index 85a621ff..398909ce 100644 --- a/api/src/main/java/net/techcable/sonarpet/item/SkullItemData.java +++ b/api/src/main/java/net/techcable/sonarpet/item/SkullItemData.java @@ -13,119 +13,50 @@ import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.SkullMeta; -public class SkullItemData extends ItemData { - private final PlayerProfile profile; - - public Optional getProfile() { - if (getSkullType() == SkullType.HUMAN_SKULL && getMeta().hasOwner()) { - String ownerName = getMeta().getOwner(); - Preconditions.checkState(profile.getName().equals(ownerName), "Profile %s doesn't match owner %s", profile, ownerName); - return Optional.of(profile); - } else { - Preconditions.checkState(profile == null, "Profile %s is present but meta has no owner", profile); - return Optional.empty(); - } - } +public interface SkullItemData extends ItemData { + Optional getProfile(); + SkullItemData withOwner(UUID owner); - protected SkullItemData(byte rawData, ItemMeta meta) { - this(rawData, meta, ((SkullMeta) meta).hasOwner() ? ProfileUtils.lookupOptimistically(((SkullMeta) meta).getOwner()) : null); - } + SkullItemData withOwner(String ownerName); - protected SkullItemData(byte rawData, ItemMeta meta, PlayerProfile profile) { - super(Material.SKULL_ITEM, rawData, meta); - Preconditions.checkArgument(profile == null || profile.getName().equals(((SkullMeta) meta).getOwner())); - this.profile = profile; - } + SkullItemData withOwner(PlayerProfile profile); - public SkullItemData withOwner(UUID owner) { - Preconditions.checkNotNull(owner, "Null owner uuid"); - if (getProfile().isPresent() && getProfile().get().getId().equals(owner)) { - return this; - } else { - return withOwner(ProfileUtils.lookupOptimistically(owner)); - } - } + Optional getOwner(); - public SkullItemData withOwner(String ownerName) { - Preconditions.checkNotNull(ownerName, "Null owner name"); - if (getProfile().isPresent() && getProfile().get().getName().equals(ownerName)) { - return this; - } else { - return withOwner(ProfileUtils.lookupOptimistically(ownerName)); - } - } + Optional getOwnerName(); - public SkullItemData withOwner(PlayerProfile profile) { - return profile.equals(this.profile) ? this : createHuman(profile, this.getMeta()); - } - - public Optional getOwner() { - return getProfile().map(PlayerProfile::getId); - } + boolean hasOwner(); - - public Optional getOwnerName() { - return getProfile().map(PlayerProfile::getName); - } - - public boolean hasOwner() { - return getProfile().isPresent(); - } - - public static SkullItemData createHuman() { + static SkullItemData createHuman() { return create(SkullType.HUMAN_SKULL); } - public static SkullItemData createHuman(PlayerProfile owner) { + static SkullItemData createHuman(PlayerProfile owner) { return createHuman(owner, Bukkit.getItemFactory().getItemMeta(Material.SKULL_ITEM)); } - public static SkullItemData createHuman(PlayerProfile owner, ItemMeta rawMeta) { - Preconditions.checkNotNull(rawMeta, "Null meta"); - Preconditions.checkNotNull(owner, "Null owner"); - SkullMeta meta; - if (rawMeta instanceof SkullMeta) { - meta = (SkullMeta) rawMeta; - } else { - meta = (SkullMeta) Bukkit.getItemFactory().asMetaFor(rawMeta, Material.SKULL_ITEM); - } - meta = meta.clone(); // Don't modify their junk - meta.setOwner(owner.getName()); - return create(SkullType.HUMAN_SKULL, meta); + static SkullItemData createHuman(PlayerProfile owner, ItemMeta rawMeta) { + return ItemDataFactory.getInstance().createHumanSkull(owner, rawMeta); } - public static SkullItemData create(SkullType type) { + static SkullItemData create(SkullType type) { return create(type, Bukkit.getItemFactory().getItemMeta(Material.SKULL_ITEM)); } - public static SkullItemData create(SkullType type, ItemMeta meta) { - return new SkullItemData(Preconditions.checkNotNull(type, "Null skull type").getId(), Preconditions.checkNotNull(meta, "Null meta")); + static SkullItemData create(SkullType type, ItemMeta meta) { + return ItemDataFactory.getInstance().createSkull(type, meta); } - public SkullType getSkullType() { - int data = getRawData(); - SkullType[] values = SkullType.values(); - if (data < 0) { - throw new IllegalStateException("Can't get skull type from negative data: " + data); - } else if (data >= values.length) { - throw new IllegalStateException("Can't get skull type from too large data: " + data); - } else { - return values[data]; - } - } + SkullType getSkullType(); - public ItemData withSkullType(SkullType type) { - return withRawData(Preconditions.checkNotNull(type, "Null type").ordinal()); - } + ItemData withSkullType(SkullType type); @Override - public SkullMeta getMeta() { - return (SkullMeta) super.getMeta(); - } + SkullMeta getMeta(); - public enum SkullType { + enum SkullType { SKELETON_SKULL, WITHER_SKELETON_SKULL, ZOMBIE_SKULL, diff --git a/api/src/main/java/net/techcable/sonarpet/item/SpawnEggItemData.java b/api/src/main/java/net/techcable/sonarpet/item/SpawnEggItemData.java index 76ea0744..432eb3f0 100644 --- a/api/src/main/java/net/techcable/sonarpet/item/SpawnEggItemData.java +++ b/api/src/main/java/net/techcable/sonarpet/item/SpawnEggItemData.java @@ -1,33 +1,27 @@ package net.techcable.sonarpet.item; -import net.techcable.sonarpet.nms.INMS; import com.google.common.base.Preconditions; - import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.EntityType; import org.bukkit.inventory.meta.ItemMeta; -public abstract class SpawnEggItemData extends ItemData { - - public static final EntityType DEFAULT_TYPE = EntityType.PIG; +public interface SpawnEggItemData extends ItemData { - protected SpawnEggItemData(byte rawData, ItemMeta meta) { - super(Material.MONSTER_EGG, rawData, meta); - } + EntityType DEFAULT_TYPE = EntityType.PIG; - public SpawnEggItemData withSpawnedType(EntityType entityType) { + default SpawnEggItemData withSpawnedType(EntityType entityType) { Preconditions.checkNotNull(entityType, "Null type"); return getSpawnedType() == entityType ? this : create(entityType, getMeta()); } - public abstract EntityType getSpawnedType(); + EntityType getSpawnedType(); - public static SpawnEggItemData create(EntityType entityType) { + static SpawnEggItemData create(EntityType entityType) { return create(entityType, Bukkit.getItemFactory().getItemMeta(Material.MONSTER_EGG)); } - public static SpawnEggItemData create(EntityType entityType, ItemMeta meta) { - return INMS.getInstance().createSpawnEggData(entityType, meta); + static SpawnEggItemData create(EntityType entityType, ItemMeta meta) { + return ItemDataFactory.getInstance().createSpawnEggData(entityType, meta); } } diff --git a/api/src/main/java/net/techcable/sonarpet/item/StainedClayItemData.java b/api/src/main/java/net/techcable/sonarpet/item/StainedClayItemData.java index f60276c6..a8ef60c6 100644 --- a/api/src/main/java/net/techcable/sonarpet/item/StainedClayItemData.java +++ b/api/src/main/java/net/techcable/sonarpet/item/StainedClayItemData.java @@ -1,37 +1,21 @@ package net.techcable.sonarpet.item; -import com.google.common.base.Preconditions; - import org.bukkit.Bukkit; import org.bukkit.DyeColor; import org.bukkit.Material; import org.bukkit.inventory.meta.ItemMeta; -public class StainedClayItemData extends ItemData implements ColoredItemData { - - protected StainedClayItemData(byte rawData, ItemMeta meta) { - super(Material.STAINED_CLAY, rawData, meta); - } +public interface StainedClayItemData extends ItemData, ColoredItemData { - @SuppressWarnings("deprecation") - public DyeColor getColor() { - return DyeColor.getByWoolData(getRawData()); - } + DyeColor getColor(); - @SuppressWarnings("deprecation") - public StainedClayItemData withColor(DyeColor color) { - return withRawData(Preconditions.checkNotNull(color, "Null color").getWoolData()); - } - - public StainedClayItemData withRawData(int rawData) { - return (StainedClayItemData) super.withRawData(rawData); - } + StainedClayItemData withColor(DyeColor color); - public static StainedClayItemData create(DyeColor color) { + static StainedClayItemData create(DyeColor color) { return create(color, Bukkit.getItemFactory().getItemMeta(Material.STAINED_CLAY)); } - public static StainedClayItemData create(DyeColor color, ItemMeta meta) { - return new StainedClayItemData(Preconditions.checkNotNull(color, "Null color").getWoolData(), meta); + static StainedClayItemData create(DyeColor color, ItemMeta meta) { + return ItemDataFactory.getInstance().createStainedClay(color, meta); } } diff --git a/api/src/main/java/net/techcable/sonarpet/item/WoolItemData.java b/api/src/main/java/net/techcable/sonarpet/item/WoolItemData.java index cf778c71..c283c9bd 100644 --- a/api/src/main/java/net/techcable/sonarpet/item/WoolItemData.java +++ b/api/src/main/java/net/techcable/sonarpet/item/WoolItemData.java @@ -1,38 +1,21 @@ package net.techcable.sonarpet.item; -import com.google.common.base.Preconditions; - import org.bukkit.Bukkit; import org.bukkit.DyeColor; import org.bukkit.Material; -import org.bukkit.entity.Wolf; import org.bukkit.inventory.meta.ItemMeta; -public class WoolItemData extends ItemData implements ColoredItemData { - - protected WoolItemData(byte rawData, ItemMeta meta) { - super(Material.WOOL, rawData, meta); - } +public interface WoolItemData extends ItemData, ColoredItemData { - @SuppressWarnings("deprecation") - public DyeColor getColor() { - return DyeColor.getByWoolData(getRawData()); - } + DyeColor getColor(); - @SuppressWarnings("deprecation") - public WoolItemData withColor(DyeColor color) { - return withRawData(Preconditions.checkNotNull(color, "Null color").getWoolData()); - } - - public WoolItemData withRawData(int rawData) { - return (WoolItemData) super.withRawData(rawData); - } + WoolItemData withColor(DyeColor color); - public static WoolItemData create(DyeColor color) { + static WoolItemData create(DyeColor color) { return create(color, Bukkit.getItemFactory().getItemMeta(Material.WOOL)); } - public static WoolItemData create(DyeColor color, ItemMeta meta) { - return new WoolItemData(Preconditions.checkNotNull(color, "Null color").getWoolData(), meta); + static WoolItemData create(DyeColor color, ItemMeta meta) { + return ItemDataFactory.getInstance().createWool(color, meta); } } diff --git a/api/src/main/java/net/techcable/sonarpet/item/legacy/BasicSerializedItem.java b/api/src/main/java/net/techcable/sonarpet/item/legacy/BasicSerializedItem.java new file mode 100644 index 00000000..4a45e4c4 --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/item/legacy/BasicSerializedItem.java @@ -0,0 +1,65 @@ +package net.techcable.sonarpet.item.legacy; + +import com.google.common.collect.ImmutableList; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import org.bukkit.Material; + +import javax.annotation.Nullable; + +@RequiredArgsConstructor(access = AccessLevel.PACKAGE) +@Getter +public class BasicSerializedItem { + @NonNull + private final Material type; + private final byte rawData; + private final ImmutableList lore; + @Nullable + private final String displayName; + + private JsonObject serialize() { + JsonObject result = new JsonObject(); + result.addProperty("type", this.type.name()); + result.addProperty("rawData", this.rawData); + if (!this.lore.isEmpty()) { + JsonArray lore = new JsonArray(); + for (String element : this.lore) { + lore.add(element); + } + result.add("lore", lore); + } + if (this.displayName != null) { + result.addProperty("displayName", this.displayName); + } + return result; + } + public String serializeAsString() { + return "legacy(" + this.serialize() + ")"; + } + public static boolean isLegacyItem(String s) { + return s.startsWith("legacy("); + } + + public static BasicSerializedItem deserializeFromString(String s) { + if (s.startsWith("legacy(") && s.endsWith(")")) { + String inner = s.substring("legacy(".length(), s.length() - 1); + try { + return new Gson().fromJson(inner, BasicSerializedItem.class); + } catch (JsonSyntaxException e) { + throw new IllegalArgumentException( + "Invalid legacy item: " + s, + e + ); + } + } else { + throw new IllegalArgumentException("Not a legacy item: " + s); + } + + } +} diff --git a/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacyDyeItemData.java b/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacyDyeItemData.java new file mode 100644 index 00000000..98b96aec --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacyDyeItemData.java @@ -0,0 +1,32 @@ +package net.techcable.sonarpet.item.legacy; + +import com.google.common.base.Preconditions; +import net.techcable.sonarpet.item.ColoredItemData; +import net.techcable.sonarpet.item.DyeItemData; +import net.techcable.sonarpet.item.ItemData; +import net.techcable.sonarpet.item.ItemDataFactory; +import org.bukkit.Bukkit; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.inventory.meta.ItemMeta; + +public class LegacyDyeItemData extends LegacyItemData implements DyeItemData { + + /* package */ LegacyDyeItemData(LegacyItemDataFactory factory, byte rawData, ItemMeta meta) { + super(factory, Material.INK_SACK, rawData, meta); + } + + @SuppressWarnings("deprecation") + public DyeColor getColor() { + return DyeColor.getByDyeData(getRawData()); + } + + @SuppressWarnings("deprecation") + public LegacyDyeItemData withColor(DyeColor color) { + return withRawData(Preconditions.checkNotNull(color, "Null color").getDyeData()); + } + + public LegacyDyeItemData withRawData(int rawData) { + return (LegacyDyeItemData) super.withRawData(rawData); + } +} diff --git a/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacyItemData.java b/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacyItemData.java new file mode 100644 index 00000000..e1c6c809 --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacyItemData.java @@ -0,0 +1,101 @@ +package net.techcable.sonarpet.item.legacy; + +import com.google.common.base.Preconditions; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NonNull; +import net.techcable.sonarpet.block.BlockData; +import net.techcable.sonarpet.block.BlockDataFactory; +import net.techcable.sonarpet.item.ItemData; +import net.techcable.sonarpet.utils.NmsVersion; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BlockStateMeta; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.material.MaterialData; + +import javax.annotation.Nullable; + +@Getter +public class LegacyItemData implements ItemData { + private final LegacyItemDataFactory factory; + @NonNull + private final Material type; + private final byte rawData; + @Getter(AccessLevel.NONE) // Doesn't make a defensive copy, which is nessicary as it is mutable + private final ItemMeta meta; + + /* package */ LegacyItemData( + LegacyItemDataFactory factory, + Material type, + byte rawData, + ItemMeta meta + ) { + NmsVersion.ensureBefore(NmsVersion.v1_13_R2); + this.factory = Preconditions.checkNotNull(factory); + this.type = Preconditions.checkNotNull(type, "Null type"); + this.rawData = rawData; + Preconditions.checkNotNull(meta, "Null metadata"); + this.meta = Bukkit.getItemFactory().asMetaFor(meta, type).clone(); // Not guarnteed to copy ;) + } + + public LegacyItemData withRawData(int rawData) { + Preconditions.checkArgument((byte) rawData == rawData, "Raw data doesn't fit into byte: %s", rawData); + return factory.create(this.type, rawData, this.meta); + } + + public LegacyItemData withMeta(ItemMeta meta) { + Preconditions.checkNotNull(meta, "Null metadata"); + return meta.equals(this.meta) ? this : factory.create(getType(), getRawData(), meta); + } + + public LegacyItemData withPlainMeta() { + return factory.create(getType(), getRawData(), getMeta()); + } + + public ItemMeta getMeta() { + return meta.clone(); + } + + @Override + public String serializeAsString() { + /* + * NOTE: Since we're on an old version, + * we aren't expected to preserve anything beyond material, + * rawData, lore, and displayName + */ + return new BasicSerializedItem( + this.type, + this.rawData, + this.getLore(), + this.getDisplayName().orElse(null) + ).serializeAsString(); + } + + public ItemStack createStack(int amount) { + ItemStack stack = new ItemStack(getType(), amount, getRawData()); + stack.setItemMeta(this.meta.clone()); + return stack; + } + + public MaterialData getLegacyMaterialData() { + return this.type.getNewData(this.rawData); + } + + @Nullable + @Override + public BlockData getBlockData() { + if (this.getMeta() instanceof BlockStateMeta) { + return BlockDataFactory.getInstance().fromState( + ((BlockStateMeta) this.getMeta()).getBlockState()); + } else if (this.getType().isBlock()) { + return BlockDataFactory.getInstance().fromLegacyData( + this.getType(), + this.rawData + ); + } else { + return null; + } + } +} \ No newline at end of file diff --git a/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacyItemDataFactory.java b/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacyItemDataFactory.java new file mode 100644 index 00000000..473579dc --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacyItemDataFactory.java @@ -0,0 +1,120 @@ +package net.techcable.sonarpet.item.legacy; + +import com.google.common.base.Preconditions; +import net.techcable.sonarpet.item.*; +import net.techcable.sonarpet.utils.NmsVersion; +import net.techcable.sonarpet.utils.PlayerProfile; +import net.techcable.sonarpet.utils.Versioning; +import org.bukkit.Bukkit; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.EntityType; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.material.SpawnEgg; + +public class LegacyItemDataFactory implements ItemDataFactory { + public LegacyItemDataFactory() { + NmsVersion.ensureBefore(NmsVersion.v1_13_R2); + } + + @Override + public ItemData parseFromString(String s) { + BasicSerializedItem data = BasicSerializedItem.deserializeFromString(s); + ItemMeta meta = Bukkit.getItemFactory().getItemMeta(data.getType()); + if (!data.getLore().isEmpty()) { + meta.setLore(data.getLore()); + } + if (data.getDisplayName() != null) { + meta.setDisplayName(data.getDisplayName()); + } + return create(data.getType(), data.getRawData(), meta); + } + + LegacyItemData create(Material type, int rawData, ItemMeta meta) { + Preconditions.checkNotNull(type, "Null type"); + Preconditions.checkArgument((byte) rawData == rawData, "Raw data doesn't fit in byte: %s", rawData); + Preconditions.checkNotNull(meta, "Null item meta"); + switch (type) { + case INK_SACK: + return new LegacyDyeItemData(this, (byte) rawData, meta); + case SKULL_ITEM: + return new LegacySkullItemData(this, (byte) rawData, meta); + case STAINED_CLAY: + return new LegacyStainedClayItemData(this, (byte) rawData, meta); + case WOOL: + return new LegacyWoolItemData(this, (byte) rawData, meta); + case MONSTER_EGG: + // We expect this to be overridden, so we leave a hook + return (LegacyItemData) createSpawnEggData((byte) rawData, meta); + default: + return new LegacyItemData(this, type, (byte) rawData, meta); + } + } + + private SpawnEggItemData createSpawnEggData(byte rawData, ItemMeta meta) { + EntityType entityType = new SpawnEgg(rawData).getSpawnedType(); + if (entityType == null) entityType = SpawnEggItemData.DEFAULT_TYPE; + return createSpawnEggData(entityType, meta); // Convert raw data to entity type + } + + @Override + public ItemData create(Material type, ItemMeta meta) { + return create(type, 0, meta); + } + + @Override + public LegacyDyeItemData createDye(DyeColor color, ItemMeta meta) { + byte data = Preconditions.checkNotNull(color, "Null color").getDyeData(); + return new LegacyDyeItemData(this, data, meta); + } + + @Override + public StainedClayItemData createStainedClay(DyeColor color, ItemMeta meta) { + byte data = Preconditions.checkNotNull(color, "Null color").getWoolData(); + return new LegacyStainedClayItemData(this, data, it); + } + + @Override + public WoolItemData createWool(DyeColor color, ItemMeta meta) { + byte data = Preconditions.checkNotNull(color, "Null color").getWoolData(); + return new LegacyWoolItemData(this, data, it); + } + + @Override + public LegacySkullItemData createHumanSkull(PlayerProfile owner, ItemMeta rawMeta) { + Preconditions.checkNotNull(rawMeta, "Null meta"); + Preconditions.checkNotNull(owner, "Null owner"); + SkullMeta meta; + if (rawMeta instanceof SkullMeta) { + meta = (SkullMeta) rawMeta; + } else { + meta = (SkullMeta) Bukkit.getItemFactory().asMetaFor(rawMeta, Material.SKULL_ITEM); + } + meta = meta.clone(); // Don't modify their junk + meta.setOwner(owner.getName()); + return createSkull(SkullItemData.SkullType.HUMAN_SKULL, meta); + } + + @Override + public LegacySkullItemData createSkull(SkullItemData.SkullType type, ItemMeta rawData) { + return new LegacySkullItemData( + this, + Preconditions.checkNotNull(type, "Null skull type").getId(), + rawData + ); + } + + @Override + public SpawnEggItemData createSpawnEggData(EntityType entityType, ItemMeta meta) { + Preconditions.checkNotNull(meta, "Null meta"); + Preconditions.checkNotNull(entityType, "Null entity type"); + return new LegacySpawnEggItemData(this, Material.LEGACY_MONSTER_EGG, new SpawnEgg(entityType).getData(), meta) { + @Override + @SuppressWarnings("depreciation") // Bukkit is okay on versions less than 1.9, and we've already checked above + public EntityType getSpawnedType() { + return ((SpawnEgg) getLegacyMaterialData()).getSpawnedType(); + } + }; + } +} diff --git a/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacySkullItemData.java b/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacySkullItemData.java new file mode 100644 index 00000000..16cb5fec --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacySkullItemData.java @@ -0,0 +1,98 @@ +package net.techcable.sonarpet.item.legacy; + +import com.google.common.base.Preconditions; +import net.techcable.sonarpet.item.ItemData; +import net.techcable.sonarpet.item.ItemDataFactory; +import net.techcable.sonarpet.item.SkullItemData; +import net.techcable.sonarpet.utils.PlayerProfile; +import net.techcable.sonarpet.utils.ProfileUtils; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; + +import java.util.Optional; +import java.util.UUID; + +public class LegacySkullItemData extends LegacyItemData implements SkullItemData { + private final PlayerProfile profile; + + public Optional getProfile() { + if (getSkullType() == SkullType.HUMAN_SKULL && getMeta().hasOwner()) { + String ownerName = getMeta().getOwner(); + Preconditions.checkState(profile.getName().equals(ownerName), "Profile %s doesn't match owner %s", profile, ownerName); + return Optional.of(profile); + } else { + Preconditions.checkState(profile == null, "Profile %s is present but meta has no owner", profile); + return Optional.empty(); + } + } + + + /* package */ LegacySkullItemData(LegacyItemDataFactory factory, byte rawData, ItemMeta meta) { + this(factory, rawData, meta, ((SkullMeta) meta).hasOwner() ? ProfileUtils.lookupOptimistically(((SkullMeta) meta).getOwner()) : null); + } + + /* package */ LegacySkullItemData(LegacyItemDataFactory factory, byte rawData, ItemMeta meta, PlayerProfile profile) { + // Pretty sure this is okay s + super(factory, Material.LEGACY_SKULL_ITEM, rawData, meta); + Preconditions.checkArgument(profile == null || profile.getName().equals(((SkullMeta) meta).getOwner())); + this.profile = profile; + } + + public LegacySkullItemData withOwner(UUID owner) { + Preconditions.checkNotNull(owner, "Null owner uuid"); + if (getProfile().isPresent() && getProfile().get().getId().equals(owner)) { + return this; + } else { + return withOwner(ProfileUtils.lookupOptimistically(owner)); + } + } + + public LegacySkullItemData withOwner(String ownerName) { + Preconditions.checkNotNull(ownerName, "Null owner name"); + if (getProfile().isPresent() && getProfile().get().getName().equals(ownerName)) { + return this; + } else { + return withOwner(ProfileUtils.lookupOptimistically(ownerName)); + } + } + + public LegacySkullItemData withOwner(PlayerProfile profile) { + return profile.equals(this.profile) ? this : getFactory().createHumanSkull(profile, this.getMeta()); + } + + public Optional getOwner() { + return getProfile().map(PlayerProfile::getId); + } + + + public Optional getOwnerName() { + return getProfile().map(PlayerProfile::getName); + } + + public boolean hasOwner() { + return getProfile().isPresent(); + } + + public SkullType getSkullType() { + int data = getRawData(); + SkullType[] values = SkullType.values(); + if (data < 0) { + throw new IllegalStateException("Can't get skull type from negative data: " + data); + } else if (data >= values.length) { + throw new IllegalStateException("Can't get skull type from too large data: " + data); + } else { + return values[data]; + } + } + + public ItemData withSkullType(SkullType type) { + return withRawData(Preconditions.checkNotNull(type, "Null type").ordinal()); + } + + @Override + public SkullMeta getMeta() { + return (SkullMeta) super.getMeta(); + } +} diff --git a/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacySpawnEggItemData.java b/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacySpawnEggItemData.java new file mode 100644 index 00000000..758adf04 --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacySpawnEggItemData.java @@ -0,0 +1,16 @@ +package net.techcable.sonarpet.item.legacy; + +import net.techcable.sonarpet.item.SpawnEggItemData; +import org.bukkit.Material; +import org.bukkit.inventory.meta.ItemMeta; + +public abstract class LegacySpawnEggItemData extends LegacyItemData implements SpawnEggItemData { + protected LegacySpawnEggItemData( + LegacyItemDataFactory factory, + Material m, + byte rawData, + ItemMeta meta + ) { + super(factory, m, rawData, meta); + } +} diff --git a/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacyStainedClayItemData.java b/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacyStainedClayItemData.java new file mode 100644 index 00000000..3c6e7317 --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacyStainedClayItemData.java @@ -0,0 +1,30 @@ +package net.techcable.sonarpet.item.legacy; + +import com.google.common.base.Preconditions; +import net.techcable.sonarpet.item.StainedClayItemData; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +public class LegacyStainedClayItemData extends LegacyItemData implements StainedClayItemData { + + protected LegacyStainedClayItemData(LegacyItemDataFactory factory, byte rawData, ItemMeta meta) { + super(factory, Material.STAINED_CLAY, rawData, meta); + } + + @SuppressWarnings("deprecation") + public DyeColor getColor() { + return DyeColor.getByWoolData(getRawData()); + } + + @SuppressWarnings("deprecation") + public LegacyStainedClayItemData withColor(DyeColor color) { + return withRawData(Preconditions.checkNotNull(color, "Null color").getWoolData()); + } + + public LegacyStainedClayItemData withRawData(int rawData) { + return (LegacyStainedClayItemData) super.withRawData(rawData); + } + +} diff --git a/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacyWoolItemData.java b/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacyWoolItemData.java new file mode 100644 index 00000000..b8008c05 --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/item/legacy/LegacyWoolItemData.java @@ -0,0 +1,31 @@ +package net.techcable.sonarpet.item.legacy; + +import com.google.common.base.Preconditions; +import net.techcable.sonarpet.item.ColoredItemData; +import net.techcable.sonarpet.item.ItemData; +import net.techcable.sonarpet.item.WoolItemData; +import org.bukkit.Bukkit; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.inventory.meta.ItemMeta; + +public class LegacyWoolItemData extends LegacyItemData implements WoolItemData, ColoredItemData { + + protected LegacyWoolItemData(LegacyItemDataFactory factory, byte rawData, ItemMeta meta) { + super(factory, Material.WOOL, rawData, meta); + } + + @SuppressWarnings("deprecation") + public DyeColor getColor() { + return DyeColor.getByWoolData(getRawData()); + } + + @SuppressWarnings("deprecation") + public LegacyWoolItemData withColor(DyeColor color) { + return withRawData(Preconditions.checkNotNull(color, "Null color").getWoolData()); + } + + public LegacyWoolItemData withRawData(int rawData) { + return (LegacyWoolItemData) super.withRawData(rawData); + } +} diff --git a/api/src/main/java/net/techcable/sonarpet/nms/IModernNMS.java b/api/src/main/java/net/techcable/sonarpet/nms/IModernNMS.java new file mode 100644 index 00000000..e731e72d --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/nms/IModernNMS.java @@ -0,0 +1,14 @@ +package net.techcable.sonarpet.nms; + +import net.techcable.sonarpet.utils.NmsVersion; +import org.bukkit.Material; + +public interface IModernNMS extends INMS { + NmsVersion MINIMUM_VERSION = NmsVersion.v1_13_R2; + Material getMaterialByLegacyId(int id); + Object getBukkitBlockData(Material m, byte b); + static IModernNMS getInstance() { + NmsVersion.ensureAtLeast(MINIMUM_VERSION); + return (IModernNMS) INMS.getInstance(); + } +} diff --git a/api/src/main/java/net/techcable/sonarpet/nms/INMS.java b/api/src/main/java/net/techcable/sonarpet/nms/INMS.java index 352f1f75..88f5a827 100644 --- a/api/src/main/java/net/techcable/sonarpet/nms/INMS.java +++ b/api/src/main/java/net/techcable/sonarpet/nms/INMS.java @@ -17,49 +17,31 @@ package net.techcable.sonarpet.nms; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - import com.dsh105.echopet.compat.api.plugin.IEchoPetPlugin; import com.google.common.base.Preconditions; - -import net.techcable.pineapple.reflection.PineappleField; import net.techcable.pineapple.reflection.Reflection; -import net.techcable.sonarpet.item.SpawnEggItemData; +import net.techcable.sonarpet.item.ItemDataFactory; +import net.techcable.sonarpet.item.legacy.LegacyItemDataFactory; +import net.techcable.sonarpet.utils.NmsVersion; import net.techcable.sonarpet.utils.Versioning; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.material.SpawnEgg; -import static net.techcable.sonarpet.utils.Versioning.*; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +import static net.techcable.sonarpet.utils.Versioning.NMS_VERSION; +import static net.techcable.sonarpet.utils.Versioning.NMS_VERSION_STRING; @SuppressWarnings("deprecation") public interface INMS { - - default SpawnEggItemData createSpawnEggData(byte rawData, ItemMeta meta) { - EntityType entityType = new SpawnEgg(rawData).getSpawnedType(); - if (entityType == null) entityType = SpawnEggItemData.DEFAULT_TYPE; - return createSpawnEggData(entityType, meta); // Convert raw data to entity type - } - - default SpawnEggItemData createSpawnEggData(EntityType entityType, ItemMeta meta) { - if (Versioning.NMS_VERSION.getMajorVersion() >= 9) throw new UnsupportedOperationException("Can't use bukkit API on versions newer than 1.9"); - Preconditions.checkNotNull(meta, "Null meta"); - Preconditions.checkNotNull(entityType, "Null entity type"); - return new SpawnEggItemData(new SpawnEgg(entityType).getData(), meta) { - @Override - @SuppressWarnings("depreciation") // Bukkit is okay on versions less than 1.9, and we've already checked above - public EntityType getSpawnedType() { - return ((SpawnEgg) getMaterialData()).getSpawnedType(); - } - }; + default ItemDataFactory getItemDataFactory() { + NmsVersion.ensureBefore(NmsVersion.v1_13_R2); + return new LegacyItemDataFactory(); } boolean spawnEntity(NMSInsentientEntity entity, Location location); @@ -131,5 +113,9 @@ class Helper { throw new AssertionError("NMS constructor threw exception", t); } } + if (NmsVersion.current().isAtLeast(IModernNMS.MINIMUM_VERSION) + && !(instance instanceof IModernNMS)) { + throw new RuntimeException("NMSImpl for " + NMS_VERSION_STRING + " should implement IModernNMS"); + } } } diff --git a/api/src/main/java/net/techcable/sonarpet/particles/BukkitParticleBuilder.java b/api/src/main/java/net/techcable/sonarpet/particles/BukkitParticleBuilder.java index 738e2451..9781eecb 100644 --- a/api/src/main/java/net/techcable/sonarpet/particles/BukkitParticleBuilder.java +++ b/api/src/main/java/net/techcable/sonarpet/particles/BukkitParticleBuilder.java @@ -6,6 +6,12 @@ import org.bukkit.entity.Player; import org.bukkit.material.MaterialData; +/** + * This is used on all modern versions (v1.8.8+) + * + * @deprecated Was only used for 1.8.8 support. + */ +@Deprecated public class BukkitParticleBuilder extends ParticleBuilder { public BukkitParticleBuilder(Particle type, float speed, int amount) { super(type, speed, amount); diff --git a/api/src/main/java/net/techcable/sonarpet/particles/PacketParticleBuilder.java b/api/src/main/java/net/techcable/sonarpet/particles/PacketParticleBuilder.java deleted file mode 100644 index 1fb60fef..00000000 --- a/api/src/main/java/net/techcable/sonarpet/particles/PacketParticleBuilder.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.techcable.sonarpet.particles; - -import com.google.common.base.Preconditions; - -import net.techcable.pineapple.reflection.Reflection; -import net.techcable.sonarpet.utils.reflection.MinecraftReflection; -import net.techcable.sonarpet.utils.reflection.PacketType; - -import org.bukkit.entity.Player; - -public abstract class PacketParticleBuilder extends ParticleBuilder { - public PacketParticleBuilder(Particle type, float speed, int amount) { - super(type, speed, amount); - } - public static final PacketType PARTICLE_PACKET_TYPE = PacketType.forName("PlayOutWorldParticles"); - public void show(Player player) { - Object packet = PARTICLE_PACKET_TYPE.newPacket(); - setupPacket(packet); - Preconditions.checkState(getPosition() != null, "Position not set"); - Preconditions.checkState(getPosition() != null, "Offset not set"); - MinecraftReflection.sendPacket(player, packet); - } - - protected abstract Object getNMSParticleType(); - - protected void setupPacket(Object packet) { - PARTICLE_PACKET_TYPE.putObject(packet, 0, this.getNMSParticleType()); - PARTICLE_PACKET_TYPE.putFloat(packet, 0, (float) getPosition().getX()); - PARTICLE_PACKET_TYPE.putFloat(packet, 1, (float) getPosition().getY()); - PARTICLE_PACKET_TYPE.putFloat(packet, 2, (float) getPosition().getZ()); - PARTICLE_PACKET_TYPE.putFloat(packet, 3, (float) getOffset().getX()); - PARTICLE_PACKET_TYPE.putFloat(packet, 4, (float) getOffset().getY()); - PARTICLE_PACKET_TYPE.putFloat(packet, 5, (float) getOffset().getZ()); - PARTICLE_PACKET_TYPE.putFloat(packet, 6, getSpeed()); - PARTICLE_PACKET_TYPE.putInt(packet, 0, getAmount()); - } -} diff --git a/api/src/main/java/net/techcable/sonarpet/particles/v18ParticleBuilder.java b/api/src/main/java/net/techcable/sonarpet/particles/v18ParticleBuilder.java deleted file mode 100644 index 5e6b9caf..00000000 --- a/api/src/main/java/net/techcable/sonarpet/particles/v18ParticleBuilder.java +++ /dev/null @@ -1,33 +0,0 @@ -package net.techcable.sonarpet.particles; - -import lombok.*; - -import com.dsh105.commodus.reflection.Reflection; - -import org.apache.commons.lang.ArrayUtils; - -@Getter -public class v18ParticleBuilder extends PacketParticleBuilder { - private boolean forced = true; - - public v18ParticleBuilder(Particle type, float speed, int amount) { - super(type, speed, amount); - } - - @Override - protected Object getNMSParticleType() { - Class var6 = Reflection.getNMSClass("EnumParticle"); - return var6.getEnumConstants()[this.getType().getId()]; - } - - @Override - protected void setupPacket(Object packet) { - super.setupPacket(packet); - PARTICLE_PACKET_TYPE.putObject(packet, 1, createData()); - PARTICLE_PACKET_TYPE.putBoolean(packet, 0, isForced()); - } - - private int[] createData() { - return hasBlockData() ? new int[] {getBlockType().getId(), getBlockMeta()} : ArrayUtils.EMPTY_INT_ARRAY; - } -} diff --git a/api/src/main/java/net/techcable/sonarpet/utils/ModernSpawnEggs.java b/api/src/main/java/net/techcable/sonarpet/utils/ModernSpawnEggs.java new file mode 100644 index 00000000..013b7304 --- /dev/null +++ b/api/src/main/java/net/techcable/sonarpet/utils/ModernSpawnEggs.java @@ -0,0 +1,76 @@ +package net.techcable.sonarpet.utils; + +import lombok.SneakyThrows; +import org.bukkit.Material; +import org.bukkit.entity.EntityType; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class ModernSpawnEggs { + private ModernSpawnEggs() {} + + @Nonnull + private static void ensureSupported() { + if (!ModernSpawnEggs.isSupported()) { + throw new IllegalStateException( + "Can't use modern spawn eggs on " + NmsVersion.current() + ); + } + } + public static boolean isSpawnEgg(Material m) { + return tryGetSpawnEggType(m) != null; + } + public static boolean isSupported() { + return NmsVersion.current().compareTo(NmsVersion.v1_13_R2) >= 0; + } + public static boolean hasSpawnEgg(EntityType e) { + return tryGetEggMaterial(e) != null; + } + @Nonnull + public static Material getEggMaterial(EntityType t) { + Material m = tryGetEggMaterial(t); + if (m == null) { + throw new IllegalArgumentException("Entity doesn't have spawn egg: " + t); + } + return m; + } + @Nonnull + public static EntityType getSpawnEggType(Material m) { + EntityType entityType = tryGetSpawnEggType(m); + if (entityType == null) { + throw new IllegalArgumentException("Material isn't a spawn egg: " + m); + } + return entityType; + } + private static final String SUFFIX = "_SPAWN_EGG"; + @Nullable + @SneakyThrows(ReflectiveOperationException.class) + private static Material tryGetEggMaterial(EntityType entityType) { + ModernSpawnEggs.ensureSupported(); + Class materialClass = Class.forName("org.bukkit.Material"); + try { + //noinspection unchecked + return (Material) Enum.valueOf(materialClass, entityType.name() + SUFFIX); + } catch (IllegalArgumentException ignored) { + return null; + } + } + + @Nullable + private static EntityType tryGetSpawnEggType(Material m) { + ModernSpawnEggs.ensureSupported(); + if (m.name().endsWith(SUFFIX)) { + String entityName = m.name().substring( + 0, + m.name().length() - SUFFIX.length() + ); + try { + return EntityType.valueOf(entityName); + } catch (IllegalArgumentException ignored) {} + } + return null; + } +} diff --git a/api/src/main/java/net/techcable/sonarpet/utils/NmsVersion.java b/api/src/main/java/net/techcable/sonarpet/utils/NmsVersion.java index 6dd77c5e..f213f47e 100644 --- a/api/src/main/java/net/techcable/sonarpet/utils/NmsVersion.java +++ b/api/src/main/java/net/techcable/sonarpet/utils/NmsVersion.java @@ -24,12 +24,8 @@ //ToDo: Version Fix Here @Getter public enum NmsVersion { - v1_8_R3, - v1_9_R1, - v1_9_R2, - v1_10_R1, - v1_11_R1, - v1_12_R1; + v1_12_R1, + v1_13_R2; public static final NmsVersion LATEST, EARLIEST; private ImmutableMap metadata; @@ -120,4 +116,29 @@ private static int parseMajorVersion(String s) { public static NmsVersion current() { return Versioning.NMS_VERSION; } + + public boolean isAtLeast(NmsVersion minimum) { + return this.compareTo(minimum) >= 0; + } + public boolean isBefore(NmsVersion other) { + return this.compareTo(other) < 0; + } + public static void ensureAtLeast(NmsVersion minimum) { + NmsVersion current = NmsVersion.current(); + if (!current.isAtLeast(minimum)) { + throw new IllegalStateException("Expected NMS version at least " + + minimum + + ", but got " + + current); + } + } + public static void ensureBefore(NmsVersion maximum) { + NmsVersion current = NmsVersion.current(); + if (!current.isBefore(maximum)) { + throw new IllegalStateException("Expected NMS version before " + + maximum + + ", but got " + + current); + } + } } diff --git a/api/src/main/java/net/techcable/sonarpet/utils/compat/AncientGuava.java b/api/src/main/java/net/techcable/sonarpet/utils/compat/AncientGuava.java deleted file mode 100644 index 94001603..00000000 --- a/api/src/main/java/net/techcable/sonarpet/utils/compat/AncientGuava.java +++ /dev/null @@ -1,36 +0,0 @@ -package net.techcable.sonarpet.utils.compat; - -import java.util.concurrent.Executor; -import java.util.stream.Collector; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.util.concurrent.MoreExecutors; - -public class AncientGuava implements GuavaVersion { - /* package */ AncientGuava() {} - @Override - public Collector> immutableListCollector() { - return Collector., ImmutableList>of( - ImmutableList::builder, - ImmutableList.Builder::add, - (first, second) -> first.addAll(second.build()), - ImmutableList.Builder::build - ); - } - - @Override - public Collector> immutableSetCollector() { - return Collector., ImmutableSet>of( - ImmutableSet::builder, - ImmutableSet.Builder::add, - (first, second) -> first.addAll(second.build()), - ImmutableSet.Builder::build - ); - } - - @Override - public Executor directExecutor() { - return MoreExecutors.sameThreadExecutor(); - } -} diff --git a/api/src/main/java/net/techcable/sonarpet/utils/compat/GuavaVersion.java b/api/src/main/java/net/techcable/sonarpet/utils/compat/GuavaVersion.java deleted file mode 100644 index b53e059c..00000000 --- a/api/src/main/java/net/techcable/sonarpet/utils/compat/GuavaVersion.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.techcable.sonarpet.utils.compat; - -import java.util.concurrent.Executor; -import java.util.stream.Collector; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; - -public interface GuavaVersion { - Collector> immutableListCollector(); - Collector> immutableSetCollector(); - Executor directExecutor(); - - GuavaVersion INSTANCE = acquireInstance(); - static GuavaVersion acquireInstance() { - if (INSTANCE != null) return INSTANCE; - try { - ImmutableList.class.getMethod("toImmutableList"); - return new ModernGuava(); - } catch (NoSuchMethodException e) { - return new AncientGuava(); - } - } -} diff --git a/api/src/main/java/net/techcable/sonarpet/utils/compat/ModernGuava.java b/api/src/main/java/net/techcable/sonarpet/utils/compat/ModernGuava.java deleted file mode 100644 index 89e3c0d8..00000000 --- a/api/src/main/java/net/techcable/sonarpet/utils/compat/ModernGuava.java +++ /dev/null @@ -1,62 +0,0 @@ -package net.techcable.sonarpet.utils.compat; - -import lombok.*; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.util.concurrent.Executor; -import java.util.stream.Collector; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.util.concurrent.MoreExecutors; - -public class ModernGuava implements GuavaVersion { - /* package */ ModernGuava() {} - - private static final MethodHandle IMMUTABLE_LIST_COLLECTOR_METHOD; - private static final MethodHandle IMMUTABLE_SET_COLLECTOR_METHOD; - private static final MethodHandle DIRECT_EXECUTOR_METHOD; - static { - MethodType collectorType = MethodType.methodType(Collector.class); - try { - IMMUTABLE_LIST_COLLECTOR_METHOD = MethodHandles.publicLookup().findStatic( - ImmutableList.class, - "toImmutableList", - collectorType - ); - IMMUTABLE_SET_COLLECTOR_METHOD = MethodHandles.publicLookup().findStatic( - ImmutableSet.class, - "toImmutableSet", - collectorType - ); - DIRECT_EXECUTOR_METHOD = MethodHandles.publicLookup().findStatic( - MoreExecutors.class, - "directExecutor", - MethodType.methodType(Executor.class) - ); - } catch (NoSuchMethodException | IllegalAccessException e) { - throw new AssertionError("Unable to find modern guava methods", e); - } - } - @Override - @SuppressWarnings("unchecked") - @SneakyThrows - public Collector> immutableListCollector() { - return (Collector>) IMMUTABLE_LIST_COLLECTOR_METHOD.invokeExact(); - } - - @SuppressWarnings("unchecked") - @Override - @SneakyThrows - public Collector> immutableSetCollector() { - return (Collector>) IMMUTABLE_SET_COLLECTOR_METHOD.invokeExact(); - } - - @Override - @SneakyThrows - public Executor directExecutor() { - return (Executor) DIRECT_EXECUTOR_METHOD.invokeExact(); - } -} diff --git a/api/src/main/kotlin/net/techcable/sonarpet/particles/ParticleBuilder.kt b/api/src/main/kotlin/net/techcable/sonarpet/particles/ParticleBuilder.kt index 87d0e0db..fdeebef4 100644 --- a/api/src/main/kotlin/net/techcable/sonarpet/particles/ParticleBuilder.kt +++ b/api/src/main/kotlin/net/techcable/sonarpet/particles/ParticleBuilder.kt @@ -10,6 +10,7 @@ import org.bukkit.entity.Player import org.bukkit.util.Vector import java.util.* +@Deprecated(message = "Only needed for 1.8.8 compat.....") abstract class ParticleBuilder protected constructor( var type: Particle, var speed: Float = 0f, @@ -70,10 +71,10 @@ abstract class ParticleBuilder protected constructor( @JvmStatic fun create(type: Particle, speed: Float, amount: Int): ParticleBuilder { return when (Versioning.NMS_VERSION!!) { - v1_12_R1, v1_11_R1, v1_10_R1, v1_9_R1, v1_9_R2 -> { + v1_12_R1, v1_11_R1, v1_10_R1, v1_9_R1, v1_9_R2, v1_13_R2 -> { BukkitParticleBuilder(type, speed, amount) } - v1_8_R3 -> v18ParticleBuilder(type, speed, amount) + -> v18ParticleBuilder(type, speed, amount) } } } diff --git a/api/src/main/kotlin/net/techcable/sonarpet/utils/compat/GuavaCompatibility.kt b/api/src/main/kotlin/net/techcable/sonarpet/utils/compat/GuavaCompatibility.kt deleted file mode 100644 index 6a7c3796..00000000 --- a/api/src/main/kotlin/net/techcable/sonarpet/utils/compat/GuavaCompatibility.kt +++ /dev/null @@ -1,3 +0,0 @@ -package net.techcable.sonarpet.utils.compat - -object GuavaCompatibility: GuavaVersion by GuavaVersion.INSTANCE \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index d377127d..df0a598e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,22 +1,20 @@ -import org.gradle.api.tasks.compile.JavaCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import org.gradle.api.tasks.testing.Test -import org.gradle.api.tasks.testing.junit.JUnitOptions buildscript { repositories { - gradleScriptKotlin() + mavenCentral() } dependencies { - classpath("org.ow2.asm:asm-all:5.2") // Used to check for guava compat - classpath(kotlinModule("gradle-plugin")) + classpath(kotlin("gradle-plugin", version = "1.3.72")) } } plugins { id("java") id("maven") - id("org.jetbrains.kotlin.jvm").version("1.2.51") - id("com.github.johnrengelman.shadow").version("1.2.4").apply(false) + kotlin("jvm").version("1.3.72") + id("com.github.johnrengelman.shadow") + .version("5.2.0") + .apply(false) } allprojects { apply { @@ -24,7 +22,7 @@ allprojects { } group = "net.techcable.sonarpet" - version = "1.1.0-alpha2-SNAPSHOT" + version = "1.2.0-alpha1-SNAPSHOT" } var versionSignature: String by rootProject.extra versionSignature = rawComputeVersionSignature() @@ -48,7 +46,7 @@ subprojects { targetCompatibility = "1.8" options.encoding = "UTF-8" } - tasks.withType { + tasks.withType().configureEach { kotlinOptions.jvmTarget = "1.8" } tasks.withType { @@ -63,14 +61,27 @@ subprojects { } repositories { + /* + * NOTE: I have a bunch of local jars to keep + * all this legacy code rolling. For now my laptop + * is the only place you can compile SonarPet ^_^ + */ mavenLocal() mavenCentral() maven { name = "techcable-repo" setUrl("https://repo.techcable.net/content/groups/public/") } - maven { setUrl("https://hub.spigotmc.org/nexus/content/groups/public/") } + maven { + name = "paper-repo" + setUrl("https://papermc.io/repo/repository/maven-public/") + } maven { setUrl("http://repo.dmulloy2.net/content/groups/public/") } + maven { + name = "enginehub-repo" + setUrl("https://maven.enginehub.org/repo/") + } + // TODO: What are all these things for!?! maven { setUrl("http://repo.md-5.net/content/groups/public/") } maven { setUrl("http://ci.hawkfalcon.com/plugin/repository/everything/") } maven { setUrl("http://maven.sk89q.com/repo/") } @@ -79,50 +90,60 @@ subprojects { maven { setUrl("http://maven.elmakers.com/repository/") } } - configurations.all { - resolutionStrategy { - // Force usage of old guava - force("com.google.guava:guava:17.0") - } - } dependencies { + implementation(kotlin("stdlib-jdk8")) testCompile("junit:junit:4.12") testCompile("com.googlecode.junit-toolbox:junit-toolbox:2.3") - compile("net.techcable:pineapple:0.1.0-beta5") - compile("org.jetbrains.kotlin:kotlin-stdlib-jre8:1.2.51") + compile("net.techcable:pineapple:0.1.0-beta6") + // TODO: Get rid of this + // TODO: Drop transitive dependency on "Minecraft-Reflection" compile("com.dsh105:Commodus:1.0.6") { exclude(module = "Minecraft-Reflection") } + // TODO: Get rid of this compile("com.dsh105:PowerMessage:1.0.1-SNAPSHOT") { exclude(module = "Commodus") } compile("org.slf4j:slf4j-jdk14:1.7.5") compile("com.zaxxer:HikariCP:2.4.5") /* - * An outdated version of ASM is used by Paper. - * We need to shade in our (modern) version, - * or else we'll use Paper's outdated version and crash. + * NOTE: Paper already includes ASM. + * + * Since we depend on them, will just assume its already present. + * Shading in this dependency is unessicarry + * * The bootstrap loader also depends on ASM to automatically relocate dependencies too, * since we need to keep our own seperate version of guava and other things. */ - "shade"("org.ow2.asm:asm:5.2") - "shade"("org.ow2.asm:asm-commons:5.2") + compileOnly("org.ow2.asm:asm:8.0.1") + compileOnly("org.ow2.asm:asm-commons:5.2") + /* + * This is not included in paper. It's required by the bootstrap loader, + * so we have to shade it in directly. + * + * Not sure if it will causes issues with the not-shaded asm. + */ + // TODO: Does this create issues since we don't shade the other parts of ASM? "shade"("org.ow2.asm:asm-util:5.2") // Provided dependencies /* - * Compile against old guava, with emulation where necessary. - * Compiling against modern guava causes the source to compile against some missing bytecode. - * For example, a new checkArgument(boolean,String,int) overload was added for effeciency, which was missing in old versions. + * We only support recent minecraft. + * Therefore we can compile against actually modern + * guava versions. */ - compileOnly("com.google.guava:guava:17.0") - compileOnly("org.bukkit:bukkit:1.12-pre5-SNAPSHOT") + compileOnly("com.google.guava:guava:21.0") + // We compile against Paper API - not Bukkit or Spigot API + compileOnly("com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT") compileOnly("org.projectlombok:lombok:1.16.12") + // TODO: Is VanishNoPacket still the standard? + // Do we need to integrate with someone elese? compileOnly("org.kitteh:VanishNoPacket:3.18.7") { exclude(module = "Vault") } compileOnly("com.sk89q:worldedit:6.0.0-SNAPSHOT") compileOnly("com.sk89q:worldguard:6.0.0-SNAPSHOT") - compileOnly("com.comphenix.protocol:ProtocolLib:3.6.5-SNAPSHOT") + // TODO: Update to modern ProtocolLib + compileOnly("com.comphenix.protocol:ProtocolLib:4.5.0") } // All test modules depend on the API's test module diff --git a/core/src/main/resources/versions/v1_12_R1.json b/core/src/main/resources/versions/v1_12_R1.json index fe185449..ea380793 100644 --- a/core/src/main/resources/versions/v1_12_R1.json +++ b/core/src/main/resources/versions/v1_12_R1.json @@ -15,6 +15,8 @@ "obfuscated_fields": { "ENTITY_SIDEWAYS_MOTION_FIELD": "be", // EntityLivingBase.moveStrafing "ENTITY_FORWARD_MOTION_FIELD": "bf", // EntityLivingBase.moveForward - "ENTITY_UPWARDS_MOTION_FIELD": "bg" // New third parameter to move() as of 1.12 + // NOTE: New third parameter to move() as of 1.12 + // TODO: Obfuscated names seems to be swapped with moveForward + "ENTITY_UPWARDS_MOTION_FIELD": "bg" // EntityLivingBase.moveVertical } } \ No newline at end of file diff --git a/core/src/main/resources/versions/v1_13_R2.json b/core/src/main/resources/versions/v1_13_R2.json new file mode 100644 index 00000000..ab711cdb --- /dev/null +++ b/core/src/main/resources/versions/v1_13_R2.json @@ -0,0 +1,23 @@ +{ + "metadata": { + "ENDERMAN_SCREAMING_METADATA_ID": 13, + "WITHER_SHIELDED_METADATA_ID": 15 + }, + "obfuscated_methods": { + "ENTITY_TICK_METHOD": "tick", // MCP: Entity.tick + // NOTE: As of 1.12, signature is (FFF) instead of (FF) + "ENTITY_MOVE_METHOD": "a", // MCP: EntityLivingBase.travel + "ON_STEP_METHOD": "a", // MCP: EntityLivingBase.travel + "ON_INTERACT_METHOD": "a", // MCP: EntityLiving.canBeLeashedTo + "ENTITY_PROCEDURAL_AI_METHOD": "J", // EntityLiving.updateAITasks + // NOTE: MCP renamed it in 1.13, it seems to have undergone some sort of change + "LIVING_UPDATE_METHOD": "n", // EntityLivingBase.livingTick + "RABBIT_SET_MOVEMENT_SPEED": "c" // EntityRabbit.setMovementSpeed + }, + "obfuscated_fields": { + "ENTITY_SIDEWAYS_MOTION_FIELD": "bh", // EntityLivingBase.moveStrafing + "ENTITY_FORWARD_MOTION_FIELD": "bj", // EntityLivingBase.moveForward + // NOTE: New third parameter to move() as of 1.12 + "ENTITY_UPWARDS_MOTION_FIELD": "bi" // EntityLivingBase.moveVertical + } +} \ No newline at end of file diff --git a/gradle/compat.gradle b/gradle/compat.gradle deleted file mode 100644 index 53f511a0..00000000 --- a/gradle/compat.gradle +++ /dev/null @@ -1,184 +0,0 @@ -buildscript { - repositories { - mavenCentral() - } - dependencies { - classpath "org.ow2.asm:asm-all:5.2" // Used to check for guava compat - } -} - -import groovy.transform.CompileStatic -import groovy.transform.Immutable -import org.objectweb.asm.* - -import java.util.zip.ZipEntry -import java.util.zip.ZipFile - -import static org.objectweb.asm.Opcodes.* - -@CompileStatic -class ClassMembers { - String className - Set> methods = new HashSet<>() - Set fields = new HashSet<>() -} - -@CompileStatic -@Immutable -class JarMembers { - private Map classes - - boolean isKnownClass(String className) { - this.classes[className] != null - } - - boolean isKnownMethod(String owner, String name, String desc) { - ClassMembers classMembers = this.classes[owner] - if (classMembers == null) return null - return new Tuple2(name, desc) in classMembers.methods - } - - boolean isKnownField(String owner, String name) { - ClassMembers classMembers = this.classes[owner] - if (classMembers == null) return null - return name in classMembers.fields - } - - static JarMembers parse(File jarFile) { - def zip = new ZipFile(jarFile) - Map classes = [:] - try { - zip.entries().each { ZipEntry entry -> - def reader = new ClassReader(zip.getInputStream(entry).bytes) - reader.accept(new ClassVisitor(ASM5) { - private ClassMembers classMembers = null - @Override - void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - this.classMembers = new ClassMembers(className: name) - } - - @Override - MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - this.classMembers.methods.add(new Tuple2(name, desc)) - return null - } - - @Override - FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { - this.classMembers.fields.add(name) - return null - } - - @Override - void visitEnd() { - classes[this.classMembers.className] = this.classMembers - } - }, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES) - } - return new JarMembers(classes: classes) - } finally { - zip.close() - } - } -} - -Logger logger = logger -@CompileStatic -class GuavaCompatEnforcementTask extends DefaultTask { - static File localRepo = new File(System.getProperty("user.home"), ".m2/repository") - @Input - String minimumVersion - @InputFiles - @SkipWhenEmpty - FileCollection classFiles - - File findOrDownloadGuava(String version) { - File localJar = new File(localRepo, "com/google/guava/guava/$version/guava-${version}.jar" as String) - if (!localJar.exists()) { - logger.info("Downloading guava $version from central repository!") - localJar.parentFile.mkdirs() - new URL("https://repo1.maven.org/maven2/com/google/guava/guava/$version/guava-${version}.jar").withInputStream { input -> - localJar << input - } - } - return localJar - } - - @TaskAction - void checkCompat() { - logger.info("Examining guava $minimumVersion") - JarMembers guavaMembers = JarMembers.parse(findOrDownloadGuava(minimumVersion)) - logger.info("Checking compliance with guava $minimumVersion") - for (File classFile in classFiles) { - classFile.withInputStream { - def reader = new ClassReader(it) - String className = reader.className - char[] buffer = new char[reader.maxStringLength] - // NOTE: We don't need to actually read the code, just the constant pool ;) - for (int constantPoolIndex = 0; constantPoolIndex < reader.itemCount; constantPoolIndex++) { - int offset = reader.getItem(constantPoolIndex) - int itemType = reader.b[offset- 1] // See wikipedia for details - switch (itemType) { - case 7: // class reference - String name = reader.readClass(offset, buffer) - if (name.startsWith("com/google/common") && !guavaMembers.isKnownClass(name)) { - throw new GradleException("$className uses guava class not found in version $minimumVersion: ${name.replace('/', '.')}") - } - break - case 9: // field reference - case 10: // method reference - case 11: // interface method reference - case 15: // MethodHandle - Handle handle = reader.readConst(offset, buffer) as Handle - if (handle.owner.startsWith("com/google/common")) { - switch (handle.tag) { - case H_INVOKEVIRTUAL: - case H_INVOKESTATIC: - case H_INVOKESPECIAL: - case H_NEWINVOKESPECIAL: - case H_INVOKEINTERFACE: - if (!guavaMembers.isKnownMethod(handle.owner, handle.name, handle.desc)) { - def methodType = Type.getMethodType(handle.desc) - def methodId = new StringBuilder(handle.owner.length() + handle.desc.length() + handle.name.length() + 50) - methodId.append(handle.owner.replace('/', '.')) - methodId.append('.') - methodId.append(handle.name) - methodId.append('(') - def argTypes = methodType.argumentTypes - if (argTypes.length > 0) { - methodId.append(argTypes[0].className) - for (int i = 1; i < argTypes.length; i++) { - methodId.append(',') - methodId.append(argTypes[i].className) - } - } - methodId.append(')') - throw new GradleException( - "$className uses guava method not found in $minimumVersion: $methodId" - ) - } - break - case H_GETFIELD: - case H_GETSTATIC: - case H_PUTFIELD: - case H_PUTSTATIC: - if (!guavaMembers.isKnownField(handle.owner, handle.name)) { - throw new GradleException( - "$className uses guava field not found in $minimumVersion: ${handle.owner.replace('/', '.')}.${handle.name}" - ) - } - } - } - break - case 3..6: - case [1, 8, 12, 16, 18]: - break // Ignored - default: - throw new AssertionError("Unknown constant pool type id: $itemType") - } - } - } - } - } -} -ext.GuavaCompatEnforcementTask = GuavaCompatEnforcementTask diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 76493013..341693ac 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-all.zip diff --git a/nms/v1_10_R1/build.gradle.kts b/nms/v1_10_R1/build.gradle.kts deleted file mode 100644 index 85acc775..00000000 --- a/nms/v1_10_R1/build.gradle.kts +++ /dev/null @@ -1,4 +0,0 @@ -dependencies { - compileOnly("org.bukkit:craftbukkit:1.10.2-R0.1-SNAPSHOT") - compileOnly(project(":api")) -} diff --git a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/BlockSoundDataImpl.java b/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/BlockSoundDataImpl.java deleted file mode 100644 index 8c81b135..00000000 --- a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/BlockSoundDataImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_10_R1; - -import lombok.*; - -import net.minecraft.server.v1_10_R1.SoundEffectType; -import net.techcable.sonarpet.nms.BlockSoundData; - -@RequiredArgsConstructor -public class BlockSoundDataImpl implements BlockSoundData { - private final SoundEffectType handle; - - @Override - public float getVolume() { - return handle.a(); - } - - @Override - public float getPitch() { - return handle.b(); - } - - @Override - public boolean equals(Object o) { // We need this!! - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - BlockSoundDataImpl that = (BlockSoundDataImpl) o; - - return handle.equals(that.handle); - } - - @Override - public int hashCode() { - return handle.hashCode(); - } -} - diff --git a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/DataWatcherImpl.java b/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/DataWatcherImpl.java deleted file mode 100644 index 887a4484..00000000 --- a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/DataWatcherImpl.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_10_R1; - -import lombok.*; - -import net.minecraft.server.v1_10_R1.DataWatcher; -import net.minecraft.server.v1_10_R1.DataWatcherObject; -import net.minecraft.server.v1_10_R1.DataWatcherRegistry; -import net.minecraft.server.v1_10_R1.DataWatcherSerializer; - -@RequiredArgsConstructor -public class DataWatcherImpl implements net.techcable.sonarpet.nms.DataWatcher { - private final DataWatcher dataWatcher; - - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - private static final DataWatcherSerializer BOOLEAN_SERIALIZER = DataWatcherRegistry.h; - private static final DataWatcherSerializer INTEGER_SERIALIZER = DataWatcherRegistry.b; - - // - // Deobfuscated methods - // - - @Override - public void setBoolean(int id, boolean value) { - dataWatcher.set(new DataWatcherObject<>(id, BOOLEAN_SERIALIZER), value); - } - - @Override - public void setInteger(int id, int value) { - dataWatcher.set(new DataWatcherObject<>(id, INTEGER_SERIALIZER), value); - } -} diff --git a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSEntityHorseImpl.java b/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSEntityHorseImpl.java deleted file mode 100644 index 899da8c2..00000000 --- a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSEntityHorseImpl.java +++ /dev/null @@ -1,77 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_10_R1; - -import com.dsh105.echopet.compat.api.entity.HorseType; -import com.dsh105.echopet.compat.api.entity.HorseTypeKt; - -import net.minecraft.server.v1_10_R1.EntityHorse; -import net.techcable.sonarpet.nms.NMSEntityHorse; - -import org.bukkit.entity.Horse; - -public class NMSEntityHorseImpl extends NMSEntityInsentientImpl implements NMSEntityHorse { - public NMSEntityHorseImpl(EntityHorse handle) { - super(handle); - } - - // - // !!!!! Highly version-dependent !!!!! - // Check these every minor update! - // - - @Override - public void setSaddled(boolean saddled) { - getHandle().u(saddled); // EntityHorse.setHorseSaddled - } - - @Override - public boolean isSaddled() { - return getHandle().dz(); // EntityHorse.isHorseSaddled - } - - // - // Breakage likely, check for bugs here - // - - @Override - public void setRearing(boolean b) { - // metadata flag with id 64 - getHandle().v(b); - } - - // Deobfuscated methods - - @Override - public void setStyle(Horse.Style bukkitStyle) { - getBukkitEntity().setStyle(bukkitStyle); - } - - @Override - public void setHorseType(HorseType t) { - getBukkitEntity().setVariant(t.getBukkitVariant()); - } - - @Override - public void setColor(Horse.Color color) { - getBukkitEntity().setColor(color); - } - - @Override - public HorseType getHorseType() { - return HorseTypeKt.getSonarType(getBukkitEntity().getVariant()); - } - - @Override - public void setCarryingChest(boolean flag) { - getBukkitEntity().setCarryingChest(flag); - } - - @Override - public EntityHorse getHandle() { - return (EntityHorse) super.getHandle(); - } - - @Override - public Horse getBukkitEntity() { - return (Horse) super.getBukkitEntity(); - } -} diff --git a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSEntityImpl.java b/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSEntityImpl.java deleted file mode 100644 index e4e37ed5..00000000 --- a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSEntityImpl.java +++ /dev/null @@ -1,70 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_10_R1; - -import lombok.*; - -import java.util.Objects; - -import com.google.common.collect.ImmutableList; - -import net.minecraft.server.v1_10_R1.DamageSource; -import net.minecraft.server.v1_10_R1.Entity; -import net.techcable.sonarpet.nms.INMS; -import net.techcable.sonarpet.nms.NMSEntity; -import net.techcable.sonarpet.nms.NMSLivingEntity; - -import org.bukkit.entity.Player; - -@RequiredArgsConstructor -public class NMSEntityImpl implements NMSEntity { - @Getter - private final Entity handle; - - // - // Deobfuscated methods - // - - @Override - public boolean damageEntity(net.techcable.sonarpet.nms.DamageSource rawSource, float amount) { - DamageSource damageSource = ((DamageSourceImpl) rawSource).getHandle(); - return getHandle().damageEntity(damageSource, amount); - } - - @Override - public org.bukkit.entity.Entity getBukkitEntity() { - return handle.getBukkitEntity(); - } - - @Override - public ImmutableList getPassengers() { - return ImmutableList.copyOf(handle.passengers.stream() - .map(Entity::getBukkitEntity) - .map(INMS.getInstance()::wrapEntity) - .toArray(NMSEntity[]::new)); - } - - @Override - public int hashCode() { - return handle.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj != null && obj instanceof NMSEntityImpl && ((NMSEntityImpl) obj).handle.equals(this.handle); - } - - @Override - public String toString() { - if (getBukkitEntity() instanceof Player) { - return "NMSPlayer(" + getBukkitEntity().getName() + ")"; - } else { - StringBuilder builder = new StringBuilder("NMSEntity("); - builder.append(getBukkitEntity().getType()); - if (getBukkitEntity().getCustomName() != null) { - builder.append(":"); - builder.append(getBukkitEntity().getCustomName()); - } - builder.append(')'); - return builder.toString(); - } - } -} diff --git a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSEntityInsentientImpl.java b/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSEntityInsentientImpl.java deleted file mode 100644 index 8f4ddf46..00000000 --- a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSEntityInsentientImpl.java +++ /dev/null @@ -1,125 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_10_R1; - -import lombok.*; - -import java.lang.invoke.MethodHandle; -import java.util.Set; - -import com.google.common.collect.ImmutableList; - -import net.minecraft.server.v1_10_R1.EntityInsentient; -import net.minecraft.server.v1_10_R1.EntityLiving; -import net.minecraft.server.v1_10_R1.GenericAttributes; -import net.minecraft.server.v1_10_R1.Navigation; -import net.minecraft.server.v1_10_R1.PathfinderGoalSelector; -import net.minecraft.server.v1_10_R1.SoundEffect; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.pineapple.reflection.Reflection; -import net.techcable.sonarpet.nms.NMSInsentientEntity; -import net.techcable.sonarpet.nms.NMSSound; - -import org.bukkit.Sound; -import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_10_R1.entity.CraftLivingEntity; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; - -public class NMSEntityInsentientImpl extends NMSLivingEntityImpl implements NMSInsentientEntity { - - // - // !!!!! Highly version-dependent !!!!! - // Check these every minor update! - // - - private static final MethodHandle GET_DEATH_SOUND_METHOD_HANDLE = Reflection.getMethod( - EntityLiving.class, - "bV" - ); - - - // - // Breakage likely, check for bugs here - // - - @Override - public float getVerticalFaceSpeed() { - return getHandle().N(); - } - - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - @Override - public void clearGoals() { - PathfinderGoalSelector goalSelector = getHandle().goalSelector; - ImmutableList> fieldsToClear = PineappleField.findFieldsWithType(PathfinderGoalSelector.class, Set.class); - if (fieldsToClear.size() != 2) { - throw new AssertionError("Unexpected number of fields to clear: " + fieldsToClear); - } - for (PineappleField field : fieldsToClear) { - field.get(goalSelector).clear(); - } - } - - @Override - public void lookAt(Entity other, float perTick, float verticalFaceSpeed) { - getHandle().getControllerLook().a(((CraftEntity) other).getHandle(), perTick, verticalFaceSpeed); - } - - @Override - public void jump() { - getHandle().getControllerJump().a(); - } - - @Override - public void setCanSwim(boolean b) { - ((Navigation) getHandle().getNavigation()).c(b); - } - - // - // Deobfuscated methods :) - // - - @Override - public void setFollowRange(double followRange) { - getHandle().getAttributeInstance(GenericAttributes.FOLLOW_RANGE).setValue(followRange); - } - - @Override - public LivingEntity getTarget() { - EntityLiving entity = getHandle().getGoalTarget(); - return entity != null ? (LivingEntity) entity.getBukkitEntity() : null; - } - - @Override - public void setTarget(LivingEntity target) { - getHandle().setGoalTarget(((CraftLivingEntity) target).getHandle()); - } - - @Override - public net.techcable.sonarpet.nms.Navigation getNavigation() { - return new NavigationImpl((Navigation) getHandle().getNavigation()); - } - - // - // Utility methods and wrappers - // - - @Override - public EntityInsentient getHandle() { - return (EntityInsentient) super.getHandle(); - } - - @Override - @SneakyThrows - public NMSSound getDeathSound() { - SoundEffect soundEffect = (SoundEffect) GET_DEATH_SOUND_METHOD_HANDLE.invoke(getHandle()); - return soundEffect != null ? new NMSSoundImpl(soundEffect) : null; - } - - public NMSEntityInsentientImpl(EntityInsentient handle) { - super(handle); - } -} diff --git a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSEntityRegistry.java b/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSEntityRegistry.java deleted file mode 100644 index fb54bc61..00000000 --- a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSEntityRegistry.java +++ /dev/null @@ -1,70 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_10_R1; - -import java.util.Map; -import java.util.Objects; - -import com.google.common.collect.ImmutableList; - -import net.minecraft.server.v1_10_R1.EntityTypes; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.sonarpet.nms.EntityRegistry; -public class NMSEntityRegistry implements EntityRegistry { - private static final PineappleField, String>> CLASS_TO_NAME_FIELD; - private static final PineappleField>> ID_TO_CLASS_FIELD; - private static final PineappleField, Integer>> CLASS_TO_ID_FIELD; - static { - ImmutableList> mapFields = PineappleField.findFieldsWithType(EntityTypes.class, Map.class); - assert mapFields.size() == 5; - //noinspection unchecked - CLASS_TO_NAME_FIELD = (PineappleField) mapFields.get(1); - //noinspection unchecked - ID_TO_CLASS_FIELD = (PineappleField) mapFields.get(2); - //noinspection unchecked - CLASS_TO_ID_FIELD = (PineappleField) mapFields.get(3); - } - - @Override - public void registerEntityClass(Class entityClass, String name, int id) { - CLASS_TO_NAME_FIELD.getStatic().put(entityClass, name); - CLASS_TO_ID_FIELD.getStatic().put(entityClass, id); - } - - @Override - public void unregisterEntityClass(Class entityClass, String name, int id) { - String actualName = CLASS_TO_NAME_FIELD.getStatic().remove(entityClass); - Integer actualId = CLASS_TO_ID_FIELD.getStatic().remove(entityClass); - if (!Objects.equals(name, actualName)) { - throw new IllegalArgumentException("Expected name " + name + " didn't equal actual name " + Objects.toString(actualName)); - } else if (actualId == null || actualId != id) { - throw new IllegalArgumentException("Expected id " + id + " didn't equal actual id " + Objects.toString(actualId)); - } - } - - @Override - public Class getEntityClass(int id) { - return ID_TO_CLASS_FIELD.getStatic().get(id); - } - - @Override - public int getEntityId(Class entityClass) { - return CLASS_TO_ID_FIELD.getStatic().get(entityClass); - } - - @Override - public String getEntityName(Class entityClass) { - return CLASS_TO_NAME_FIELD.getStatic().get(entityClass); - } - - @Override - public void registerEntityId(int id, Class entityClass) { - ID_TO_CLASS_FIELD.getStatic().put(id, entityClass); - } - - @Override - public void unregisterEntityId(int id, Class entityClass) { - Class actualEntityClass = ID_TO_CLASS_FIELD.getStatic().remove(id); - if (!Objects.equals(actualEntityClass, entityClass)) { - throw new IllegalArgumentException("Exepcted entity class " + entityClass + " didn't equal actual entity class " + Objects.toString(actualEntityClass)); - } - } -} diff --git a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSImpl.java b/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSImpl.java deleted file mode 100644 index 095d02cc..00000000 --- a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSImpl.java +++ /dev/null @@ -1,144 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_10_R1; - -import net.minecraft.server.v1_10_R1.EntityHorse; -import net.minecraft.server.v1_10_R1.EntityInsentient; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.sonarpet.nms.DismountingBlocked; -import net.techcable.sonarpet.nms.EntityRegistry; -import net.techcable.sonarpet.nms.INMS; -import com.google.common.collect.ImmutableMap; - -import net.minecraft.server.v1_10_R1.Block; -import net.minecraft.server.v1_10_R1.DamageSource; -import net.minecraft.server.v1_10_R1.EntityHuman; -import net.minecraft.server.v1_10_R1.EntityLiving; -import net.minecraft.server.v1_10_R1.EntityPlayer; -import net.minecraft.server.v1_10_R1.Packet; -import net.minecraft.server.v1_10_R1.PacketPlayOutMount; -import net.minecraft.server.v1_10_R1.SoundEffect; -import net.minecraft.server.v1_10_R1.SoundEffectType; -import net.techcable.sonarpet.item.SpawnEggItemData; -import net.techcable.sonarpet.nms.BlockSoundData; -import net.techcable.sonarpet.nms.NMSEntity; -import net.techcable.sonarpet.nms.NMSInsentientEntity; -import net.techcable.sonarpet.nms.NMSSound; -import net.techcable.sonarpet.nms.versions.v1_10_R1.data.NMSSpawnEggItemData; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.craftbukkit.v1_10_R1.CraftSound; -import org.bukkit.craftbukkit.v1_10_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_10_R1.entity.CraftLivingEntity; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.material.SpawnEgg; - -import static com.google.common.base.Preconditions.*; - -public class NMSImpl implements INMS { - @Override - public SpawnEggItemData createSpawnEggData(byte rawData, ItemMeta meta) { - EntityType entityType = NMSSpawnEggItemData.getSpawnEggEntityTypeIfPresent(meta).orElse(EntityType.fromId(rawData)); - if (entityType == null) entityType = SpawnEggItemData.DEFAULT_TYPE; // 'Fix' broken configs - return new NMSSpawnEggItemData(rawData, meta, entityType); - } - - @Override - public SpawnEggItemData createSpawnEggData(EntityType entityType, ItemMeta meta) { - checkNotNull(entityType, "Null entity type"); - checkNotNull(meta, "Null item meta"); - return new NMSSpawnEggItemData(new SpawnEgg(entityType).getData(), meta, entityType); // Pretend we use metadata to make the code happy - } - - @Override - public void mount(Entity bukkitRider, Entity bukkitVehicle) { - net.minecraft.server.v1_10_R1.Entity rider = ((CraftEntity) bukkitRider).getHandle(); - if (bukkitVehicle == null) { - net.minecraft.server.v1_10_R1.Entity vehicle = rider.getVehicle(); // This is how you *really* get the vehicle :/ - if (rider instanceof DismountingBlocked) { - ((DismountingBlocked) rider).reallyStopRiding();; - } - rider.stopRiding(); - if (vehicle != null) { - Packet packet = new PacketPlayOutMount(vehicle); - for (EntityHuman human : rider.world.players) { - ((EntityPlayer) human).playerConnection.sendPacket(packet); - } - } - } else { - checkArgument(bukkitRider.getWorld().equals(bukkitVehicle.getWorld()), "Rider is in world %s, while vehicle is in world %s", bukkitRider.getWorld().getName(), bukkitVehicle.getWorld().getName()); - net.minecraft.server.v1_10_R1.Entity vehicle = ((CraftEntity) bukkitVehicle).getHandle(); - rider.a(vehicle, true); // !! Obfuscated !! - Packet packet = new PacketPlayOutMount(vehicle); - for (EntityHuman human : rider.world.players) { - ((EntityPlayer) human).playerConnection.sendPacket(packet); - } - } - } - - @Override - public boolean spawnEntity(NMSInsentientEntity wrapper, Location l) { - EntityLiving entity = ((NMSEntityInsentientImpl) wrapper).getHandle(); - entity.spawnIn(((CraftWorld) l.getWorld()).getHandle()); - ((LivingEntity) entity.getBukkitEntity()).setCollidable(false); - entity.setLocation(l.getX(), l.getY(), l.getZ(), l.getYaw(), l.getPitch()); - if (!l.getChunk().isLoaded()) { - l.getChunk().load(); - } - return entity.world.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); - } - - @Override - public net.techcable.sonarpet.nms.DamageSource mobAttackDamageSource(LivingEntity entity) { - return new DamageSourceImpl(DamageSource.mobAttack(((CraftLivingEntity) entity).getHandle())); - } - - @Override - public net.techcable.sonarpet.nms.DamageSource wrapDamageSource(Object handle) { - return new DamageSourceImpl((DamageSource) handle); - } - - @Override - public NMSEntity wrapEntity(Entity entity) { - net.minecraft.server.v1_10_R1.Entity handle = ((CraftEntity) entity).getHandle(); - if (handle instanceof EntityPlayer) { - return new NMSPlayerImpl((EntityPlayer) handle); - } else if (handle instanceof EntityHorse) { - return new NMSEntityHorseImpl((EntityHorse) handle); - } else if (handle instanceof EntityInsentient) { - return new NMSEntityInsentientImpl((EntityInsentient) handle); - } else if (handle instanceof EntityLiving) { - return new NMSLivingEntityImpl((EntityLiving) handle); - } else { - return new NMSEntityImpl(handle); - } - } - - private PineappleField STEP_SOUND_FIELD = PineappleField.create(Block.class, "stepSound", SoundEffectType.class); - @Override - @SuppressWarnings("deprecation") // I know about ur stupid magic value warning mom - public BlockSoundData getBlockSoundData(Material material) { - return new BlockSoundDataImpl(STEP_SOUND_FIELD.get(Block.getById(material.getId()))); - } - - @Override - @SuppressWarnings("deprecation") // I know about ur stupid magic value warning mom - public boolean isLiquid(Material block) { - return Block.getById(block.getId()).getBlockData().getMaterial().isLiquid(); - } - - @Override - public EntityRegistry createDefaultEntityRegistry() { - return new NMSEntityRegistry(); - } - - @Override - public NMSSound getNmsSound(Sound bukkitSound) { - return new NMSSoundImpl(NMSSoundImplKt.getSoundEffect(bukkitSound)); - } -} diff --git a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSLivingEntityImpl.java b/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSLivingEntityImpl.java deleted file mode 100644 index 3a91f156..00000000 --- a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSLivingEntityImpl.java +++ /dev/null @@ -1,181 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_10_R1; - -import net.minecraft.server.v1_10_R1.EntityHuman; -import net.minecraft.server.v1_10_R1.EntityLiving; -import net.minecraft.server.v1_10_R1.SoundEffect; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.sonarpet.nms.DataWatcher; -import net.techcable.sonarpet.nms.NMSLivingEntity; -import net.techcable.sonarpet.nms.NMSSound; - -import org.bukkit.Sound; -import org.bukkit.craftbukkit.v1_10_R1.CraftSound; -import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; - -public class NMSLivingEntityImpl extends NMSEntityImpl implements NMSLivingEntity { - - // - // !!!!! Highly version-dependent !!!!! - // Check these every minor update! - // - public static final String IS_JUMPING_FIELD_NAME = "be"; - - public NMSLivingEntityImpl(EntityLiving handle) { - super(handle); - } - - /** - * Set the 'offsets' for pitch and yaw to the same value as the yaw itself. - * Apparently this is needed to set rotation. - * See EntityLiving.h(FF) for details (method profiler 'headTurn'). - * Note that EntityInsentient overrides h(FF) and delegates to 'EntityAIBodyControl'. - * 'EntityAIBodyControl' is what actually accesses/uses these fields and where the mappings should be fetched. - *

- * Also, these fields have the MCP names 'renderYawOffset' and 'rotationYawHead' - */ - @Override - public void correctYaw() { - getHandle().aO = getHandle().aQ = getHandle().yaw; - } - - @Override - public boolean isInLava() { - return getHandle().aO(); - } - - // - // Breakage likely, check for bugs here - // - - @Override - public void setMoveSpeed(double rideSpeed) { - getHandle().l((float) rideSpeed); - } - - @Override - public void setStepHeight(float stepHeight) { - getHandle().P = stepHeight; - } - - - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - @Override - public void playSound(NMSSound sound, float volume, float pitch) { - getHandle().a(((NMSSoundImpl) sound).getHandle(), volume, pitch); - } - - @Override - public double distanceTo(Entity other) { - return getHandle().h(((CraftEntity) other).getHandle()); - } - - - // - // Deobfuscated methods :) - // - - @Override - public Player findNearbyPlayer(double range) { - EntityHuman player = getHandle().world.findNearbyPlayer(getHandle(), range); - return player == null ? null : (Player) player.getBukkitEntity(); - } - - @Override - public boolean isInvisible() { - return getHandle().isInvisible(); - } - - @Override - public boolean isSneaking() { - return getHandle().isSneaking(); - } - - @Override - public void setSneaking(boolean b) { - getHandle().setSneaking(b); - } - - @Override - public void setInvisible(boolean b) { - getHandle().setInvisible(b); - } - - @Override - public boolean isSprinting() { - return getHandle().isSprinting(); - } - - @Override - public void setSprinting(boolean b) { - getHandle().setSprinting(b); - } - - @Override - public void setYaw(float yaw) { - getHandle().yaw = yaw; - } - - @Override - public void setPitch(float pitch) { - getHandle().pitch = pitch; - } - - @Override - public void setNoClip(boolean b) { - getHandle().noclip = b; - } - - @Override - public boolean isInWater() { - return getHandle().isInWater(); - } - - - @Override - public void setUpwardsMotion(double motY) { - getHandle().motY = motY; - } - - @Override - public DataWatcher getDataWatcher() { - return new DataWatcherImpl(getHandle().getDataWatcher()); - } - - @Override - public double getWidth() { - return getHandle().width; - } - - @Override - public double getLength() { - return getHandle().length; - } - - // - // Utility methods and wrappers - // - - private static final PineappleField IS_JUMPING_FIELD = PineappleField.create(EntityLiving.class, IS_JUMPING_FIELD_NAME, boolean.class); - - @Override - public boolean isJumping() { - return IS_JUMPING_FIELD.getBoxed(getHandle()); - } - - @Override - public EntityLiving getHandle() { - return (EntityLiving) super.getHandle(); - } - - @Override - public LivingEntity getBukkitEntity() { - return (LivingEntity) getHandle().getBukkitEntity(); - } -} diff --git a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSPlayerImpl.java b/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSPlayerImpl.java deleted file mode 100644 index 5812d767..00000000 --- a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSPlayerImpl.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_10_R1; - -import net.minecraft.server.v1_10_R1.EntityPlayer; -import net.techcable.sonarpet.nms.NMSPlayer; - -import org.bukkit.entity.Player; - -public class NMSPlayerImpl extends NMSLivingEntityImpl implements NMSPlayer { - public NMSPlayerImpl(EntityPlayer handle) { - super(handle); - } - - @Override - public boolean isOnGround() { - return getHandle().onGround; - } - - @Override - public EntityPlayer getHandle() { - return (EntityPlayer) super.getHandle(); - } - - @Override - public Player getBukkitEntity() { - return (Player) super.getBukkitEntity(); - } -} diff --git a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/data/NMSSpawnEggItemData.java b/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/data/NMSSpawnEggItemData.java deleted file mode 100644 index 45200acf..00000000 --- a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/data/NMSSpawnEggItemData.java +++ /dev/null @@ -1,86 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_10_R1.data; - -import java.util.Optional; - -import com.google.common.base.Preconditions; - -import net.minecraft.server.v1_10_R1.EntityTypes; -import net.minecraft.server.v1_10_R1.Item; -import net.minecraft.server.v1_10_R1.ItemStack; -import net.minecraft.server.v1_10_R1.NBTTagCompound; -import net.techcable.sonarpet.item.SpawnEggItemData; - -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.craftbukkit.v1_10_R1.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_10_R1.util.CraftMagicNumbers; -import org.bukkit.entity.EntityType; -import org.bukkit.inventory.meta.ItemMeta; - -public class NMSSpawnEggItemData extends SpawnEggItemData { - public NMSSpawnEggItemData(byte rawData, ItemMeta meta) { - this(rawData, meta, SpawnEggItemData.DEFAULT_TYPE); - } - - public NMSSpawnEggItemData(byte rawData, ItemMeta meta, EntityType type) { - super(rawData, createMetaWithEntityType(meta, type)); - } - - @Override - public EntityType getSpawnedType() { - return getSpawnEggEntityType(this.getMeta()); - } - - public static EntityType getSpawnEggEntityType(ItemMeta meta) { - Preconditions.checkNotNull(meta, "Null meta"); - NBTTagCompound tag = getTagFromMeta(Material.MONSTER_EGG, meta); - Preconditions.checkState(tag != null, "No nbt tag"); - Preconditions.checkState(tag.hasKeyOfType("EntityTag", 10), "No entity tag"); - NBTTagCompound entityTag = tag.getCompound("EntityTag"); - Preconditions.checkState(entityTag.hasKeyOfType("id", 8), "No internal name"); - String internalName = entityTag.getString("id"); - int id = EntityTypes.a(internalName); - EntityType type = EntityType.fromId(id); - if (type == null) - throw new IllegalStateException("No entity found with internal name " + internalName + " and id " + id); - return type; - } - - public static Optional getSpawnEggEntityTypeIfPresent(ItemMeta meta) { - try { - return Optional.of(getSpawnEggEntityType(meta)); - } catch (IllegalArgumentException | IllegalStateException e) { - return Optional.empty(); - } - } - - public static ItemMeta createMetaWithEntityType(ItemMeta meta, EntityType entityType) { - NBTTagCompound entityTag = new NBTTagCompound(); - String internalName = EntityTypes.getName(EntityTypes.a(entityType.getTypeId())); - if (internalName == null) throw new AssertionError("Couldn't find internal name for type: " + entityType); - entityTag.setString("id", internalName); - NBTTagCompound tag = getTagFromMeta(Material.MONSTER_EGG, Preconditions.checkNotNull(meta, "Null meta")); - if (tag == null) tag = new NBTTagCompound(); - tag.set("EntityTag", entityTag); - return createMetaFromTag(Material.MONSTER_EGG, tag); - } - - - public static ItemMeta createMetaFromTag(Material type, NBTTagCompound tag) { - Item item = CraftMagicNumbers.getItem(Preconditions.checkNotNull(type, "Null type")); - ItemStack stack = new ItemStack(item); - stack.setTag(Preconditions.checkNotNull(tag, "Null nbt tag")); - return CraftItemStack.getItemMeta(stack); - } - - public static NBTTagCompound getTagFromMeta(Material type, ItemMeta meta) { - Preconditions.checkNotNull(meta, "Null meta"); - Preconditions.checkNotNull(type, "Null type"); - Preconditions.checkArgument(Bukkit.getItemFactory().isApplicable(meta, type), "Meta %s isn't applicable to %s", meta, type); - Item item = CraftMagicNumbers.getItem(type); - ItemStack stack = new ItemStack(item); - boolean worked = CraftItemStack.setItemMeta(stack, meta); - if (!worked) throw new RuntimeException("Didn't work"); - return stack.getTag(); - } -} diff --git a/nms/v1_10_R1/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSSoundImpl.kt b/nms/v1_10_R1/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSSoundImpl.kt deleted file mode 100644 index 9ce7ac31..00000000 --- a/nms/v1_10_R1/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_10_R1/NMSSoundImpl.kt +++ /dev/null @@ -1,21 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_10_R1 - -import net.minecraft.server.v1_10_R1.SoundEffect -import net.techcable.sonarpet.nms.NMSSound -import net.techcable.sonarpet.utils.buildImmutableMap -import org.bukkit.Sound -import org.bukkit.craftbukkit.v1_10_R1.CraftSound - -private val BUKKIT_SOUNDS = buildImmutableMap { - for (sound in enumValues()) { - put(sound.soundEffect, sound) - } -} - -val Sound.soundEffect: SoundEffect - get() = CraftSound.getSoundEffect(CraftSound.getSound(this))!! - -class NMSSoundImpl(val handle: SoundEffect): NMSSound { - override val bukkitSound: Sound? - get() = BUKKIT_SOUNDS[handle] -} \ No newline at end of file diff --git a/nms/v1_11_R1/build.gradle.kts b/nms/v1_11_R1/build.gradle.kts deleted file mode 100644 index 35aaabfd..00000000 --- a/nms/v1_11_R1/build.gradle.kts +++ /dev/null @@ -1,4 +0,0 @@ -dependencies { - compileOnly("org.bukkit:craftbukkit:1.11-R0.1-SNAPSHOT") - compileOnly(project(":api")) -} diff --git a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/BlockSoundDataImpl.java b/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/BlockSoundDataImpl.java deleted file mode 100644 index 14ca9cce..00000000 --- a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/BlockSoundDataImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_11_R1; - -import lombok.*; - -import net.minecraft.server.v1_11_R1.SoundEffectType; -import net.techcable.sonarpet.nms.BlockSoundData; - -@RequiredArgsConstructor -public class BlockSoundDataImpl implements BlockSoundData { - private final SoundEffectType handle; - - @Override - public float getVolume() { - return handle.a(); - } - - @Override - public float getPitch() { - return handle.b(); - } - - @Override - public boolean equals(Object o) { // We need this!! - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - BlockSoundDataImpl that = (BlockSoundDataImpl) o; - - return handle.equals(that.handle); - } - - @Override - public int hashCode() { - return handle.hashCode(); - } -} - diff --git a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/DamageSourceImpl.java b/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/DamageSourceImpl.java deleted file mode 100644 index 84a92464..00000000 --- a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/DamageSourceImpl.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_11_R1; - -import lombok.*; - -import net.minecraft.server.v1_11_R1.DamageSource; - -@RequiredArgsConstructor -public class DamageSourceImpl implements net.techcable.sonarpet.nms.DamageSource { - @Getter - private final DamageSource handle; -} diff --git a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSEntityInsentientImpl.java b/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSEntityInsentientImpl.java deleted file mode 100644 index 46bce34f..00000000 --- a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSEntityInsentientImpl.java +++ /dev/null @@ -1,125 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_11_R1; - -import lombok.*; - -import java.lang.invoke.MethodHandle; -import java.util.Set; - -import com.google.common.collect.ImmutableList; - -import net.minecraft.server.v1_11_R1.EntityInsentient; -import net.minecraft.server.v1_11_R1.EntityLiving; -import net.minecraft.server.v1_11_R1.GenericAttributes; -import net.minecraft.server.v1_11_R1.Navigation; -import net.minecraft.server.v1_11_R1.PathfinderGoalSelector; -import net.minecraft.server.v1_11_R1.SoundEffect; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.pineapple.reflection.Reflection; -import net.techcable.sonarpet.nms.NMSInsentientEntity; -import net.techcable.sonarpet.nms.NMSSound; - -import org.bukkit.Sound; -import org.bukkit.craftbukkit.v1_11_R1.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_11_R1.entity.CraftLivingEntity; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; - -public class NMSEntityInsentientImpl extends NMSLivingEntityImpl implements NMSInsentientEntity { - - // - // !!!!! Highly version-dependent !!!!! - // Check these every minor update! - // - - private static final MethodHandle GET_DEATH_SOUND_METHOD_HANDLE = Reflection.getMethod( - EntityLiving.class, - "bW" // EntityLivingBase.getHurtSound - ); - - - // - // Breakage likely, check for bugs here - // - - @Override - public float getVerticalFaceSpeed() { - return getHandle().N(); - } - - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - @Override - public void clearGoals() { - PathfinderGoalSelector goalSelector = getHandle().goalSelector; - ImmutableList> fieldsToClear = PineappleField.findFieldsWithType(PathfinderGoalSelector.class, Set.class); - if (fieldsToClear.size() != 2) { - throw new AssertionError("Unexpected number of fields to clear: " + fieldsToClear); - } - for (PineappleField field : fieldsToClear) { - field.get(goalSelector).clear(); - } - } - - @Override - public void lookAt(Entity other, float perTick, float verticalFaceSpeed) { - getHandle().getControllerLook().a(((CraftEntity) other).getHandle(), perTick, verticalFaceSpeed); - } - - @Override - public void jump() { - getHandle().getControllerJump().a(); - } - - @Override - public void setCanSwim(boolean b) { - ((Navigation) getHandle().getNavigation()).c(b); - } - - // - // Deobfuscated methods :) - // - - @Override - public void setFollowRange(double followRange) { - getHandle().getAttributeInstance(GenericAttributes.FOLLOW_RANGE).setValue(followRange); - } - - @Override - public LivingEntity getTarget() { - EntityLiving entity = getHandle().getGoalTarget(); - return entity != null ? (LivingEntity) entity.getBukkitEntity() : null; - } - - @Override - public void setTarget(LivingEntity target) { - getHandle().setGoalTarget(((CraftLivingEntity) target).getHandle()); - } - - @Override - public net.techcable.sonarpet.nms.Navigation getNavigation() { - return new NavigationImpl((Navigation) getHandle().getNavigation()); - } - - // - // Utility methods and wrappers - // - - @Override - public EntityInsentient getHandle() { - return (EntityInsentient) super.getHandle(); - } - - @Override - @SneakyThrows - public NMSSound getDeathSound() { - SoundEffect soundEffect = (SoundEffect) GET_DEATH_SOUND_METHOD_HANDLE.invoke(getHandle()); - return soundEffect != null ? new NMSSoundImpl(soundEffect) : null; - } - - public NMSEntityInsentientImpl(EntityInsentient handle) { - super(handle); - } -} diff --git a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSEntityRegistry.java b/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSEntityRegistry.java deleted file mode 100644 index 704b5808..00000000 --- a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSEntityRegistry.java +++ /dev/null @@ -1,63 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_11_R1; - -import lombok.*; - -import java.lang.invoke.MethodHandle; - -import net.minecraft.server.v1_11_R1.Entity; -import net.minecraft.server.v1_11_R1.EntityTypes; -import net.minecraft.server.v1_11_R1.MinecraftKey; -import net.minecraft.server.v1_11_R1.RegistryID; -import net.minecraft.server.v1_11_R1.RegistryMaterials; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.pineapple.reflection.Reflection; -import net.techcable.sonarpet.nms.EntityRegistry; - -public class NMSEntityRegistry implements EntityRegistry { - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - @SuppressWarnings("unchecked") - private final PineappleField>, RegistryID>> REGISTRY_ID_FIELD = - (PineappleField) PineappleField.findFieldWithType(RegistryMaterials.class, RegistryID.class); - private final MethodHandle REGISTER_ENTITY_METHOD = - Reflection.getMethod(EntityTypes.class, "a", int.class, String.class, Class.class, String.class); // EntityList.register - - @Override - @SneakyThrows - public void registerEntityClass(Class entityClass, String name, int id) { - REGISTER_ENTITY_METHOD.invokeExact(id, name, entityClass, name); - } - - @Override - public void unregisterEntityClass(Class entityClass, String name, int id) { - // TODO: unregister - } - - @Override - public Class getEntityClass(int id) { - return REGISTRY_ID_FIELD.get(EntityTypes.b).fromId(id); - } - - @Override - public int getEntityId(Class entityClass) { - return REGISTRY_ID_FIELD.get(EntityTypes.b).getId(entityClass); - } - - @Override - public String getEntityName(Class entityClass) { - return EntityTypes.getName(entityClass.asSubclass(Entity.class)).a(); - } - - @Override - public void registerEntityId(int id, Class entityClass) { - REGISTRY_ID_FIELD.get(EntityTypes.b).a(entityClass, id); // IntIdentityHashBiMap.put - } - - @Override - public void unregisterEntityId(int id, Class entityClass) { - REGISTRY_ID_FIELD.get(EntityTypes.b).a(null, id); // IntIdentityHashBiMap.put - } -} diff --git a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSPlayerImpl.java b/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSPlayerImpl.java deleted file mode 100644 index fe1d80a9..00000000 --- a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSPlayerImpl.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_11_R1; - -import net.minecraft.server.v1_11_R1.EntityPlayer; -import net.techcable.sonarpet.nms.NMSPlayer; - -import org.bukkit.entity.Player; - -public class NMSPlayerImpl extends NMSLivingEntityImpl implements NMSPlayer { - public NMSPlayerImpl(EntityPlayer handle) { - super(handle); - } - - @Override - public boolean isOnGround() { - return getHandle().onGround; - } - - @Override - public EntityPlayer getHandle() { - return (EntityPlayer) super.getHandle(); - } - - @Override - public Player getBukkitEntity() { - return (Player) super.getBukkitEntity(); - } -} diff --git a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NavigationImpl.java b/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NavigationImpl.java deleted file mode 100644 index 1bac4766..00000000 --- a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NavigationImpl.java +++ /dev/null @@ -1,54 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_11_R1; - -import lombok.*; - -import net.minecraft.server.v1_11_R1.Navigation; -import net.techcable.sonarpet.nms.PathEntity; - -import org.bukkit.craftbukkit.v1_11_R1.entity.CraftEntity; -import org.bukkit.entity.Entity; - -@RequiredArgsConstructor -public class NavigationImpl implements net.techcable.sonarpet.nms.Navigation { - private final Navigation handle; - - - // - // Breakage likely, check for bugs here - // - - @Override - public boolean canEnterDoors() { - return handle.f(); // PathNavigateGround.getEnterDoors - } - - @Override - public void finish() { - handle.n(); // PathNavigate.noPath - } - - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - @Override - public PathEntity getPathToLocation(int blockX, int blockY, int blockZ) { - return new PathEntityImpl(handle.a(blockX, blockY, blockZ)); - } - - @Override - public PathEntity getPathTo(Entity other) { - return new PathEntityImpl(handle.a(((CraftEntity) other).getHandle())); - } - - @Override - public void navigateTo(PathEntity path, double speed) { - handle.a(((PathEntityImpl) path).handle, speed); - } - - @RequiredArgsConstructor - private static class PathEntityImpl implements PathEntity { - /* package */ final net.minecraft.server.v1_11_R1.PathEntity handle; - } -} diff --git a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/data/NMSSpawnEggItemData.java b/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/data/NMSSpawnEggItemData.java deleted file mode 100644 index 19831c87..00000000 --- a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/data/NMSSpawnEggItemData.java +++ /dev/null @@ -1,87 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_11_R1.data; - -import java.util.Optional; - -import com.google.common.base.Preconditions; - -import net.minecraft.server.v1_11_R1.EntityTypes; -import net.minecraft.server.v1_11_R1.Item; -import net.minecraft.server.v1_11_R1.ItemStack; -import net.minecraft.server.v1_11_R1.MinecraftKey; -import net.minecraft.server.v1_11_R1.NBTTagCompound; -import net.techcable.sonarpet.item.SpawnEggItemData; - -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.craftbukkit.v1_11_R1.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_11_R1.util.CraftMagicNumbers; -import org.bukkit.entity.EntityType; -import org.bukkit.inventory.meta.ItemMeta; - -public class NMSSpawnEggItemData extends SpawnEggItemData { - public NMSSpawnEggItemData(byte rawData, ItemMeta meta) { - this(rawData, meta, SpawnEggItemData.DEFAULT_TYPE); - } - - public NMSSpawnEggItemData(byte rawData, ItemMeta meta, EntityType type) { - super(rawData, createMetaWithEntityType(meta, type)); - } - - @Override - public EntityType getSpawnedType() { - return getSpawnEggEntityType(this.getMeta()); - } - - public static EntityType getSpawnEggEntityType(ItemMeta meta) { - Preconditions.checkNotNull(meta, "Null meta"); - NBTTagCompound tag = getTagFromMeta(Material.MONSTER_EGG, meta); - Preconditions.checkState(tag != null, "No nbt tag"); - Preconditions.checkState(tag.hasKeyOfType("EntityTag", 10), "No entity tag"); - NBTTagCompound entityTag = tag.getCompound("EntityTag"); - Preconditions.checkState(entityTag.hasKeyOfType("id", 8), "No internal name"); - String internalName = entityTag.getString("id"); - int id = EntityTypes.b.a(EntityTypes.b.get(new MinecraftKey(internalName))); - EntityType type = EntityType.fromId(id); - if (type == null) - throw new IllegalStateException("No entity found with internal name " + internalName + " and id " + id); - return type; - } - - public static Optional getSpawnEggEntityTypeIfPresent(ItemMeta meta) { - try { - return Optional.of(getSpawnEggEntityType(meta)); - } catch (IllegalArgumentException | IllegalStateException e) { - return Optional.empty(); - } - } - - public static ItemMeta createMetaWithEntityType(ItemMeta meta, EntityType entityType) { - NBTTagCompound entityTag = new NBTTagCompound(); - String internalName = EntityTypes.getName(EntityTypes.b.getId(entityType.getTypeId())).b(); - if (internalName == null) throw new AssertionError("Couldn't find internal name for type: " + entityType); - entityTag.setString("id", internalName); - NBTTagCompound tag = getTagFromMeta(Material.MONSTER_EGG, Preconditions.checkNotNull(meta, "Null meta")); - if (tag == null) tag = new NBTTagCompound(); - tag.set("EntityTag", entityTag); - return createMetaFromTag(Material.MONSTER_EGG, tag); - } - - - public static ItemMeta createMetaFromTag(Material type, NBTTagCompound tag) { - Item item = CraftMagicNumbers.getItem(Preconditions.checkNotNull(type, "Null type")); - ItemStack stack = new ItemStack(item); - stack.setTag(Preconditions.checkNotNull(tag, "Null nbt tag")); - return CraftItemStack.getItemMeta(stack); - } - - public static NBTTagCompound getTagFromMeta(Material type, ItemMeta meta) { - Preconditions.checkNotNull(meta, "Null meta"); - Preconditions.checkNotNull(type, "Null type"); - Preconditions.checkArgument(Bukkit.getItemFactory().isApplicable(meta, type), "Meta %s isn't applicable to %s", meta, type); - Item item = CraftMagicNumbers.getItem(type); - ItemStack stack = new ItemStack(item); - boolean worked = CraftItemStack.setItemMeta(stack, meta); - if (!worked) throw new RuntimeException("Didn't work"); - return stack.getTag(); - } -} diff --git a/nms/v1_11_R1/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSSoundImpl.kt b/nms/v1_11_R1/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSSoundImpl.kt deleted file mode 100644 index df0e1bcf..00000000 --- a/nms/v1_11_R1/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSSoundImpl.kt +++ /dev/null @@ -1,21 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_11_R1 - -import net.minecraft.server.v1_11_R1.SoundEffect -import net.techcable.sonarpet.nms.NMSSound -import net.techcable.sonarpet.utils.buildImmutableMap -import org.bukkit.Sound -import org.bukkit.craftbukkit.v1_11_R1.CraftSound - -private val BUKKIT_SOUNDS = buildImmutableMap { - for (sound in enumValues()) { - put(sound.soundEffect, sound) - } -} - -val Sound.soundEffect: SoundEffect - get() = CraftSound.getSoundEffect(CraftSound.getSound(this))!! - -class NMSSoundImpl(val handle: SoundEffect): NMSSound { - override val bukkitSound: Sound? - get() = BUKKIT_SOUNDS[handle] -} \ No newline at end of file diff --git a/nms/v1_12_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_12_R1/NMSImpl.java b/nms/v1_12_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_12_R1/NMSImpl.java index 3a841b64..9f6d9601 100644 --- a/nms/v1_12_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_12_R1/NMSImpl.java +++ b/nms/v1_12_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_12_R1/NMSImpl.java @@ -42,13 +42,6 @@ import static com.google.common.base.Preconditions.*; public class NMSImpl implements INMS { - @Override - public SpawnEggItemData createSpawnEggData(byte rawData, ItemMeta meta) { - EntityType entityType = NMSSpawnEggItemData.getSpawnEggEntityTypeIfPresent(meta).orElse(EntityType.fromId(rawData)); - if (entityType == null) entityType = SpawnEggItemData.DEFAULT_TYPE; // 'Fix' broken configs - return new NMSSpawnEggItemData(rawData, meta, entityType); - } - @Override public SpawnEggItemData createSpawnEggData(EntityType entityType, ItemMeta meta) { checkNotNull(entityType, "Null entity type"); diff --git a/nms/v1_12_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_12_R1/data/NMSSpawnEggItemData.java b/nms/v1_12_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_12_R1/data/NMSSpawnEggItemData.java index 5b0d9c03..389b2eae 100644 --- a/nms/v1_12_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_12_R1/data/NMSSpawnEggItemData.java +++ b/nms/v1_12_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_12_R1/data/NMSSpawnEggItemData.java @@ -24,7 +24,7 @@ public NMSSpawnEggItemData(byte rawData, ItemMeta meta) { } public NMSSpawnEggItemData(byte rawData, ItemMeta meta, EntityType type) { - super(rawData, createMetaWithEntityType(meta, type)); + super(Material.MONSTER_EGG, rawData, createMetaWithEntityType(meta, type)); } @Override diff --git a/nms/v1_13_R2/build.gradle.kts b/nms/v1_13_R2/build.gradle.kts new file mode 100644 index 00000000..297b0f27 --- /dev/null +++ b/nms/v1_13_R2/build.gradle.kts @@ -0,0 +1,5 @@ +dependencies { + // NOTE: We're compiling against paper now, too much hassle to compile Craftbukkit + compileOnly("com.destroystokyo.paper:paper:1.13.1-R0.1-SNAPSHOT") + compileOnly(project(":api")) +} diff --git a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/BlockSoundDataImpl.java b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/BlockSoundDataImpl.java similarity index 80% rename from nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/BlockSoundDataImpl.java rename to nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/BlockSoundDataImpl.java index 9911fba3..9370161b 100644 --- a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/BlockSoundDataImpl.java +++ b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/BlockSoundDataImpl.java @@ -1,8 +1,8 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R2; +package net.techcable.sonarpet.nms.versions.v1_13_R2; import lombok.*; -import net.minecraft.server.v1_9_R2.SoundEffectType; +import net.minecraft.server.v1_13_R2.SoundEffectType; import net.techcable.sonarpet.nms.BlockSoundData; @RequiredArgsConstructor @@ -11,11 +11,13 @@ public class BlockSoundDataImpl implements BlockSoundData { @Override public float getVolume() { + // MCP: SoundType.getVolume return handle.a(); } @Override public float getPitch() { + // MCP: SoundType.getPitch return handle.b(); } diff --git a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/DamageSourceImpl.java b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/DamageSourceImpl.java similarity index 63% rename from nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/DamageSourceImpl.java rename to nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/DamageSourceImpl.java index 58660c8f..ef59f6ed 100644 --- a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/DamageSourceImpl.java +++ b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/DamageSourceImpl.java @@ -1,8 +1,8 @@ -package net.techcable.sonarpet.nms.versions.v1_10_R1; +package net.techcable.sonarpet.nms.versions.v1_13_R2; import lombok.*; -import net.minecraft.server.v1_10_R1.DamageSource; +import net.minecraft.server.v1_13_R2.DamageSource; @RequiredArgsConstructor public class DamageSourceImpl implements net.techcable.sonarpet.nms.DamageSource { diff --git a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/DataWatcherImpl.java b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/DataWatcherImpl.java similarity index 67% rename from nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/DataWatcherImpl.java rename to nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/DataWatcherImpl.java index 4e3624f6..52075b9b 100644 --- a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/DataWatcherImpl.java +++ b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/DataWatcherImpl.java @@ -1,11 +1,11 @@ -package net.techcable.sonarpet.nms.versions.v1_11_R1; +package net.techcable.sonarpet.nms.versions.v1_13_R2; import lombok.*; -import net.minecraft.server.v1_11_R1.DataWatcher; -import net.minecraft.server.v1_11_R1.DataWatcherObject; -import net.minecraft.server.v1_11_R1.DataWatcherRegistry; -import net.minecraft.server.v1_11_R1.DataWatcherSerializer; +import net.minecraft.server.v1_13_R2.DataWatcher; +import net.minecraft.server.v1_13_R2.DataWatcherObject; +import net.minecraft.server.v1_13_R2.DataWatcherRegistry; +import net.minecraft.server.v1_13_R2.DataWatcherSerializer; @RequiredArgsConstructor public class DataWatcherImpl implements net.techcable.sonarpet.nms.DataWatcher { @@ -16,7 +16,9 @@ public class DataWatcherImpl implements net.techcable.sonarpet.nms.DataWatcher { // IE: never broken yet ^_^ // - private static final DataWatcherSerializer BOOLEAN_SERIALIZER = DataWatcherRegistry.h; + // MCP: DataSerializers.BOOLEAN + private static final DataWatcherSerializer BOOLEAN_SERIALIZER = DataWatcherRegistry.i; + // MCP: DataSerializers.VARINT private static final DataWatcherSerializer INTEGER_SERIALIZER = DataWatcherRegistry.b; // diff --git a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSEntityHorseImpl.java b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSEntityHorseImpl.java similarity index 87% rename from nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSEntityHorseImpl.java rename to nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSEntityHorseImpl.java index 15f0232b..81feb5f4 100644 --- a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSEntityHorseImpl.java +++ b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSEntityHorseImpl.java @@ -1,9 +1,9 @@ -package net.techcable.sonarpet.nms.versions.v1_11_R1; +package net.techcable.sonarpet.nms.versions.v1_13_R2; import com.dsh105.echopet.compat.api.entity.HorseType; import com.dsh105.echopet.compat.api.entity.HorseTypeKt; -import net.minecraft.server.v1_11_R1.EntityHorseAbstract; +import net.minecraft.server.v1_13_R2.EntityHorseAbstract; import net.techcable.sonarpet.nms.NMSEntityHorse; import org.bukkit.entity.AbstractHorse; @@ -22,12 +22,12 @@ public NMSEntityHorseImpl(EntityHorseAbstract handle) { @Override public void setSaddled(boolean saddled) { - getHandle().t(saddled); // AbstractHorse.setHorseSaddled + getHandle().x(saddled); // MCP: AbstractHorse.setHorseSaddled } @Override public boolean isSaddled() { - return getHandle().dB(); // AbstractHorse.isHorseSaddled + return getHandle().dV(); // MCP: AbstractHorse.isHorseSaddled } // Deobfuscated methods diff --git a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSEntityImpl.java b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSEntityImpl.java similarity index 92% rename from nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSEntityImpl.java rename to nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSEntityImpl.java index fd98933c..2ad92df0 100644 --- a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSEntityImpl.java +++ b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSEntityImpl.java @@ -1,11 +1,11 @@ -package net.techcable.sonarpet.nms.versions.v1_11_R1; +package net.techcable.sonarpet.nms.versions.v1_13_R2; import lombok.*; import com.google.common.collect.ImmutableList; -import net.minecraft.server.v1_11_R1.DamageSource; -import net.minecraft.server.v1_11_R1.Entity; +import net.minecraft.server.v1_13_R2.DamageSource; +import net.minecraft.server.v1_13_R2.Entity; import net.techcable.sonarpet.nms.INMS; import net.techcable.sonarpet.nms.NMSEntity; diff --git a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSEntityInsentientImpl.java b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSEntityInsentientImpl.java similarity index 80% rename from nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSEntityInsentientImpl.java rename to nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSEntityInsentientImpl.java index 39058dc7..ed8da971 100644 --- a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSEntityInsentientImpl.java +++ b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSEntityInsentientImpl.java @@ -1,4 +1,4 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R2; +package net.techcable.sonarpet.nms.versions.v1_13_R2; import lombok.*; @@ -7,19 +7,14 @@ import com.google.common.collect.ImmutableList; -import net.minecraft.server.v1_9_R2.EntityInsentient; -import net.minecraft.server.v1_9_R2.EntityLiving; -import net.minecraft.server.v1_9_R2.GenericAttributes; -import net.minecraft.server.v1_9_R2.Navigation; -import net.minecraft.server.v1_9_R2.PathfinderGoalSelector; -import net.minecraft.server.v1_9_R2.SoundEffect; +import net.minecraft.server.v1_13_R2.*; import net.techcable.pineapple.reflection.PineappleField; import net.techcable.pineapple.reflection.Reflection; import net.techcable.sonarpet.nms.NMSInsentientEntity; import net.techcable.sonarpet.nms.NMSSound; -import org.bukkit.craftbukkit.v1_9_R2.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_9_R2.entity.CraftLivingEntity; +import org.bukkit.craftbukkit.v1_13_R2.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_13_R2.entity.CraftLivingEntity; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; @@ -32,7 +27,8 @@ public class NMSEntityInsentientImpl extends NMSLivingEntityImpl implements NMSI private static final MethodHandle GET_DEATH_SOUND_METHOD_HANDLE = Reflection.getMethod( EntityLiving.class, - "bT" + "d", // MCP: EntityLivingBase.getHurtSound + DamageSource.class ); @@ -42,7 +38,7 @@ public class NMSEntityInsentientImpl extends NMSLivingEntityImpl implements NMSI @Override public float getVerticalFaceSpeed() { - return getHandle().N(); + return getHandle().K(); // MCP: EntityLiving.getVerticalFaceSpeed } // @@ -74,7 +70,10 @@ public void jump() { @Override public void setCanSwim(boolean b) { - ((Navigation) getHandle().getNavigation()).c(b); + NavigationAbstract navigation = getHandle().getNavigation(); + if (navigation instanceof Navigation) { + ((Navigation) navigation).c(b); + } } // @@ -99,7 +98,7 @@ public void setTarget(LivingEntity target) { @Override public net.techcable.sonarpet.nms.Navigation getNavigation() { - return new NavigationImpl((Navigation) getHandle().getNavigation()); + return new NavigationImpl((NavigationAbstract) getHandle().getNavigation()); } // @@ -114,7 +113,7 @@ public EntityInsentient getHandle() { @Override @SneakyThrows public NMSSound getDeathSound() { - SoundEffect soundEffect = (SoundEffect) GET_DEATH_SOUND_METHOD_HANDLE.invoke(getHandle()); + SoundEffect soundEffect = (SoundEffect) GET_DEATH_SOUND_METHOD_HANDLE.invoke(getHandle(), DamageSource.GENERIC); return soundEffect != null ? new NMSSoundImpl(soundEffect) : null; } diff --git a/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSEntityRegistry.java b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSEntityRegistry.java new file mode 100644 index 00000000..4aad384a --- /dev/null +++ b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSEntityRegistry.java @@ -0,0 +1,120 @@ +package net.techcable.sonarpet.nms.versions.v1_13_R2; + +import com.google.common.base.Preconditions; +import lombok.*; + +import java.lang.invoke.MethodHandle; + +import net.minecraft.server.v1_13_R2.*; +import net.techcable.pineapple.SneakyThrow; +import net.techcable.pineapple.reflection.PineappleField; +import net.techcable.pineapple.reflection.Reflection; +import net.techcable.sonarpet.nms.EntityRegistry; + +public class NMSEntityRegistry implements EntityRegistry { + // + // Very rarely breaks + // Only broken once on 1.13 + // + + /* + * NOTE: Although classes are rarely obfuscated, + * EntityTypes.a should really be EntityTypes.Builder (according to MCP). + * EntityTypes is also a misleading name, + * it should really be EntityType since it represents only a single entity. + */ + @SuppressWarnings("unchecked") + private static final PineappleField>, RegistryID>> REGISTRY_ID_FIELD = + (PineappleField) PineappleField.findFieldWithType(RegistryMaterials.class, RegistryID.class); + private static final MethodHandle REGISTER_ENTITY_METHOD = + Reflection.getMethod(EntityTypes.class, "a", String.class, EntityTypes.a.class); // EntityList.register + + @Override + @SneakyThrows + public void registerEntityClass(Class entityClass, String name, int id) { + /* + * EntityTypes uses the following code to register an entity + * ```` + * AREA_EFFECT_CLOUD = a( + * "area_effect_cloud", + * EntityTypes.a.a( + * EntityAreaEffectCloud.class, + * EntityAreaEffectCloud::new + * ) + * ) + * ``` + * This roughHuhly deobfuscates as + * ```` + * EntityType.register( + * "area_effect_cloud", + * EntityTypes.Builder.create( + * EntityAreaEffectCloud.class, + * EntityAreaEffectClood::new + * ) + * ) + * NOTE: EntityTypes.Builder.create is missing from MCP + * ```` + */ + MethodHandle constructor = Reflection.getConstructor(entityClass, World.class); + // TODO: This seems to use whatever id it wants + REGISTER_ENTITY_METHOD.invoke(name, EntityTypes.a.a( + entityClass.asSubclass(Entity.class), + (world) -> { + try { + return (Entity) constructor.invoke(world); + } catch (Throwable t) { + throw SneakyThrow.sneakyThrow(t); + } + } + )); + } + + @Override + public void unregisterEntityClass(Class entityClass, String name, int id) { + // TODO: unregister + } + + @Override + public int getEntityId(Class entityClass) { + MinecraftKey key = EntityTypes.clsToKeyMap.get(entityClass.asSubclass(Entity.class)); + Preconditions.checkNotNull(key, "Invalid class %s", entityClass); + EntityTypes entityType = IRegistry.ENTITY_TYPE.get(key); + /* + * I was stuck on how to use ids until I looked in the packet system. + * In PacketPlayOutSpawnEntityLiving: `IRegistry.ENTITY_TYPE.a(var1.P())` + * This deobfuscates to `IRegistry.ENTITY_TYPE.getId(var1.getType())` + */ + // MCP: IRegistry.getId + return IRegistry.ENTITY_TYPE.a(entityType); + } + + @Override + public Class getEntityClass(int id) { + EntityTypes entityType = IRegistry.ENTITY_TYPE.fromId(id); + // MCP: EntityType.getEntityClass + return entityType.c(); + } + + + @Override + public String getEntityName(Class entityClass) { + MinecraftKey key = EntityTypes.clsToKeyMap.get(entityClass.asSubclass(Entity.class)); + Preconditions.checkNotNull(key, "Invalid class %s", entityClass); + EntityTypes entityType = IRegistry.ENTITY_TYPE.get(key); + return EntityTypes.getName(entityType).getKey(); + } + + @SuppressWarnings("unchecked") // I am already doing dark magic + @Override + public void registerEntityId(int id, Class entityClass) { + REGISTRY_ID_FIELD.get((RegistryMaterials) IRegistry.ENTITY_TYPE) + .a(entityClass, id); // IntIdentityHashBiMap.put + } + + @SuppressWarnings("unchecked") // I am already doing dark magic + @Override + public void unregisterEntityId(int id, Class entityClass) { + REGISTRY_ID_FIELD.get((RegistryMaterials) IRegistry.ENTITY_TYPE) + .a(null, id); // IntIdentityHashBiMap.put + } +} diff --git a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSImpl.java b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSImpl.java similarity index 56% rename from nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSImpl.java rename to nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSImpl.java index 15a9fcfa..56ca4ec3 100644 --- a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSImpl.java +++ b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSImpl.java @@ -1,67 +1,56 @@ -package net.techcable.sonarpet.nms.versions.v1_11_R1; +package net.techcable.sonarpet.nms.versions.v1_13_R2; -import com.google.common.collect.ImmutableMap; - -import net.minecraft.server.v1_11_R1.Block; -import net.minecraft.server.v1_11_R1.DamageSource; -import net.minecraft.server.v1_11_R1.EntityHorseAbstract; -import net.minecraft.server.v1_11_R1.EntityHuman; -import net.minecraft.server.v1_11_R1.EntityInsentient; -import net.minecraft.server.v1_11_R1.EntityLiving; -import net.minecraft.server.v1_11_R1.EntityPlayer; -import net.minecraft.server.v1_11_R1.Packet; -import net.minecraft.server.v1_11_R1.PacketPlayOutMount; -import net.minecraft.server.v1_11_R1.SoundEffect; -import net.minecraft.server.v1_11_R1.SoundEffectType; +import com.google.common.base.Preconditions; +import lombok.SneakyThrows; +import net.minecraft.server.v1_13_R2.*; +import net.minecraft.server.v1_13_R2.DamageSource; import net.techcable.pineapple.reflection.PineappleField; +import net.techcable.pineapple.reflection.Reflection; +import net.techcable.sonarpet.item.ItemData; import net.techcable.sonarpet.item.SpawnEggItemData; -import net.techcable.sonarpet.nms.BlockSoundData; -import net.techcable.sonarpet.nms.DismountingBlocked; -import net.techcable.sonarpet.nms.EntityRegistry; -import net.techcable.sonarpet.nms.INMS; -import net.techcable.sonarpet.nms.NMSEntity; -import net.techcable.sonarpet.nms.NMSInsentientEntity; -import net.techcable.sonarpet.nms.NMSSound; -import net.techcable.sonarpet.nms.versions.v1_11_R1.data.NMSSpawnEggItemData; - +import net.techcable.sonarpet.nms.*; +import net.techcable.sonarpet.nms.versions.v1_13_R2.data.NMSSpawnEggItemData; +import net.techcable.sonarpet.utils.ModernSpawnEggs; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; -import org.bukkit.craftbukkit.v1_11_R1.CraftSound; -import org.bukkit.craftbukkit.v1_11_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_11_R1.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_11_R1.entity.CraftLivingEntity; +import org.bukkit.craftbukkit.v1_13_R2.CraftWorld; +import org.bukkit.craftbukkit.v1_13_R2.block.data.CraftBlockData; +import org.bukkit.craftbukkit.v1_13_R2.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_13_R2.entity.CraftLivingEntity; +import org.bukkit.craftbukkit.v1_13_R2.util.CraftLegacy; +import org.bukkit.craftbukkit.v1_13_R2.util.CraftMagicNumbers; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.material.SpawnEgg; -import static com.google.common.base.Preconditions.*; +import java.lang.invoke.MethodHandle; +import java.util.Arrays; +import java.util.HashMap; -public class NMSImpl implements INMS { - @Override - public SpawnEggItemData createSpawnEggData(byte rawData, ItemMeta meta) { - EntityType entityType = NMSSpawnEggItemData.getSpawnEggEntityTypeIfPresent(meta).orElse(EntityType.fromId(rawData)); - if (entityType == null) entityType = SpawnEggItemData.DEFAULT_TYPE; // 'Fix' broken configs - return new NMSSpawnEggItemData(rawData, meta, entityType); - } +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +public class NMSImpl implements INMS, IModernNMS { @Override public SpawnEggItemData createSpawnEggData(EntityType entityType, ItemMeta meta) { checkNotNull(entityType, "Null entity type"); checkNotNull(meta, "Null item meta"); - return new NMSSpawnEggItemData(new SpawnEgg(entityType).getData(), meta, entityType); // Pretend we use metadata to make the code happy + if (!ModernSpawnEggs.hasSpawnEgg(entityType)) { + entityType = SpawnEggItemData.DEFAULT_TYPE; + } + return new NMSSpawnEggItemData((byte) 0, meta, entityType); } @Override public void mount(Entity bukkitRider, Entity bukkitVehicle) { - net.minecraft.server.v1_11_R1.Entity rider = ((CraftEntity) bukkitRider).getHandle(); + net.minecraft.server.v1_13_R2.Entity rider = ((CraftEntity) bukkitRider).getHandle(); if (bukkitVehicle == null) { - net.minecraft.server.v1_11_R1.Entity vehicle = rider.getVehicle(); // This is how you *really* get the vehicle :/ + net.minecraft.server.v1_13_R2.Entity vehicle = rider.getVehicle(); // This is how you *really* get the vehicle :/ if (rider instanceof DismountingBlocked) { - ((DismountingBlocked) rider).reallyStopRiding();; + ((DismountingBlocked) rider).reallyStopRiding(); } rider.stopRiding(); if (vehicle != null) { @@ -72,7 +61,7 @@ public void mount(Entity bukkitRider, Entity bukkitVehicle) { } } else { checkArgument(bukkitRider.getWorld().equals(bukkitVehicle.getWorld()), "Rider is in world %s, while vehicle is in world %s", bukkitRider.getWorld().getName(), bukkitVehicle.getWorld().getName()); - net.minecraft.server.v1_11_R1.Entity vehicle = ((CraftEntity) bukkitVehicle).getHandle(); + net.minecraft.server.v1_13_R2.Entity vehicle = ((CraftEntity) bukkitVehicle).getHandle(); rider.a(vehicle, true); // !! Obfuscated !! Packet packet = new PacketPlayOutMount(vehicle); for (EntityHuman human : rider.world.players) { @@ -105,7 +94,7 @@ public net.techcable.sonarpet.nms.DamageSource wrapDamageSource(Object handle) { @Override public NMSEntity wrapEntity(Entity entity) { - net.minecraft.server.v1_11_R1.Entity handle = ((CraftEntity) entity).getHandle(); + net.minecraft.server.v1_13_R2.Entity handle = ((CraftEntity) entity).getHandle(); if (handle instanceof EntityPlayer) { return new NMSPlayerImpl((EntityPlayer) handle); } else if (handle instanceof EntityHorseAbstract) { @@ -123,13 +112,14 @@ public NMSEntity wrapEntity(Entity entity) { @Override @SuppressWarnings("deprecation") // I know about ur stupid magic value warning mom public BlockSoundData getBlockSoundData(Material material) { - return new BlockSoundDataImpl(STEP_SOUND_FIELD.get(Block.getById(material.getId()))); + Block block = Block.getByCombinedId(material.getId()).getBlock(); + return new BlockSoundDataImpl(STEP_SOUND_FIELD.get(block)); } @Override @SuppressWarnings("deprecation") // I know about ur stupid magic value warning mom public boolean isLiquid(Material block) { - return Block.getById(block.getId()).getBlockData().getMaterial().isLiquid(); + return Block.getByCombinedId(block.getId()).getMaterial().isLiquid(); } @Override @@ -141,4 +131,45 @@ public EntityRegistry createDefaultEntityRegistry() { public NMSSound getNmsSound(Sound bukkitSound) { return new NMSSoundImpl(NMSSoundImplKt.getSoundEffect(bukkitSound)); } + + // The isLegacy methods seems to be hidden from us somehow + private static final MethodHandle MATERIAL_IS_LEGACY_METHOD = Reflection.getMethod( + Material.class, + "isLegacy" + ); + @SneakyThrows + private static boolean isLegacy(Material m) { + return (boolean) MATERIAL_IS_LEGACY_METHOD.invokeExact(m); + } + // Looks like this is the best way to do it :( + private static final Material[] LEGACY_MATERIAL_BY_ID; + static { + Material[] byId = new Material[256]; + int maxId = 0; + for (Material m : CraftLegacy.values()) { + if (!isLegacy(m)) continue; + int id = m.getId(); + if (id >= byId.length){ + byId = Arrays.copyOf(byId, id + 128); + } + maxId = Math.max(id, maxId); + } + LEGACY_MATERIAL_BY_ID = Arrays.copyOf(byId, maxId + 1); + } + @Override + public Material getMaterialByLegacyId(int id) { + if (id < LEGACY_MATERIAL_BY_ID.length) { + Material m = LEGACY_MATERIAL_BY_ID[id]; + if (m != null) { + return CraftLegacy.fromLegacy(m); + } + } + throw new IllegalArgumentException("Invalid id: " + id); + } + + @Override + public Object getBukkitBlockData(Material m, byte b) { + IBlockData data = Block.getByCombinedId((m.getId() << 4) | (int) b); + return CraftBlockData.fromData(data); + } } diff --git a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSLivingEntityImpl.java b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSLivingEntityImpl.java similarity index 86% rename from nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSLivingEntityImpl.java rename to nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSLivingEntityImpl.java index f526cfb7..88a79c61 100644 --- a/nms/v1_11_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_11_R1/NMSLivingEntityImpl.java +++ b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSLivingEntityImpl.java @@ -1,16 +1,15 @@ -package net.techcable.sonarpet.nms.versions.v1_11_R1; +package net.techcable.sonarpet.nms.versions.v1_13_R2; -import net.minecraft.server.v1_11_R1.EntityHuman; -import net.minecraft.server.v1_11_R1.EntityLiving; -import net.minecraft.server.v1_11_R1.SoundEffect; +import net.minecraft.server.v1_13_R2.EntityHuman; +import net.minecraft.server.v1_13_R2.EntityLiving; +import net.minecraft.server.v1_13_R2.SoundEffect; import net.techcable.pineapple.reflection.PineappleField; import net.techcable.sonarpet.nms.DataWatcher; import net.techcable.sonarpet.nms.NMSLivingEntity; import net.techcable.sonarpet.nms.NMSSound; -import org.bukkit.Sound; -import org.bukkit.craftbukkit.v1_11_R1.CraftSound; -import org.bukkit.craftbukkit.v1_11_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_13_R2.CraftSound; +import org.bukkit.craftbukkit.v1_13_R2.entity.CraftEntity; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -21,7 +20,7 @@ public class NMSLivingEntityImpl extends NMSEntityImpl implements NMSLivingEntit // !!!!! Highly version-dependent !!!!! // Check these every minor update! // - public static final String IS_JUMPING_FIELD_NAME = "bd"; // EntityLivingBase.isJumping + public static final String IS_JUMPING_FIELD_NAME = "bg"; // EntityLivingBase.isJumping public NMSLivingEntityImpl(EntityLiving handle) { super(handle); @@ -38,12 +37,12 @@ public NMSLivingEntityImpl(EntityLiving handle) { */ @Override public void correctYaw() { - getHandle().aN = getHandle().aP = getHandle().yaw; + getHandle().aQ = getHandle().aS = getHandle().yaw; } @Override public boolean isInLava() { - return getHandle().ao(); // Entity.isInLava + return getHandle().ax(); // MCP: Entity.isInLava } // @@ -52,12 +51,12 @@ public boolean isInLava() { @Override public void setMoveSpeed(double rideSpeed) { - getHandle().l((float) rideSpeed); + getHandle().o((float) rideSpeed); // MCP: EntityLivingBase.setAIMoveSpeed } @Override public void setStepHeight(float stepHeight) { - getHandle().P = stepHeight; + getHandle().Q = stepHeight; // MCP: Entity.stepHeight } diff --git a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSPlayerImpl.java b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSPlayerImpl.java similarity index 83% rename from nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSPlayerImpl.java rename to nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSPlayerImpl.java index 725a1478..f4999eac 100644 --- a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSPlayerImpl.java +++ b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSPlayerImpl.java @@ -1,6 +1,6 @@ -package net.techcable.sonarpet.nms.versions.v1_8_R3; +package net.techcable.sonarpet.nms.versions.v1_13_R2; -import net.minecraft.server.v1_8_R3.EntityPlayer; +import net.minecraft.server.v1_13_R2.EntityPlayer; import net.techcable.sonarpet.nms.NMSPlayer; import org.bukkit.entity.Player; diff --git a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NavigationImpl.java b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NavigationImpl.java similarity index 69% rename from nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NavigationImpl.java rename to nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NavigationImpl.java index 80a73da3..6d124097 100644 --- a/nms/v1_10_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_10_R1/NavigationImpl.java +++ b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/NavigationImpl.java @@ -1,16 +1,17 @@ -package net.techcable.sonarpet.nms.versions.v1_10_R1; +package net.techcable.sonarpet.nms.versions.v1_13_R2; import lombok.*; -import net.minecraft.server.v1_10_R1.Navigation; +import net.minecraft.server.v1_13_R2.Navigation; +import net.minecraft.server.v1_13_R2.NavigationAbstract; import net.techcable.sonarpet.nms.PathEntity; -import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_13_R2.entity.CraftEntity; import org.bukkit.entity.Entity; @RequiredArgsConstructor public class NavigationImpl implements net.techcable.sonarpet.nms.Navigation { - private final Navigation handle; + private final NavigationAbstract handle; // @@ -19,12 +20,12 @@ public class NavigationImpl implements net.techcable.sonarpet.nms.Navigation { @Override public boolean canEnterDoors() { - return handle.f(); + return handle.s().c(); // MCP: PathNavigate.getNodeProcessor().getCanEnterDoors() } @Override public void finish() { - handle.n(); + handle.p(); // MCP: PathNavigate.noPath } // @@ -49,6 +50,6 @@ public void navigateTo(PathEntity path, double speed) { @RequiredArgsConstructor private static class PathEntityImpl implements PathEntity { - /* package */ final net.minecraft.server.v1_10_R1.PathEntity handle; + /* package */ final net.minecraft.server.v1_13_R2.PathEntity handle; } } diff --git a/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/data/NMSSpawnEggItemData.java b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/data/NMSSpawnEggItemData.java new file mode 100644 index 00000000..f7d5a122 --- /dev/null +++ b/nms/v1_13_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_13_R2/data/NMSSpawnEggItemData.java @@ -0,0 +1,35 @@ +package net.techcable.sonarpet.nms.versions.v1_13_R2.data; + +import java.util.Optional; + +import com.google.common.base.Preconditions; + +import net.minecraft.server.v1_13_R2.*; +import net.techcable.sonarpet.item.SpawnEggItemData; + +import net.techcable.sonarpet.utils.ModernSpawnEggs; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_13_R2.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_13_R2.util.CraftMagicNumbers; +import org.bukkit.entity.EntityType; +import org.bukkit.inventory.meta.ItemMeta; + +public class NMSSpawnEggItemData extends SpawnEggItemData { + public NMSSpawnEggItemData(byte rawData, ItemMeta meta, EntityType type) { + super(ModernSpawnEggs.getEggMaterial(type), rawData, meta); + } + + @Override + public EntityType getSpawnedType() { + return ModernSpawnEggs.getSpawnEggType(this.getType()); + } + + + public static ItemMeta create(Material type, NBTTagCompound tag) { + Item item = CraftMagicNumbers.getItem(Preconditions.checkNotNull(type, "Null type")); + ItemStack stack = new ItemStack(item); + stack.setTag(Preconditions.checkNotNull(tag, "Null nbt tag")); + return CraftItemStack.getItemMeta(stack); + } +} diff --git a/nms/v1_9_R2/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSSoundImpl.kt b/nms/v1_13_R2/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSSoundImpl.kt similarity index 77% rename from nms/v1_9_R2/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSSoundImpl.kt rename to nms/v1_13_R2/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSSoundImpl.kt index f0e02c6a..421a368e 100644 --- a/nms/v1_9_R2/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSSoundImpl.kt +++ b/nms/v1_13_R2/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_13_R2/NMSSoundImpl.kt @@ -1,10 +1,10 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R2 +package net.techcable.sonarpet.nms.versions.v1_13_R2 -import net.minecraft.server.v1_9_R2.SoundEffect +import net.minecraft.server.v1_13_R2.SoundEffect import net.techcable.sonarpet.nms.NMSSound import net.techcable.sonarpet.utils.buildImmutableMap import org.bukkit.Sound -import org.bukkit.craftbukkit.v1_9_R2.CraftSound +import org.bukkit.craftbukkit.v1_13_R2.CraftSound private val BUKKIT_SOUNDS = buildImmutableMap { for (sound in enumValues()) { diff --git a/nms/v1_8_R3/build.gradle.kts b/nms/v1_8_R3/build.gradle.kts deleted file mode 100644 index 958dbb0a..00000000 --- a/nms/v1_8_R3/build.gradle.kts +++ /dev/null @@ -1,4 +0,0 @@ -dependencies { - compileOnly("org.bukkit:craftbukkit:1.8.4-R0.1-SNAPSHOT") - compileOnly(project(":api")) -} diff --git a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/BlockSoundDataImpl.java b/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/BlockSoundDataImpl.java deleted file mode 100644 index 87efe4dc..00000000 --- a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/BlockSoundDataImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_8_R3; - -import lombok.*; - -import net.minecraft.server.v1_8_R3.Block; -import net.techcable.sonarpet.nms.BlockSoundData; - -@RequiredArgsConstructor -public class BlockSoundDataImpl implements BlockSoundData { - private final Block.StepSound handle; - - @Override - public float getVolume() { - return handle.getVolume1(); - } - - @Override - public float getPitch() { - return handle.getVolume2(); - } - - @Override - public boolean equals(Object o) { // We need this!! - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - BlockSoundDataImpl that = (BlockSoundDataImpl) o; - - return handle.equals(that.handle); - } - - @Override - public int hashCode() { - return handle.hashCode(); - } -} - diff --git a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/DamageSourceImpl.java b/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/DamageSourceImpl.java deleted file mode 100644 index ca1970b0..00000000 --- a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/DamageSourceImpl.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_8_R3; - -import lombok.*; - -import net.minecraft.server.v1_8_R3.DamageSource; - -@RequiredArgsConstructor -public class DamageSourceImpl implements net.techcable.sonarpet.nms.DamageSource { - @Getter - private final DamageSource handle; -} diff --git a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/DataWatcherImpl.java b/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/DataWatcherImpl.java deleted file mode 100644 index a1e01476..00000000 --- a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/DataWatcherImpl.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_8_R3; - -import lombok.*; - -import net.minecraft.server.v1_8_R3.DataWatcher; - -@RequiredArgsConstructor -public class DataWatcherImpl implements net.techcable.sonarpet.nms.DataWatcher { - private final DataWatcher dataWatcher; - - // - // Deobfuscated methods - // - - @Override - public void setBoolean(int id, boolean value) { - dataWatcher.watch(id, (byte) (value ? 1 : 0)); - } - - @Override - public void setInteger(int id, int value) { - dataWatcher.watch(id, value); - } -} diff --git a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSEntityHorseImpl.java b/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSEntityHorseImpl.java deleted file mode 100644 index 741e8609..00000000 --- a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSEntityHorseImpl.java +++ /dev/null @@ -1,77 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_8_R3; - -import com.dsh105.echopet.compat.api.entity.HorseType; -import com.dsh105.echopet.compat.api.entity.HorseTypeKt; - -import net.minecraft.server.v1_8_R3.EntityHorse; -import net.techcable.sonarpet.nms.NMSEntityHorse; - -import org.bukkit.entity.Horse; - -public class NMSEntityHorseImpl extends NMSEntityInsentientImpl implements NMSEntityHorse { - public NMSEntityHorseImpl(EntityHorse handle) { - super(handle); - } - - // - // !!!!! Highly version-dependent !!!!! - // Check these every minor update! - // - - @Override - public void setSaddled(boolean saddled) { - getHandle().q(saddled); // EntityHorse.setHorseSaddled - } - - @Override - public boolean isSaddled() { - return getHandle().cG(); // EntityHorse.isHorseSaddled - } - - // - // Breakage likely, check for bugs here - // - - @Override - public void setRearing(boolean b) { - // metadata flag with id 64 - getHandle().s(b); - } - - // Deobfuscated methods - - @Override - public void setStyle(Horse.Style bukkitStyle) { - getBukkitEntity().setStyle(bukkitStyle); - } - - @Override - public void setHorseType(HorseType t) { - getBukkitEntity().setVariant(t.getBukkitVariant()); - } - - @Override - public void setColor(Horse.Color color) { - getBukkitEntity().setColor(color); - } - - @Override - public HorseType getHorseType() { - return HorseTypeKt.getSonarType(getBukkitEntity().getVariant()); - } - - @Override - public void setCarryingChest(boolean flag) { - getBukkitEntity().setCarryingChest(flag); - } - - @Override - public EntityHorse getHandle() { - return (EntityHorse) super.getHandle(); - } - - @Override - public Horse getBukkitEntity() { - return (Horse) super.getBukkitEntity(); - } -} diff --git a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSEntityImpl.java b/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSEntityImpl.java deleted file mode 100644 index d46030b5..00000000 --- a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSEntityImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_8_R3; - -import lombok.*; - -import com.google.common.collect.ImmutableList; - -import net.minecraft.server.v1_8_R3.DamageSource; -import net.minecraft.server.v1_8_R3.Entity; -import net.techcable.sonarpet.nms.INMS; -import net.techcable.sonarpet.nms.NMSEntity; - -import org.bukkit.entity.Player; - -@RequiredArgsConstructor -public class NMSEntityImpl implements NMSEntity { - @Getter - private final Entity handle; - - // - // Deobfuscated methods - // - - @Override - public boolean damageEntity(net.techcable.sonarpet.nms.DamageSource rawSource, float amount) { - DamageSource damageSource = ((DamageSourceImpl) rawSource).getHandle(); - return getHandle().damageEntity(damageSource, amount); - } - - @Override - public org.bukkit.entity.Entity getBukkitEntity() { - return handle.getBukkitEntity(); - } - - @Override - public ImmutableList getPassengers() { - if (handle.passenger != null) { - return ImmutableList.of(INMS.getInstance().wrapEntity(handle.passenger.getBukkitEntity())); - } else { - return ImmutableList.of(); - } - } - - @Override - public int hashCode() { - return handle.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj != null && obj instanceof NMSEntityImpl && ((NMSEntityImpl) obj).handle.equals(this.handle); - } - - @Override - public String toString() { - if (getBukkitEntity() instanceof Player) { - return "NMSPlayer(" + getBukkitEntity().getName() + ")"; - } else { - StringBuilder builder = new StringBuilder("NMSEntity("); - builder.append(getBukkitEntity().getType()); - if (getBukkitEntity().getCustomName() != null) { - builder.append(":"); - builder.append(getBukkitEntity().getCustomName()); - } - builder.append(')'); - return builder.toString(); - } - } -} diff --git a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSEntityInsentientImpl.java b/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSEntityInsentientImpl.java deleted file mode 100644 index 7372ec61..00000000 --- a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSEntityInsentientImpl.java +++ /dev/null @@ -1,123 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_8_R3; - -import lombok.*; - -import java.lang.invoke.MethodHandle; -import java.util.List; - -import com.google.common.collect.ImmutableList; - -import net.minecraft.server.v1_8_R3.EntityInsentient; -import net.minecraft.server.v1_8_R3.EntityLiving; -import net.minecraft.server.v1_8_R3.GenericAttributes; -import net.minecraft.server.v1_8_R3.Navigation; -import net.minecraft.server.v1_8_R3.PathfinderGoalSelector; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.pineapple.reflection.Reflection; -import net.techcable.sonarpet.nms.NMSInsentientEntity; -import net.techcable.sonarpet.nms.NMSSound; - -import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_8_R3.entity.CraftLivingEntity; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; - -public class NMSEntityInsentientImpl extends NMSLivingEntityImpl implements NMSInsentientEntity { - - // - // !!!!! Highly version-dependent !!!!! - // Check these every minor update! - // - - private static final MethodHandle GET_DEATH_SOUND_METHOD_HANDLE = Reflection.getMethod( - EntityLiving.class, - "bo" - ); - - - // - // Breakage likely, check for bugs here - // - - @Override - public float getVerticalFaceSpeed() { - return getHandle().bQ(); - } - - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - @Override - public void clearGoals() { - PathfinderGoalSelector goalSelector = getHandle().goalSelector; - ImmutableList> fieldsToClear = PineappleField.findFieldsWithType(PathfinderGoalSelector.class, List.class); - if (fieldsToClear.size() != 2) { - throw new AssertionError("Unexpected number of fields to clear: " + fieldsToClear); - } - for (PineappleField field : fieldsToClear) { - field.get(goalSelector).clear(); - } - } - - @Override - public void lookAt(Entity other, float perTick, float verticalFaceSpeed) { - getHandle().getControllerLook().a(((CraftEntity) other).getHandle(), perTick, verticalFaceSpeed); - } - - @Override - public void jump() { - getHandle().getControllerJump().a(); - } - - @Override - public void setCanSwim(boolean b) { - ((Navigation) getHandle().getNavigation()).c(b); - } - - // - // Deobfuscated methods :) - // - - @Override - public void setFollowRange(double followRange) { - getHandle().getAttributeInstance(GenericAttributes.FOLLOW_RANGE).setValue(followRange); - } - - @Override - public LivingEntity getTarget() { - EntityLiving entity = getHandle().getGoalTarget(); - return entity != null ? (LivingEntity) entity.getBukkitEntity() : null; - } - - @Override - public void setTarget(LivingEntity target) { - getHandle().setGoalTarget(((CraftLivingEntity) target).getHandle()); - } - - @Override - public net.techcable.sonarpet.nms.Navigation getNavigation() { - return new NavigationImpl((Navigation) getHandle().getNavigation()); - } - - // - // Utility methods and wrappers - // - - @Override - public EntityInsentient getHandle() { - return (EntityInsentient) super.getHandle(); - } - - @Override - @SneakyThrows - public NMSSound getDeathSound() { - String soundEffect = (String) GET_DEATH_SOUND_METHOD_HANDLE.invoke(getHandle()); - return soundEffect != null ? new NMSSoundImpl(soundEffect) : null; - } - - public NMSEntityInsentientImpl(EntityInsentient handle) { - super(handle); - } -} diff --git a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSEntityRegistry.java b/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSEntityRegistry.java deleted file mode 100644 index 0abf89be..00000000 --- a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSEntityRegistry.java +++ /dev/null @@ -1,72 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_8_R3; - -import java.util.Map; -import java.util.Objects; - -import com.google.common.collect.ImmutableList; - -import net.minecraft.server.v1_8_R3.EntityTypes; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.sonarpet.nms.EntityRegistry; - -public class NMSEntityRegistry implements EntityRegistry { - private static final PineappleField, String>> CLASS_TO_NAME_FIELD; - private static final PineappleField>> ID_TO_CLASS_FIELD; - private static final PineappleField, Integer>> CLASS_TO_ID_FIELD; - - static { - ImmutableList> mapFields = PineappleField.findFieldsWithType(EntityTypes.class, Map.class); - assert mapFields.size() == 6; - //noinspection unchecked - CLASS_TO_NAME_FIELD = (PineappleField) mapFields.get(1); - //noinspection unchecked - ID_TO_CLASS_FIELD = (PineappleField) mapFields.get(2); - //noinspection unchecked - CLASS_TO_ID_FIELD = (PineappleField) mapFields.get(3); - } - - @Override - public void registerEntityClass(Class entityClass, String name, int id) { - CLASS_TO_NAME_FIELD.getStatic().put(entityClass, name); - CLASS_TO_ID_FIELD.getStatic().put(entityClass, id); - } - - @Override - public void unregisterEntityClass(Class entityClass, String name, int id) { - String actualName = CLASS_TO_NAME_FIELD.getStatic().remove(entityClass); - Integer actualId = CLASS_TO_ID_FIELD.getStatic().remove(entityClass); - if (!Objects.equals(name, actualName)) { - throw new IllegalArgumentException("Expected name " + name + " didn't equal actual name " + Objects.toString(actualName)); - } else if (actualId == null || actualId != id) { - throw new IllegalArgumentException("Expected id " + id + " didn't equal actual id " + Objects.toString(actualId)); - } - } - - @Override - public Class getEntityClass(int id) { - return ID_TO_CLASS_FIELD.getStatic().get(id); - } - - @Override - public int getEntityId(Class entityClass) { - return CLASS_TO_ID_FIELD.getStatic().get(entityClass); - } - - @Override - public String getEntityName(Class entityClass) { - return CLASS_TO_NAME_FIELD.getStatic().get(entityClass); - } - - @Override - public void registerEntityId(int id, Class entityClass) { - ID_TO_CLASS_FIELD.getStatic().put(id, entityClass); - } - - @Override - public void unregisterEntityId(int id, Class entityClass) { - Class actualEntityClass = ID_TO_CLASS_FIELD.getStatic().remove(id); - if (!Objects.equals(actualEntityClass, entityClass)) { - throw new IllegalArgumentException("Expected entity class " + entityClass + " didn't equal actual entity class " + Objects.toString(actualEntityClass)); - } - } -} diff --git a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSImpl.java b/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSImpl.java deleted file mode 100644 index 0e189c8f..00000000 --- a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_8_R3; - -import javax.annotation.Nullable; - -import net.minecraft.server.v1_8_R3.EntityHorse; -import net.minecraft.server.v1_8_R3.EntityInsentient; -import net.minecraft.server.v1_8_R3.EntityPlayer; -import net.techcable.sonarpet.nms.EntityRegistry; -import net.techcable.sonarpet.nms.INMS; -import com.google.common.collect.ImmutableMap; - -import net.minecraft.server.v1_8_R3.Block; -import net.minecraft.server.v1_8_R3.DamageSource; -import net.minecraft.server.v1_8_R3.EntityLiving; -import net.techcable.sonarpet.nms.BlockSoundData; -import net.techcable.sonarpet.nms.NMSEntity; -import net.techcable.sonarpet.nms.NMSInsentientEntity; -import net.techcable.sonarpet.nms.NMSSound; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.craftbukkit.v1_8_R3.CraftSound; -import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; -import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_8_R3.entity.CraftLivingEntity; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.entity.CreatureSpawnEvent; - -public class NMSImpl implements INMS { - @Override - public boolean spawnEntity(NMSInsentientEntity wrapper, Location l) { - EntityLiving entity = ((NMSEntityInsentientImpl) wrapper).getHandle(); - entity.spawnIn(((CraftWorld) l.getWorld()).getHandle()); - entity.setLocation(l.getX(), l.getY(), l.getZ(), l.getYaw(), l.getPitch()); - if (!l.getChunk().isLoaded()) { - l.getChunk().load(); - } - return entity.world.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); - } - - @Override - public net.techcable.sonarpet.nms.DamageSource mobAttackDamageSource(LivingEntity entity) { - return new DamageSourceImpl(DamageSource.mobAttack(((CraftLivingEntity) entity).getHandle())); - } - - @Override - public net.techcable.sonarpet.nms.DamageSource wrapDamageSource(Object handle) { - return new DamageSourceImpl((DamageSource) handle); - } - - @Override - public NMSEntity wrapEntity(Entity entity) { - net.minecraft.server.v1_8_R3.Entity handle = ((CraftEntity) entity).getHandle(); - if (handle instanceof EntityPlayer) { - return new NMSPlayerImpl((EntityPlayer) handle); - } else if (handle instanceof EntityHorse) { - return new NMSEntityHorseImpl((EntityHorse) handle); - } else if (handle instanceof EntityInsentient) { - return new NMSEntityInsentientImpl((EntityInsentient) handle); - } else if (handle instanceof EntityLiving) { - return new NMSLivingEntityImpl((EntityLiving) handle); - } else { - return new NMSEntityImpl(handle); - } - } - - @Override - @SuppressWarnings("deprecation") // I know about ur stupid magic value warning mom - public BlockSoundData getBlockSoundData(Material material) { - return new BlockSoundDataImpl(Block.getById(material.getId()).stepSound); - } - - @Override - @SuppressWarnings("deprecation") // I know about ur stupid magic value warning mom - public boolean isLiquid(Material block) { - return Block.getById(block.getId()).getMaterial().isLiquid(); - } - - @Override - public EntityRegistry createDefaultEntityRegistry() { - return new NMSEntityRegistry(); - } - - @Override - public NMSSound getNmsSound(Sound bukkitSound) { - return new NMSSoundImpl(NMSSoundImplKt.getInternalName(bukkitSound)); - } -} diff --git a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSLivingEntityImpl.java b/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSLivingEntityImpl.java deleted file mode 100644 index 30b2c7fe..00000000 --- a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSLivingEntityImpl.java +++ /dev/null @@ -1,178 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_8_R3; - -import net.minecraft.server.v1_8_R3.EntityHuman; -import net.minecraft.server.v1_8_R3.EntityLiving; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.sonarpet.nms.DataWatcher; -import net.techcable.sonarpet.nms.NMSLivingEntity; -import net.techcable.sonarpet.nms.NMSSound; - -import org.bukkit.Sound; -import org.bukkit.craftbukkit.v1_8_R3.CraftSound; -import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; - -public class NMSLivingEntityImpl extends NMSEntityImpl implements NMSLivingEntity { - - // - // !!!!! Highly version-dependent !!!!! - // Check these every minor update! - // - public static final String IS_JUMPING_FIELD_NAME = "aY"; - - public NMSLivingEntityImpl(EntityLiving handle) { - super(handle); - } - - /** - * Set the 'offsets' for pitch and yaw to the same value as the yaw itself. - * Apparently this is needed to set rotation. - * See EntityLiving.h(FF) for details (method profiler 'headTurn'). - * Note that EntityInsentient overrides h(FF) and delegates to 'EntityAIBodyControl'. - * 'EntityAIBodyControl' is what actually accesses/uses these fields and where the mappings should be fetched. - *

- * Also, these fields have the MCP names 'renderYawOffset' and 'rotationYawHead' - */ - @Override - public void correctYaw() { - getHandle().aK = getHandle().aI = getHandle().yaw; - } - - @Override - public boolean isInLava() { - return getHandle().ab(); - } - - // - // Breakage likely, check for bugs here - // - - @Override - public void setMoveSpeed(double rideSpeed) { - getHandle().k((float) rideSpeed); - } - - @Override - public void setStepHeight(float stepHeight) { - getHandle().S = stepHeight; - } - - - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - @Override - public boolean isInWater() { - return getHandle().V(); - } - - @Override - public double distanceTo(Entity other) { - return getHandle().h(((CraftEntity) other).getHandle()); - } - - // - // Deobfuscated methods :) - // - - @Override - public void playSound(NMSSound sound, float volume, float pitch) { - getHandle().makeSound(((NMSSoundImpl) sound).getInternalName(), volume, pitch); - } - - @Override - public Player findNearbyPlayer(double range) { - EntityHuman player = getHandle().world.findNearbyPlayer(getHandle(), range); - return player == null ? null : (Player) player.getBukkitEntity(); - } - - @Override - public boolean isInvisible() { - return getHandle().isInvisible(); - } - - @Override - public boolean isSneaking() { - return getHandle().isSneaking(); - } - - @Override - public void setSneaking(boolean b) { - getHandle().setSneaking(b); - } - - @Override - public void setInvisible(boolean b) { - getHandle().setInvisible(b); - } - - @Override - public boolean isSprinting() { - return getHandle().isSprinting(); - } - - @Override - public void setSprinting(boolean b) { - getHandle().setSprinting(b); - } - - @Override - public void setYaw(float yaw) { - getHandle().yaw = yaw; - } - - @Override - public void setPitch(float pitch) { - getHandle().pitch = pitch; - } - - @Override - public void setNoClip(boolean b) { - getHandle().noclip = b; - } - - @Override - public void setUpwardsMotion(double motY) { - getHandle().motY = motY; - } - - @Override - public DataWatcher getDataWatcher() { - return new DataWatcherImpl(getHandle().getDataWatcher()); - } - - @Override - public double getWidth() { - return getHandle().width; - } - - @Override - public double getLength() { - return getHandle().length; - } - - // - // Utility methods and wrappers - // - - private static final PineappleField IS_JUMPING_FIELD = PineappleField.create(EntityLiving.class, IS_JUMPING_FIELD_NAME, boolean.class); - - @Override - public boolean isJumping() { - return IS_JUMPING_FIELD.getBoxed(getHandle()); - } - - @Override - public EntityLiving getHandle() { - return (EntityLiving) super.getHandle(); - } - - @Override - public LivingEntity getBukkitEntity() { - return (LivingEntity) getHandle().getBukkitEntity(); - } -} diff --git a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NavigationImpl.java b/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NavigationImpl.java deleted file mode 100644 index ec66f9a8..00000000 --- a/nms/v1_8_R3/src/main/java/net/techcable/sonarpet/nms/versions/v1_8_R3/NavigationImpl.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_8_R3; - -import lombok.*; - -import net.minecraft.server.v1_8_R3.Navigation; -import net.techcable.sonarpet.nms.PathEntity; - -import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; -import org.bukkit.entity.Entity; - -@RequiredArgsConstructor -public class NavigationImpl implements net.techcable.sonarpet.nms.Navigation { - private final Navigation handle; - - // - // Breakage likely, check for bugs here - // - - @Override - public boolean canEnterDoors() { - return handle.g(); - } - - @Override - public void finish() { - handle.n(); - } - - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - @Override - public PathEntity getPathToLocation(int blockX, int blockY, int blockZ) { - return new PathEntityImpl(handle.a(blockX, blockY, blockZ)); - } - - @Override - public PathEntity getPathTo(Entity other) { - return new PathEntityImpl(handle.a(((CraftEntity) other).getHandle())); - } - - @Override - public void navigateTo(PathEntity path, double speed) { - handle.a(((PathEntityImpl) path).handle, speed); - } - - @RequiredArgsConstructor - private static class PathEntityImpl implements PathEntity { - /* package */ final net.minecraft.server.v1_8_R3.PathEntity handle; - } -} diff --git a/nms/v1_8_R3/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSSoundImpl.kt b/nms/v1_8_R3/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSSoundImpl.kt deleted file mode 100644 index 2d2cf2ff..00000000 --- a/nms/v1_8_R3/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_8_R3/NMSSoundImpl.kt +++ /dev/null @@ -1,20 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_8_R3 - -import net.techcable.sonarpet.nms.NMSSound -import net.techcable.sonarpet.utils.buildImmutableMap -import org.bukkit.Sound -import org.bukkit.craftbukkit.v1_8_R3.CraftSound - -private val BUKKIT_SOUNDS = buildImmutableMap { - for (sound in enumValues()) { - put(sound.internalName, sound) - } -} - -val Sound.internalName: String - get() = CraftSound.getSound(this)!! - -class NMSSoundImpl(val internalName: String): NMSSound { - override val bukkitSound: Sound? - get() = BUKKIT_SOUNDS[internalName] -} \ No newline at end of file diff --git a/nms/v1_9_R1/build.gradle.kts b/nms/v1_9_R1/build.gradle.kts deleted file mode 100644 index 1feed895..00000000 --- a/nms/v1_9_R1/build.gradle.kts +++ /dev/null @@ -1,7 +0,0 @@ -dependencies { - compileOnly("org.bukkit:bukkit:1.9-R0.1-SNAPSHOT") // Override the version of bukkit - compileOnly("org.bukkit:craftbukkit:1.9-R0.1-SNAPSHOT") { - exclude(mapOf("module" to "bukkit")) - } - compileOnly(project(":api")) -} diff --git a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/BlockSoundDataImpl.java b/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/BlockSoundDataImpl.java deleted file mode 100644 index c72409a5..00000000 --- a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/BlockSoundDataImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R1; - -import lombok.*; - -import net.minecraft.server.v1_9_R1.SoundEffectType; -import net.techcable.sonarpet.nms.BlockSoundData; - -@RequiredArgsConstructor -public class BlockSoundDataImpl implements BlockSoundData { - private final SoundEffectType handle; - - @Override - public float getVolume() { - return handle.a(); - } - - @Override - public float getPitch() { - return handle.b(); - } - - @Override - public boolean equals(Object o) { // We need this!! - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - BlockSoundDataImpl that = (BlockSoundDataImpl) o; - - return handle.equals(that.handle); - } - - @Override - public int hashCode() { - return handle.hashCode(); - } -} - diff --git a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/DamageSourceImpl.java b/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/DamageSourceImpl.java deleted file mode 100644 index a6dd75fd..00000000 --- a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/DamageSourceImpl.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R1; - -import lombok.*; - -import net.minecraft.server.v1_9_R1.DamageSource; - -@RequiredArgsConstructor -public class DamageSourceImpl implements net.techcable.sonarpet.nms.DamageSource { - @Getter - private final DamageSource handle; -} diff --git a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/DataWatcherImpl.java b/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/DataWatcherImpl.java deleted file mode 100644 index 549b7cb7..00000000 --- a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/DataWatcherImpl.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R1; - -import lombok.*; - -import net.minecraft.server.v1_9_R1.DataWatcher; -import net.minecraft.server.v1_9_R1.DataWatcherObject; -import net.minecraft.server.v1_9_R1.DataWatcherRegistry; -import net.minecraft.server.v1_9_R1.DataWatcherSerializer; - -@RequiredArgsConstructor -public class DataWatcherImpl implements net.techcable.sonarpet.nms.DataWatcher { - private final DataWatcher dataWatcher; - - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - private static final DataWatcherSerializer BOOLEAN_SERIALIZER = DataWatcherRegistry.h; - private static final DataWatcherSerializer INTEGER_SERIALIZER = DataWatcherRegistry.b; - - // - // Deobfuscated methods - // - - @Override - public void setBoolean(int id, boolean value) { - dataWatcher.set(new DataWatcherObject<>(id, BOOLEAN_SERIALIZER), value); - } - - @Override - public void setInteger(int id, int value) { - dataWatcher.set(new DataWatcherObject<>(id, INTEGER_SERIALIZER), value); - } -} diff --git a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSEntityHorseImpl.java b/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSEntityHorseImpl.java deleted file mode 100644 index b83e0934..00000000 --- a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSEntityHorseImpl.java +++ /dev/null @@ -1,77 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R1; - -import com.dsh105.echopet.compat.api.entity.HorseType; -import com.dsh105.echopet.compat.api.entity.HorseTypeKt; - -import net.minecraft.server.v1_9_R1.EntityHorse; -import net.techcable.sonarpet.nms.NMSEntityHorse; - -import org.bukkit.entity.Horse; - -public class NMSEntityHorseImpl extends NMSEntityInsentientImpl implements NMSEntityHorse { - public NMSEntityHorseImpl(EntityHorse handle) { - super(handle); - } - - // - // !!!!! Highly version-dependent !!!!! - // Check these every minor update! - // - - @Override - public void setSaddled(boolean saddled) { - getHandle().t(saddled); // EntityHorse.setHorseSaddled - } - - @Override - public boolean isSaddled() { - return getHandle().du(); // EntityHorse.isHorseSaddled - } - - // - // Breakage likely, check for bugs here - // - - @Override - public void setRearing(boolean b) { - // metadata flag with id 64 - getHandle().v(b); - } - - // Deobfuscated methods - - @Override - public void setStyle(Horse.Style bukkitStyle) { - getBukkitEntity().setStyle(bukkitStyle); - } - - @Override - public void setHorseType(HorseType t) { - getBukkitEntity().setVariant(t.getBukkitVariant()); - } - - @Override - public void setColor(Horse.Color color) { - getBukkitEntity().setColor(color); - } - - @Override - public HorseType getHorseType() { - return HorseTypeKt.getSonarType(getBukkitEntity().getVariant()); - } - - @Override - public void setCarryingChest(boolean flag) { - getBukkitEntity().setCarryingChest(flag); - } - - @Override - public EntityHorse getHandle() { - return (EntityHorse) super.getHandle(); - } - - @Override - public Horse getBukkitEntity() { - return (Horse) super.getBukkitEntity(); - } -} diff --git a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSEntityImpl.java b/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSEntityImpl.java deleted file mode 100644 index e31a1838..00000000 --- a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSEntityImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R1; - -import lombok.*; - -import com.google.common.collect.ImmutableList; - -import net.minecraft.server.v1_9_R1.DamageSource; -import net.minecraft.server.v1_9_R1.Entity; -import net.techcable.sonarpet.nms.INMS; -import net.techcable.sonarpet.nms.NMSEntity; -import net.techcable.sonarpet.nms.NMSLivingEntity; - -import org.bukkit.entity.Player; - -@RequiredArgsConstructor -public class NMSEntityImpl implements NMSEntity { - @Getter - private final Entity handle; - - // - // Deobfuscated methods - // - - @Override - public boolean damageEntity(net.techcable.sonarpet.nms.DamageSource rawSource, float amount) { - DamageSource damageSource = ((DamageSourceImpl) rawSource).getHandle(); - return getHandle().damageEntity(damageSource, amount); - } - - @Override - public org.bukkit.entity.Entity getBukkitEntity() { - return handle.getBukkitEntity(); - } - - @Override - public ImmutableList getPassengers() { - return ImmutableList.copyOf(handle.passengers.stream() - .map(Entity::getBukkitEntity) - .map(INMS.getInstance()::wrapEntity) - .toArray(NMSEntity[]::new)); - } - - @Override - public int hashCode() { - return handle.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj != null && obj instanceof NMSEntityImpl && ((NMSEntityImpl) obj).handle.equals(this.handle); - } - - @Override - public String toString() { - if (getBukkitEntity() instanceof Player) { - return "NMSPlayer(" + getBukkitEntity().getName() + ")"; - } else { - StringBuilder builder = new StringBuilder("NMSEntity("); - builder.append(getBukkitEntity().getType()); - if (getBukkitEntity().getCustomName() != null) { - builder.append(":"); - builder.append(getBukkitEntity().getCustomName()); - } - builder.append(')'); - return builder.toString(); - } - } -} diff --git a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSEntityInsentientImpl.java b/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSEntityInsentientImpl.java deleted file mode 100644 index 33b78058..00000000 --- a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSEntityInsentientImpl.java +++ /dev/null @@ -1,124 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R1; - -import lombok.*; - -import java.lang.invoke.MethodHandle; -import java.util.Set; - -import com.google.common.collect.ImmutableList; - -import net.minecraft.server.v1_9_R1.EntityInsentient; -import net.minecraft.server.v1_9_R1.EntityLiving; -import net.minecraft.server.v1_9_R1.GenericAttributes; -import net.minecraft.server.v1_9_R1.Navigation; -import net.minecraft.server.v1_9_R1.PathfinderGoalSelector; -import net.minecraft.server.v1_9_R1.SoundEffect; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.pineapple.reflection.Reflection; -import net.techcable.sonarpet.nms.NMSInsentientEntity; -import net.techcable.sonarpet.nms.NMSSound; - -import org.bukkit.craftbukkit.v1_9_R1.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_9_R1.entity.CraftLivingEntity; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; - -public class NMSEntityInsentientImpl extends NMSLivingEntityImpl implements NMSInsentientEntity { - - // - // !!!!! Highly version-dependent !!!!! - // Check these every minor update! - // - - private static final MethodHandle GET_DEATH_SOUND_METHOD_HANDLE = Reflection.getMethod( - EntityLiving.class, - "bS" - ); - - - // - // Breakage likely, check for bugs here - // - - @Override - public float getVerticalFaceSpeed() { - return getHandle().N(); - } - - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - @Override - public void clearGoals() { - PathfinderGoalSelector goalSelector = getHandle().goalSelector; - ImmutableList> fieldsToClear = PineappleField.findFieldsWithType(PathfinderGoalSelector.class, Set.class); - if (fieldsToClear.size() != 2) { - throw new AssertionError("Unexpected number of fields to clear: " + fieldsToClear); - } - for (PineappleField field : fieldsToClear) { - field.get(goalSelector).clear(); - } - } - - @Override - public void lookAt(Entity other, float perTick, float verticalFaceSpeed) { - getHandle().getControllerLook().a(((CraftEntity) other).getHandle(), perTick, verticalFaceSpeed); - } - - @Override - public void jump() { - getHandle().getControllerJump().a(); - } - - @Override - public void setCanSwim(boolean b) { - ((Navigation) getHandle().getNavigation()).c(b); - } - - // - // Deobfuscated methods :) - // - - @Override - public void setFollowRange(double followRange) { - getHandle().getAttributeInstance(GenericAttributes.FOLLOW_RANGE).setValue(followRange); - } - - @Override - public LivingEntity getTarget() { - EntityLiving entity = getHandle().getGoalTarget(); - return entity != null ? (LivingEntity) entity.getBukkitEntity() : null; - } - - @Override - public void setTarget(LivingEntity target) { - getHandle().setGoalTarget(((CraftLivingEntity) target).getHandle()); - } - - @Override - public net.techcable.sonarpet.nms.Navigation getNavigation() { - return new NavigationImpl((Navigation) getHandle().getNavigation()); - } - - // - // Utility methods and wrappers - // - - @Override - public EntityInsentient getHandle() { - return (EntityInsentient) super.getHandle(); - } - - @Override - @SneakyThrows - public NMSSound getDeathSound() { - SoundEffect soundEffect = (SoundEffect) GET_DEATH_SOUND_METHOD_HANDLE.invoke(getHandle()); - return soundEffect != null ? new NMSSoundImpl(soundEffect) : null; - } - - public NMSEntityInsentientImpl(EntityInsentient handle) { - super(handle); - } -} diff --git a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSEntityRegistry.java b/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSEntityRegistry.java deleted file mode 100644 index fd9a12be..00000000 --- a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSEntityRegistry.java +++ /dev/null @@ -1,72 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R1; - -import java.util.Map; -import java.util.Objects; - -import com.google.common.collect.ImmutableList; - -import net.minecraft.server.v1_9_R1.EntityTypes; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.sonarpet.nms.EntityRegistry; - -public class NMSEntityRegistry implements EntityRegistry { - private static final PineappleField, String>> CLASS_TO_NAME_FIELD; - private static final PineappleField>> ID_TO_CLASS_FIELD; - private static final PineappleField, Integer>> CLASS_TO_ID_FIELD; - - static { - ImmutableList> mapFields = PineappleField.findFieldsWithType(EntityTypes.class, Map.class); - assert mapFields.size() == 5; - //noinspection unchecked - CLASS_TO_NAME_FIELD = (PineappleField) mapFields.get(1); - //noinspection unchecked - ID_TO_CLASS_FIELD = (PineappleField) mapFields.get(2); - //noinspection unchecked - CLASS_TO_ID_FIELD = (PineappleField) mapFields.get(3); - } - - @Override - public void registerEntityClass(Class entityClass, String name, int id) { - CLASS_TO_NAME_FIELD.getStatic().put(entityClass, name); - CLASS_TO_ID_FIELD.getStatic().put(entityClass, id); - } - - @Override - public void unregisterEntityClass(Class entityClass, String name, int id) { - String actualName = CLASS_TO_NAME_FIELD.getStatic().remove(entityClass); - Integer actualId = CLASS_TO_ID_FIELD.getStatic().remove(entityClass); - if (!Objects.equals(name, actualName)) { - throw new IllegalArgumentException("Expected name " + name + " didn't equal actual name " + Objects.toString(actualName)); - } else if (actualId == null || actualId != id) { - throw new IllegalArgumentException("Expected id " + id + " didn't equal actual id " + Objects.toString(actualId)); - } - } - - @Override - public Class getEntityClass(int id) { - return ID_TO_CLASS_FIELD.getStatic().get(id); - } - - @Override - public int getEntityId(Class entityClass) { - return CLASS_TO_ID_FIELD.getStatic().get(entityClass); - } - - @Override - public String getEntityName(Class entityClass) { - return CLASS_TO_NAME_FIELD.getStatic().get(entityClass); - } - - @Override - public void registerEntityId(int id, Class entityClass) { - ID_TO_CLASS_FIELD.getStatic().put(id, entityClass); - } - - @Override - public void unregisterEntityId(int id, Class entityClass) { - Class actualEntityClass = ID_TO_CLASS_FIELD.getStatic().remove(id); - if (!Objects.equals(actualEntityClass, entityClass)) { - throw new IllegalArgumentException("Exepcted entity class " + entityClass + " didn't equal actual entity class " + Objects.toString(actualEntityClass)); - } - } -} diff --git a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSImpl.java b/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSImpl.java deleted file mode 100644 index e70678be..00000000 --- a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSImpl.java +++ /dev/null @@ -1,145 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R1; - -import net.minecraft.server.v1_9_R1.EntityHorse; -import net.minecraft.server.v1_9_R1.EntityInsentient; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.sonarpet.nms.DismountingBlocked; -import net.techcable.sonarpet.nms.EntityRegistry; -import net.techcable.sonarpet.nms.INMS; -import com.google.common.collect.ImmutableMap; - -import net.minecraft.server.v1_9_R1.Block; -import net.minecraft.server.v1_9_R1.DamageSource; -import net.minecraft.server.v1_9_R1.EntityHuman; -import net.minecraft.server.v1_9_R1.EntityLiving; -import net.minecraft.server.v1_9_R1.EntityPlayer; -import net.minecraft.server.v1_9_R1.Packet; -import net.minecraft.server.v1_9_R1.PacketPlayOutMount; -import net.minecraft.server.v1_9_R1.SoundEffect; -import net.minecraft.server.v1_9_R1.SoundEffectType; -import net.techcable.sonarpet.item.SpawnEggItemData; -import net.techcable.sonarpet.nms.BlockSoundData; -import net.techcable.sonarpet.nms.NMSEntity; -import net.techcable.sonarpet.nms.NMSInsentientEntity; -import net.techcable.sonarpet.nms.NMSSound; -import net.techcable.sonarpet.nms.versions.v1_9_R1.data.NMSSpawnEggItemData; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.craftbukkit.v1_9_R1.CraftSound; -import org.bukkit.craftbukkit.v1_9_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_9_R1.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_9_R1.entity.CraftLivingEntity; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.material.SpawnEgg; - -import static com.google.common.base.Preconditions.*; - -public class NMSImpl implements INMS { - @Override - public SpawnEggItemData createSpawnEggData(byte rawData, ItemMeta meta) { - EntityType entityType = NMSSpawnEggItemData.getSpawnEggEntityTypeIfPresent(meta).orElse(EntityType.fromId(rawData)); - if (entityType == null) entityType = SpawnEggItemData.DEFAULT_TYPE; // 'Fix' broken configs - return new NMSSpawnEggItemData(rawData, meta, entityType); - } - - @Override - public SpawnEggItemData createSpawnEggData(EntityType entityType, ItemMeta meta) { - checkNotNull(entityType, "Null entity type"); - checkNotNull(meta, "Null item meta"); - return new NMSSpawnEggItemData(new SpawnEgg(entityType).getData(), meta, entityType); // Pretend we use metadata to make the code happy - } - - @Override - public void mount(Entity bukkitRider, Entity bukkitVehicle) { - net.minecraft.server.v1_9_R1.Entity rider = ((CraftEntity) bukkitRider).getHandle(); - if (bukkitVehicle == null) { - net.minecraft.server.v1_9_R1.Entity vehicle = rider.getVehicle(); // This is how you *really* get the vehicle :/ - if (rider instanceof DismountingBlocked) { - ((DismountingBlocked) rider).reallyStopRiding(); - } else { - rider.stopRiding(); - } - if (vehicle != null) { - Packet packet = new PacketPlayOutMount(vehicle); - for (EntityHuman human : rider.world.players) { - ((EntityPlayer) human).playerConnection.sendPacket(packet); - } - } - } else { - checkArgument(bukkitRider.getWorld().equals(bukkitVehicle.getWorld()), "Rider is in world %s, while vehicle is in world %s", bukkitRider.getWorld().getName(), bukkitVehicle.getWorld().getName()); - net.minecraft.server.v1_9_R1.Entity vehicle = ((CraftEntity) bukkitVehicle).getHandle(); - rider.a(vehicle, true); // !! Obfuscated !! - Packet packet = new PacketPlayOutMount(vehicle); - for (EntityHuman human : rider.world.players) { - ((EntityPlayer) human).playerConnection.sendPacket(packet); - } - } - } - - @Override - public boolean spawnEntity(NMSInsentientEntity wrapper, Location l) { - EntityLiving entity = ((NMSEntityInsentientImpl) wrapper).getHandle(); - entity.spawnIn(((CraftWorld) l.getWorld()).getHandle()); - ((LivingEntity) entity.getBukkitEntity()).setCollidable(false); - entity.setLocation(l.getX(), l.getY(), l.getZ(), l.getYaw(), l.getPitch()); - if (!l.getChunk().isLoaded()) { - l.getChunk().load(); - } - return entity.world.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); - } - - @Override - public net.techcable.sonarpet.nms.DamageSource mobAttackDamageSource(LivingEntity entity) { - return new DamageSourceImpl(DamageSource.mobAttack(((CraftLivingEntity) entity).getHandle())); - } - - @Override - public net.techcable.sonarpet.nms.DamageSource wrapDamageSource(Object handle) { - return new DamageSourceImpl((DamageSource) handle); - } - - @Override - public NMSEntity wrapEntity(Entity entity) { - net.minecraft.server.v1_9_R1.Entity handle = ((CraftEntity) entity).getHandle(); - if (handle instanceof EntityPlayer) { - return new NMSPlayerImpl((EntityPlayer) handle); - } else if (handle instanceof EntityHorse) { - return new NMSEntityHorseImpl((EntityHorse) handle); - } else if (handle instanceof EntityInsentient) { - return new NMSEntityInsentientImpl((EntityInsentient) handle); - } else if (handle instanceof EntityLiving) { - return new NMSLivingEntityImpl((EntityLiving) handle); - } else { - return new NMSEntityImpl(handle); - } - } - - private PineappleField STEP_SOUND_FIELD = PineappleField.create(Block.class, "stepSound", SoundEffectType.class); - @Override - @SuppressWarnings("deprecation") // I know about ur stupid magic value warning mom - public BlockSoundData getBlockSoundData(Material material) { - return new BlockSoundDataImpl(STEP_SOUND_FIELD.get(Block.getById(material.getId()))); - } - - @Override - @SuppressWarnings("deprecation") // I know about ur stupid magic value warning mom - public boolean isLiquid(Material block) { - return Block.getById(block.getId()).getBlockData().getMaterial().isLiquid(); - } - - @Override - public EntityRegistry createDefaultEntityRegistry() { - return new NMSEntityRegistry(); - } - - @Override - public NMSSound getNmsSound(Sound bukkitSound) { - return new NMSSoundImpl(NMSSoundImplKt.getSoundEffect(bukkitSound)); - } -} diff --git a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSLivingEntityImpl.java b/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSLivingEntityImpl.java deleted file mode 100644 index e39e8e5a..00000000 --- a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSLivingEntityImpl.java +++ /dev/null @@ -1,181 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R1; - -import net.minecraft.server.v1_9_R1.EntityHuman; -import net.minecraft.server.v1_9_R1.EntityLiving; -import net.minecraft.server.v1_9_R1.SoundEffect; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.sonarpet.nms.DataWatcher; -import net.techcable.sonarpet.nms.NMSLivingEntity; -import net.techcable.sonarpet.nms.NMSSound; - -import org.bukkit.Sound; -import org.bukkit.craftbukkit.v1_9_R1.CraftSound; -import org.bukkit.craftbukkit.v1_9_R1.entity.CraftEntity; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; - -public class NMSLivingEntityImpl extends NMSEntityImpl implements NMSLivingEntity { - - // - // !!!!! Highly version-dependent !!!!! - // Check these every minor update! - // - public static final String IS_JUMPING_FIELD_NAME = "bc"; - - public NMSLivingEntityImpl(EntityLiving handle) { - super(handle); - } - - /** - * Set the 'offsets' for pitch and yaw to the same value as the yaw itself. - * Apparently this is needed to set rotation. - * See EntityLiving.h(FF) for details (method profiler 'headTurn'). - * Note that EntityInsentient overrides h(FF) and delegates to 'EntityAIBodyControl'. - * 'EntityAIBodyControl' is what actually accesses/uses these fields and where the mappings should be fetched. - *

- * Also, these fields have the MCP names 'renderYawOffset' and 'rotationYawHead' - */ - @Override - public void correctYaw() { - getHandle().aM = getHandle().aO = getHandle().yaw; - } - - @Override - public boolean isInLava() { - return getHandle().an(); - } - - // - // Breakage likely, check for bugs here - // - - @Override - public void setMoveSpeed(double rideSpeed) { - getHandle().l((float) rideSpeed); - } - - @Override - public void setStepHeight(float stepHeight) { - getHandle().P = stepHeight; - } - - - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - @Override - public void playSound(NMSSound sound, float volume, float pitch) { - getHandle().a(((NMSSoundImpl) sound).getHandle(), volume, pitch); - } - - @Override - public double distanceTo(Entity other) { - return getHandle().h(((CraftEntity) other).getHandle()); - } - - - // - // Deobfuscated methods :) - // - - @Override - public Player findNearbyPlayer(double range) { - EntityHuman player = getHandle().world.findNearbyPlayer(getHandle(), range); - return player == null ? null : (Player) player.getBukkitEntity(); - } - - @Override - public boolean isInvisible() { - return getHandle().isInvisible(); - } - - @Override - public boolean isSneaking() { - return getHandle().isSneaking(); - } - - @Override - public void setSneaking(boolean b) { - getHandle().setSneaking(b); - } - - @Override - public void setInvisible(boolean b) { - getHandle().setInvisible(b); - } - - @Override - public boolean isSprinting() { - return getHandle().isSprinting(); - } - - @Override - public void setSprinting(boolean b) { - getHandle().setSprinting(b); - } - - @Override - public void setYaw(float yaw) { - getHandle().yaw = yaw; - } - - @Override - public void setPitch(float pitch) { - getHandle().pitch = pitch; - } - - @Override - public void setNoClip(boolean b) { - getHandle().noclip = b; - } - - @Override - public boolean isInWater() { - return getHandle().isInWater(); - } - - - @Override - public void setUpwardsMotion(double motY) { - getHandle().motY = motY; - } - - @Override - public DataWatcher getDataWatcher() { - return new DataWatcherImpl(getHandle().getDataWatcher()); - } - - @Override - public double getWidth() { - return getHandle().width; - } - - @Override - public double getLength() { - return getHandle().length; - } - - // - // Utility methods and wrappers - // - - private static final PineappleField IS_JUMPING_FIELD = PineappleField.create(EntityLiving.class, IS_JUMPING_FIELD_NAME, boolean.class); - - @Override - public boolean isJumping() { - return IS_JUMPING_FIELD.getBoxed(getHandle()); - } - - @Override - public EntityLiving getHandle() { - return (EntityLiving) super.getHandle(); - } - - @Override - public LivingEntity getBukkitEntity() { - return (LivingEntity) getHandle().getBukkitEntity(); - } -} diff --git a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSPlayerImpl.java b/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSPlayerImpl.java deleted file mode 100644 index 7317fb43..00000000 --- a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSPlayerImpl.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R1; - -import net.minecraft.server.v1_9_R1.EntityPlayer; -import net.techcable.sonarpet.nms.NMSPlayer; - -import org.bukkit.entity.Player; - -public class NMSPlayerImpl extends NMSLivingEntityImpl implements NMSPlayer { - public NMSPlayerImpl(EntityPlayer handle) { - super(handle); - } - - @Override - public boolean isOnGround() { - return getHandle().onGround; - } - - @Override - public EntityPlayer getHandle() { - return (EntityPlayer) super.getHandle(); - } - - @Override - public Player getBukkitEntity() { - return (Player) super.getBukkitEntity(); - } -} diff --git a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NavigationImpl.java b/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NavigationImpl.java deleted file mode 100644 index 8d6320b5..00000000 --- a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/NavigationImpl.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R1; - -import lombok.*; - -import net.minecraft.server.v1_9_R1.Navigation; -import net.techcable.sonarpet.nms.PathEntity; - -import org.bukkit.craftbukkit.v1_9_R1.entity.CraftEntity; -import org.bukkit.entity.Entity; - -@RequiredArgsConstructor -public class NavigationImpl implements net.techcable.sonarpet.nms.Navigation { - private final Navigation handle; - - // - // Breakage likely, check for bugs here - // - - @Override - public boolean canEnterDoors() { - return handle.f(); - } - - @Override - public void finish() { - handle.n(); - } - - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - @Override - public PathEntity getPathToLocation(int blockX, int blockY, int blockZ) { - return new PathEntityImpl(handle.a(blockX, blockY, blockZ)); - } - - @Override - public PathEntity getPathTo(Entity other) { - return new PathEntityImpl(handle.a(((CraftEntity) other).getHandle())); - } - - @Override - public void navigateTo(PathEntity path, double speed) { - handle.a(((PathEntityImpl) path).handle, speed); - } - - @RequiredArgsConstructor - private static class PathEntityImpl implements PathEntity { - /* package */ final net.minecraft.server.v1_9_R1.PathEntity handle; - } -} diff --git a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/data/NMSSpawnEggItemData.java b/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/data/NMSSpawnEggItemData.java deleted file mode 100644 index 5e6e3e63..00000000 --- a/nms/v1_9_R1/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R1/data/NMSSpawnEggItemData.java +++ /dev/null @@ -1,86 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R1.data; - -import java.util.Optional; - -import com.google.common.base.Preconditions; - -import net.minecraft.server.v1_9_R1.EntityTypes; -import net.minecraft.server.v1_9_R1.Item; -import net.minecraft.server.v1_9_R1.ItemStack; -import net.minecraft.server.v1_9_R1.NBTTagCompound; -import net.techcable.sonarpet.item.SpawnEggItemData; - -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.craftbukkit.v1_9_R1.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_9_R1.util.CraftMagicNumbers; -import org.bukkit.entity.EntityType; -import org.bukkit.inventory.meta.ItemMeta; - -public class NMSSpawnEggItemData extends SpawnEggItemData { - public NMSSpawnEggItemData(byte rawData, ItemMeta meta) { - this(rawData, meta, SpawnEggItemData.DEFAULT_TYPE); - } - - public NMSSpawnEggItemData(byte rawData, ItemMeta meta, EntityType type) { - super(rawData, createMetaWithEntityType(meta, type)); - } - - @Override - public EntityType getSpawnedType() { - return getSpawnEggEntityType(this.getMeta()); - } - - public static EntityType getSpawnEggEntityType(ItemMeta meta) { - Preconditions.checkNotNull(meta, "Null meta"); - NBTTagCompound tag = getTagFromMeta(Material.MONSTER_EGG, meta); - Preconditions.checkState(tag != null, "No nbt tag"); - Preconditions.checkState(tag.hasKeyOfType("EntityTag", 10), "No entity tag"); - NBTTagCompound entityTag = tag.getCompound("EntityTag"); - Preconditions.checkState(entityTag.hasKeyOfType("id", 8), "No internal name"); - String internalName = entityTag.getString("id"); - int id = EntityTypes.a(internalName); - EntityType type = EntityType.fromId(id); - if (type == null) - throw new IllegalStateException("No entity found with internal name " + internalName + " and id " + id); - return type; - } - - public static Optional getSpawnEggEntityTypeIfPresent(ItemMeta meta) { - try { - return Optional.of(getSpawnEggEntityType(meta)); - } catch (IllegalArgumentException | IllegalStateException e) { - return Optional.empty(); - } - } - - public static ItemMeta createMetaWithEntityType(ItemMeta meta, EntityType entityType) { - NBTTagCompound entityTag = new NBTTagCompound(); - String internalName = EntityTypes.getName(EntityTypes.a(entityType.getTypeId())); - if (internalName == null) throw new AssertionError("Couldn't find internal name for type: " + entityType); - entityTag.setString("id", internalName); - NBTTagCompound tag = getTagFromMeta(Material.MONSTER_EGG, Preconditions.checkNotNull(meta, "Null meta")); - if (tag == null) tag = new NBTTagCompound(); - tag.set("EntityTag", entityTag); - return createMetaFromTag(Material.MONSTER_EGG, tag); - } - - - public static ItemMeta createMetaFromTag(Material type, NBTTagCompound tag) { - Item item = CraftMagicNumbers.getItem(Preconditions.checkNotNull(type, "Null type")); - ItemStack stack = new ItemStack(item); - stack.setTag(Preconditions.checkNotNull(tag, "Null nbt tag")); - return CraftItemStack.getItemMeta(stack); - } - - public static NBTTagCompound getTagFromMeta(Material type, ItemMeta meta) { - Preconditions.checkNotNull(meta, "Null meta"); - Preconditions.checkNotNull(type, "Null type"); - Preconditions.checkArgument(Bukkit.getItemFactory().isApplicable(meta, type), "Meta %s isn't applicable to %s", meta, type); - Item item = CraftMagicNumbers.getItem(type); - ItemStack stack = new ItemStack(item); - boolean worked = CraftItemStack.setItemMeta(stack, meta); - if (!worked) throw new RuntimeException("Didn't work"); - return stack.getTag(); - } -} diff --git a/nms/v1_9_R1/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSSoundImpl.kt b/nms/v1_9_R1/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSSoundImpl.kt deleted file mode 100644 index 08d6e7d8..00000000 --- a/nms/v1_9_R1/src/main/kotlin/net/techcable/sonarpet/nms/versions/v1_9_R1/NMSSoundImpl.kt +++ /dev/null @@ -1,21 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R1 - -import net.minecraft.server.v1_9_R1.SoundEffect -import net.techcable.sonarpet.nms.NMSSound -import net.techcable.sonarpet.utils.buildImmutableMap -import org.bukkit.Sound -import org.bukkit.craftbukkit.v1_9_R1.CraftSound - -private val BUKKIT_SOUNDS = buildImmutableMap { - for (sound in enumValues()) { - put(sound.soundEffect, sound) - } -} - -val Sound.soundEffect: SoundEffect - get() = CraftSound.getSoundEffect(CraftSound.getSound(this))!! - -class NMSSoundImpl(val handle: SoundEffect): NMSSound { - override val bukkitSound: Sound? - get() = BUKKIT_SOUNDS[handle] -} \ No newline at end of file diff --git a/nms/v1_9_R2/build.gradle.kts b/nms/v1_9_R2/build.gradle.kts deleted file mode 100644 index c4931980..00000000 --- a/nms/v1_9_R2/build.gradle.kts +++ /dev/null @@ -1,4 +0,0 @@ -dependencies { - compileOnly("org.bukkit:craftbukkit:1.9.4-R0.1-SNAPSHOT") - compileOnly(project(":api")) -} diff --git a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/DamageSourceImpl.java b/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/DamageSourceImpl.java deleted file mode 100644 index d5225549..00000000 --- a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/DamageSourceImpl.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R2; - -import lombok.*; - -import net.minecraft.server.v1_9_R2.DamageSource; - -@RequiredArgsConstructor -public class DamageSourceImpl implements net.techcable.sonarpet.nms.DamageSource { - @Getter - private final DamageSource handle; -} diff --git a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/DataWatcherImpl.java b/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/DataWatcherImpl.java deleted file mode 100644 index 167fc525..00000000 --- a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/DataWatcherImpl.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R2; - -import lombok.*; - -import net.minecraft.server.v1_9_R2.DataWatcher; -import net.minecraft.server.v1_9_R2.DataWatcherObject; -import net.minecraft.server.v1_9_R2.DataWatcherRegistry; -import net.minecraft.server.v1_9_R2.DataWatcherSerializer; - -@RequiredArgsConstructor -public class DataWatcherImpl implements net.techcable.sonarpet.nms.DataWatcher { - private final DataWatcher dataWatcher; - - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - private static final DataWatcherSerializer BOOLEAN_SERIALIZER = DataWatcherRegistry.h; - private static final DataWatcherSerializer INTEGER_SERIALIZER = DataWatcherRegistry.b; - - // - // Deobfuscated methods - // - - @Override - public void setBoolean(int id, boolean value) { - dataWatcher.set(new DataWatcherObject<>(id, BOOLEAN_SERIALIZER), value); - } - - @Override - public void setInteger(int id, int value) { - dataWatcher.set(new DataWatcherObject<>(id, INTEGER_SERIALIZER), value); - } -} diff --git a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSEntityHorseImpl.java b/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSEntityHorseImpl.java deleted file mode 100644 index 9c70d1bd..00000000 --- a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSEntityHorseImpl.java +++ /dev/null @@ -1,77 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R2; - -import com.dsh105.echopet.compat.api.entity.HorseType; -import com.dsh105.echopet.compat.api.entity.HorseTypeKt; - -import net.minecraft.server.v1_9_R2.EntityHorse; -import net.techcable.sonarpet.nms.NMSEntityHorse; - -import org.bukkit.entity.Horse; - -public class NMSEntityHorseImpl extends NMSEntityInsentientImpl implements NMSEntityHorse { - public NMSEntityHorseImpl(EntityHorse handle) { - super(handle); - } - - // - // !!!!! Highly version-dependent !!!!! - // Check these every minor update! - // - - @Override - public void setSaddled(boolean saddled) { - getHandle().t(saddled); // EntityHorse.setHorseSaddled - } - - @Override - public boolean isSaddled() { - return getHandle().dv(); // EntityHorse.isHorseSaddled - } - - // - // Breakage likely, check for bugs here - // - - @Override - public void setRearing(boolean b) { - // metadata flag with id 64 - getHandle().v(b); - } - - // Deobfuscated methods - - @Override - public void setStyle(Horse.Style bukkitStyle) { - getBukkitEntity().setStyle(bukkitStyle); - } - - @Override - public void setHorseType(HorseType t) { - getBukkitEntity().setVariant(t.getBukkitVariant()); - } - - @Override - public void setColor(Horse.Color color) { - getBukkitEntity().setColor(color); - } - - @Override - public HorseType getHorseType() { - return HorseTypeKt.getSonarType(getBukkitEntity().getVariant()); - } - - @Override - public void setCarryingChest(boolean flag) { - getBukkitEntity().setCarryingChest(flag); - } - - @Override - public EntityHorse getHandle() { - return (EntityHorse) super.getHandle(); - } - - @Override - public Horse getBukkitEntity() { - return (Horse) super.getBukkitEntity(); - } -} diff --git a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSEntityImpl.java b/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSEntityImpl.java deleted file mode 100644 index dc28bc7a..00000000 --- a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSEntityImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R2; - -import lombok.*; - -import com.google.common.collect.ImmutableList; - -import net.minecraft.server.v1_9_R2.DamageSource; -import net.minecraft.server.v1_9_R2.Entity; -import net.techcable.sonarpet.nms.INMS; -import net.techcable.sonarpet.nms.NMSEntity; -import net.techcable.sonarpet.nms.NMSLivingEntity; - -import org.bukkit.entity.Player; - -@RequiredArgsConstructor -public class NMSEntityImpl implements NMSEntity { - @Getter - private final Entity handle; - - // - // Deobfuscated methods - // - - @Override - public boolean damageEntity(net.techcable.sonarpet.nms.DamageSource rawSource, float amount) { - DamageSource damageSource = ((DamageSourceImpl) rawSource).getHandle(); - return getHandle().damageEntity(damageSource, amount); - } - - @Override - public org.bukkit.entity.Entity getBukkitEntity() { - return handle.getBukkitEntity(); - } - - @Override - public ImmutableList getPassengers() { - return ImmutableList.copyOf(handle.passengers.stream() - .map(Entity::getBukkitEntity) - .map(INMS.getInstance()::wrapEntity) - .toArray(NMSEntity[]::new)); - } - - @Override - public int hashCode() { - return handle.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj != null && obj instanceof NMSEntityImpl && ((NMSEntityImpl) obj).handle.equals(this.handle); - } - - @Override - public String toString() { - if (getBukkitEntity() instanceof Player) { - return "NMSPlayer(" + getBukkitEntity().getName() + ")"; - } else { - StringBuilder builder = new StringBuilder("NMSEntity("); - builder.append(getBukkitEntity().getType()); - if (getBukkitEntity().getCustomName() != null) { - builder.append(":"); - builder.append(getBukkitEntity().getCustomName()); - } - builder.append(')'); - return builder.toString(); - } - } -} diff --git a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSEntityRegistry.java b/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSEntityRegistry.java deleted file mode 100644 index 7ab27c99..00000000 --- a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSEntityRegistry.java +++ /dev/null @@ -1,72 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R2; - -import java.util.Map; -import java.util.Objects; - -import com.google.common.collect.ImmutableList; - -import net.minecraft.server.v1_9_R2.EntityTypes; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.sonarpet.nms.EntityRegistry; - -public class NMSEntityRegistry implements EntityRegistry { - private static final PineappleField, String>> CLASS_TO_NAME_FIELD; - private static final PineappleField>> ID_TO_CLASS_FIELD; - private static final PineappleField, Integer>> CLASS_TO_ID_FIELD; - - static { - ImmutableList> mapFields = PineappleField.findFieldsWithType(EntityTypes.class, Map.class); - assert mapFields.size() == 5; - //noinspection unchecked - CLASS_TO_NAME_FIELD = (PineappleField) mapFields.get(1); - //noinspection unchecked - ID_TO_CLASS_FIELD = (PineappleField) mapFields.get(2); - //noinspection unchecked - CLASS_TO_ID_FIELD = (PineappleField) mapFields.get(3); - } - - @Override - public void registerEntityClass(Class entityClass, String name, int id) { - CLASS_TO_NAME_FIELD.getStatic().put(entityClass, name); - CLASS_TO_ID_FIELD.getStatic().put(entityClass, id); - } - - @Override - public void unregisterEntityClass(Class entityClass, String name, int id) { - String actualName = CLASS_TO_NAME_FIELD.getStatic().remove(entityClass); - Integer actualId = CLASS_TO_ID_FIELD.getStatic().remove(entityClass); - if (!Objects.equals(name, actualName)) { - throw new IllegalArgumentException("Expected name " + name + " didn't equal actual name " + Objects.toString(actualName)); - } else if (actualId == null || actualId != id) { - throw new IllegalArgumentException("Expected id " + id + " didn't equal actual id " + Objects.toString(actualId)); - } - } - - @Override - public Class getEntityClass(int id) { - return ID_TO_CLASS_FIELD.getStatic().get(id); - } - - @Override - public int getEntityId(Class entityClass) { - return CLASS_TO_ID_FIELD.getStatic().get(entityClass); - } - - @Override - public String getEntityName(Class entityClass) { - return CLASS_TO_NAME_FIELD.getStatic().get(entityClass); - } - - @Override - public void registerEntityId(int id, Class entityClass) { - ID_TO_CLASS_FIELD.getStatic().put(id, entityClass); - } - - @Override - public void unregisterEntityId(int id, Class entityClass) { - Class actualEntityClass = ID_TO_CLASS_FIELD.getStatic().remove(id); - if (!Objects.equals(actualEntityClass, entityClass)) { - throw new IllegalArgumentException("Exepcted entity class " + entityClass + " didn't equal actual entity class " + Objects.toString(actualEntityClass)); - } - } -} diff --git a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSImpl.java b/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSImpl.java deleted file mode 100644 index 178d6f45..00000000 --- a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSImpl.java +++ /dev/null @@ -1,145 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R2; - -import net.minecraft.server.v1_9_R2.EntityHorse; -import net.minecraft.server.v1_9_R2.EntityInsentient; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.sonarpet.nms.DismountingBlocked; -import net.techcable.sonarpet.nms.EntityRegistry; -import net.techcable.sonarpet.nms.INMS; -import com.google.common.collect.ImmutableMap; - -import net.minecraft.server.v1_9_R2.Block; -import net.minecraft.server.v1_9_R2.DamageSource; -import net.minecraft.server.v1_9_R2.EntityHuman; -import net.minecraft.server.v1_9_R2.EntityLiving; -import net.minecraft.server.v1_9_R2.EntityPlayer; -import net.minecraft.server.v1_9_R2.Packet; -import net.minecraft.server.v1_9_R2.PacketPlayOutMount; -import net.minecraft.server.v1_9_R2.SoundEffect; -import net.minecraft.server.v1_9_R2.SoundEffectType; -import net.techcable.sonarpet.item.SpawnEggItemData; -import net.techcable.sonarpet.nms.BlockSoundData; -import net.techcable.sonarpet.nms.NMSEntity; -import net.techcable.sonarpet.nms.NMSInsentientEntity; -import net.techcable.sonarpet.nms.NMSSound; -import net.techcable.sonarpet.nms.versions.v1_9_R2.data.NMSSpawnEggItemData; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.craftbukkit.v1_9_R2.CraftSound; -import org.bukkit.craftbukkit.v1_9_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_9_R2.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_9_R2.entity.CraftLivingEntity; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.material.SpawnEgg; - -import static com.google.common.base.Preconditions.*; - -public class NMSImpl implements INMS { - @Override - public SpawnEggItemData createSpawnEggData(byte rawData, ItemMeta meta) { - EntityType entityType = NMSSpawnEggItemData.getSpawnEggEntityTypeIfPresent(meta).orElse(EntityType.fromId(rawData)); - if (entityType == null) entityType = SpawnEggItemData.DEFAULT_TYPE; // 'Fix' broken configs - return new NMSSpawnEggItemData(rawData, meta, entityType); - } - - @Override - public SpawnEggItemData createSpawnEggData(EntityType entityType, ItemMeta meta) { - checkNotNull(entityType, "Null entity type"); - checkNotNull(meta, "Null item meta"); - return new NMSSpawnEggItemData(new SpawnEgg(entityType).getData(), meta, entityType); // Pretend we use metadata to make the code happy - } - - @Override - public void mount(Entity bukkitRider, Entity bukkitVehicle) { - net.minecraft.server.v1_9_R2.Entity rider = ((CraftEntity) bukkitRider).getHandle(); - if (bukkitVehicle == null) { - net.minecraft.server.v1_9_R2.Entity vehicle = rider.getVehicle(); // This is how you *really* get the vehicle :/ - if (rider instanceof DismountingBlocked) { - ((DismountingBlocked) rider).reallyStopRiding(); - } else { - rider.stopRiding(); - } - if (vehicle != null) { - Packet packet = new PacketPlayOutMount(vehicle); - for (EntityHuman human : rider.world.players) { - ((EntityPlayer) human).playerConnection.sendPacket(packet); - } - } - } else { - checkArgument(bukkitRider.getWorld().equals(bukkitVehicle.getWorld()), "Rider is in world %s, while vehicle is in world %s", bukkitRider.getWorld().getName(), bukkitVehicle.getWorld().getName()); - net.minecraft.server.v1_9_R2.Entity vehicle = ((CraftEntity) bukkitVehicle).getHandle(); - rider.a(vehicle, true); // !! Obfuscated !! - Packet packet = new PacketPlayOutMount(vehicle); - for (EntityHuman human : rider.world.players) { - ((EntityPlayer) human).playerConnection.sendPacket(packet); - } - } - } - - @Override - public boolean spawnEntity(NMSInsentientEntity wrapper, Location l) { - EntityLiving entity = ((NMSEntityInsentientImpl) wrapper).getHandle(); - entity.spawnIn(((CraftWorld) l.getWorld()).getHandle()); - ((LivingEntity) entity.getBukkitEntity()).setCollidable(false); - entity.setLocation(l.getX(), l.getY(), l.getZ(), l.getYaw(), l.getPitch()); - if (!l.getChunk().isLoaded()) { - l.getChunk().load(); - } - return entity.world.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); - } - - @Override - public net.techcable.sonarpet.nms.DamageSource mobAttackDamageSource(LivingEntity entity) { - return new DamageSourceImpl(DamageSource.mobAttack(((CraftLivingEntity) entity).getHandle())); - } - - @Override - public net.techcable.sonarpet.nms.DamageSource wrapDamageSource(Object handle) { - return new DamageSourceImpl((DamageSource) handle); - } - - @Override - public NMSEntity wrapEntity(Entity entity) { - net.minecraft.server.v1_9_R2.Entity handle = ((CraftEntity) entity).getHandle(); - if (handle instanceof EntityPlayer) { - return new NMSPlayerImpl((EntityPlayer) handle); - } else if (handle instanceof EntityHorse) { - return new NMSEntityHorseImpl((EntityHorse) handle); - } else if (handle instanceof EntityInsentient) { - return new NMSEntityInsentientImpl((EntityInsentient) handle); - } else if (handle instanceof EntityLiving) { - return new NMSLivingEntityImpl((EntityLiving) handle); - } else { - return new NMSEntityImpl(handle); - } - } - - private PineappleField STEP_SOUND_FIELD = PineappleField.create(Block.class, "stepSound", SoundEffectType.class); - @Override - @SuppressWarnings("deprecation") // I know about ur stupid magic value warning mom - public BlockSoundData getBlockSoundData(Material material) { - return new BlockSoundDataImpl(STEP_SOUND_FIELD.get(Block.getById(material.getId()))); - } - - @Override - @SuppressWarnings("deprecation") // I know about ur stupid magic value warning mom - public boolean isLiquid(Material block) { - return Block.getById(block.getId()).getBlockData().getMaterial().isLiquid(); - } - - @Override - public EntityRegistry createDefaultEntityRegistry() { - return new NMSEntityRegistry(); - } - - @Override - public NMSSound getNmsSound(Sound bukkitSound) { - return new NMSSoundImpl(NMSSoundImplKt.getSoundEffect(bukkitSound)); - } -} diff --git a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSLivingEntityImpl.java b/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSLivingEntityImpl.java deleted file mode 100644 index 8af2f34f..00000000 --- a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSLivingEntityImpl.java +++ /dev/null @@ -1,181 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R2; - -import net.minecraft.server.v1_9_R2.EntityHuman; -import net.minecraft.server.v1_9_R2.EntityLiving; -import net.minecraft.server.v1_9_R2.SoundEffect; -import net.techcable.pineapple.reflection.PineappleField; -import net.techcable.sonarpet.nms.DataWatcher; -import net.techcable.sonarpet.nms.NMSLivingEntity; -import net.techcable.sonarpet.nms.NMSSound; - -import org.bukkit.Sound; -import org.bukkit.craftbukkit.v1_9_R2.CraftSound; -import org.bukkit.craftbukkit.v1_9_R2.entity.CraftEntity; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; - -public class NMSLivingEntityImpl extends NMSEntityImpl implements NMSLivingEntity { - - // - // !!!!! Highly version-dependent !!!!! - // Check these every minor update! - // - public static final String IS_JUMPING_FIELD_NAME = "bd"; - - public NMSLivingEntityImpl(EntityLiving handle) { - super(handle); - } - - /** - * Set the 'offsets' for pitch and yaw to the same value as the yaw itself. - * Apparently this is needed to set rotation. - * See EntityLiving.h(FF) for details (method profiler 'headTurn'). - * Note that EntityInsentient overrides h(FF) and delegates to 'EntityAIBodyControl'. - * 'EntityAIBodyControl' is what actually accesses/uses these fields and where the mappings should be fetched. - *

- * Also, these fields have the MCP names 'renderYawOffset' and 'rotationYawHead' - */ - @Override - public void correctYaw() { - getHandle().aN = getHandle().aP = getHandle().yaw; - } - - @Override - public boolean isInLava() { - return getHandle().an(); - } - - // - // Breakage likely, check for bugs here - // - - @Override - public void setMoveSpeed(double rideSpeed) { - getHandle().l((float) rideSpeed); - } - - @Override - public void setStepHeight(float stepHeight) { - getHandle().P = stepHeight; - } - - - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - @Override - public void playSound(NMSSound sound, float volume, float pitch) { - getHandle().a(((NMSSoundImpl) sound).getHandle(), volume, pitch); - } - - @Override - public double distanceTo(Entity other) { - return getHandle().h(((CraftEntity) other).getHandle()); - } - - - // - // Deobfuscated methods :) - // - - @Override - public Player findNearbyPlayer(double range) { - EntityHuman player = getHandle().world.findNearbyPlayer(getHandle(), range); - return player == null ? null : (Player) player.getBukkitEntity(); - } - - @Override - public boolean isInvisible() { - return getHandle().isInvisible(); - } - - @Override - public boolean isSneaking() { - return getHandle().isSneaking(); - } - - @Override - public void setSneaking(boolean b) { - getHandle().setSneaking(b); - } - - @Override - public void setInvisible(boolean b) { - getHandle().setInvisible(b); - } - - @Override - public boolean isSprinting() { - return getHandle().isSprinting(); - } - - @Override - public void setSprinting(boolean b) { - getHandle().setSprinting(b); - } - - @Override - public void setYaw(float yaw) { - getHandle().yaw = yaw; - } - - @Override - public void setPitch(float pitch) { - getHandle().pitch = pitch; - } - - @Override - public void setNoClip(boolean b) { - getHandle().noclip = b; - } - - @Override - public boolean isInWater() { - return getHandle().isInWater(); - } - - - @Override - public void setUpwardsMotion(double motY) { - getHandle().motY = motY; - } - - @Override - public DataWatcher getDataWatcher() { - return new DataWatcherImpl(getHandle().getDataWatcher()); - } - - @Override - public double getWidth() { - return getHandle().width; - } - - @Override - public double getLength() { - return getHandle().length; - } - - // - // Utility methods and wrappers - // - - private static final PineappleField IS_JUMPING_FIELD = PineappleField.create(EntityLiving.class, IS_JUMPING_FIELD_NAME, boolean.class); - - @Override - public boolean isJumping() { - return IS_JUMPING_FIELD.getBoxed(getHandle()); - } - - @Override - public EntityLiving getHandle() { - return (EntityLiving) super.getHandle(); - } - - @Override - public LivingEntity getBukkitEntity() { - return (LivingEntity) getHandle().getBukkitEntity(); - } -} diff --git a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSPlayerImpl.java b/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSPlayerImpl.java deleted file mode 100644 index 38acd3b8..00000000 --- a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NMSPlayerImpl.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R2; - -import net.minecraft.server.v1_9_R2.EntityPlayer; -import net.techcable.sonarpet.nms.NMSPlayer; - -import org.bukkit.entity.Player; - -public class NMSPlayerImpl extends NMSLivingEntityImpl implements NMSPlayer { - public NMSPlayerImpl(EntityPlayer handle) { - super(handle); - } - - @Override - public boolean isOnGround() { - return getHandle().onGround; - } - - @Override - public EntityPlayer getHandle() { - return (EntityPlayer) super.getHandle(); - } - - @Override - public Player getBukkitEntity() { - return (Player) super.getBukkitEntity(); - } -} diff --git a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NavigationImpl.java b/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NavigationImpl.java deleted file mode 100644 index 01973fe6..00000000 --- a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/NavigationImpl.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R2; - -import lombok.*; - -import net.minecraft.server.v1_9_R2.Navigation; -import net.techcable.sonarpet.nms.PathEntity; - -import org.bukkit.craftbukkit.v1_9_R2.entity.CraftEntity; -import org.bukkit.entity.Entity; - -@RequiredArgsConstructor -public class NavigationImpl implements net.techcable.sonarpet.nms.Navigation { - private final Navigation handle; - - // - // Breakage likely, check for bugs here - // - - @Override - public boolean canEnterDoors() { - return handle.f(); - } - - @Override - public void finish() { - handle.n(); - } - - // - // Unlikely to break, even across major versions - // IE: never broken yet ^_^ - // - - @Override - public PathEntity getPathToLocation(int blockX, int blockY, int blockZ) { - return new PathEntityImpl(handle.a(blockX, blockY, blockZ)); - } - - @Override - public PathEntity getPathTo(Entity other) { - return new PathEntityImpl(handle.a(((CraftEntity) other).getHandle())); - } - - @Override - public void navigateTo(PathEntity path, double speed) { - handle.a(((PathEntityImpl) path).handle, speed); - } - - @RequiredArgsConstructor - private static class PathEntityImpl implements PathEntity { - /* package */ final net.minecraft.server.v1_9_R2.PathEntity handle; - } -} diff --git a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/data/NMSSpawnEggItemData.java b/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/data/NMSSpawnEggItemData.java deleted file mode 100644 index 1691fe89..00000000 --- a/nms/v1_9_R2/src/main/java/net/techcable/sonarpet/nms/versions/v1_9_R2/data/NMSSpawnEggItemData.java +++ /dev/null @@ -1,86 +0,0 @@ -package net.techcable.sonarpet.nms.versions.v1_9_R2.data; - -import java.util.Optional; - -import com.google.common.base.Preconditions; - -import net.minecraft.server.v1_9_R2.EntityTypes; -import net.minecraft.server.v1_9_R2.Item; -import net.minecraft.server.v1_9_R2.ItemStack; -import net.minecraft.server.v1_9_R2.NBTTagCompound; -import net.techcable.sonarpet.item.SpawnEggItemData; - -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.craftbukkit.v1_9_R2.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_9_R2.util.CraftMagicNumbers; -import org.bukkit.entity.EntityType; -import org.bukkit.inventory.meta.ItemMeta; - -public class NMSSpawnEggItemData extends SpawnEggItemData { - public NMSSpawnEggItemData(byte rawData, ItemMeta meta) { - this(rawData, meta, SpawnEggItemData.DEFAULT_TYPE); - } - - public NMSSpawnEggItemData(byte rawData, ItemMeta meta, EntityType type) { - super(rawData, createMetaWithEntityType(meta, type)); - } - - @Override - public EntityType getSpawnedType() { - return getSpawnEggEntityType(this.getMeta()); - } - - public static EntityType getSpawnEggEntityType(ItemMeta meta) { - Preconditions.checkNotNull(meta, "Null meta"); - NBTTagCompound tag = getTagFromMeta(Material.MONSTER_EGG, meta); - Preconditions.checkState(tag != null, "No nbt tag"); - Preconditions.checkState(tag.hasKeyOfType("EntityTag", 10), "No entity tag"); - NBTTagCompound entityTag = tag.getCompound("EntityTag"); - Preconditions.checkState(entityTag.hasKeyOfType("id", 8), "No internal name"); - String internalName = entityTag.getString("id"); - int id = EntityTypes.a(internalName); - EntityType type = EntityType.fromId(id); - if (type == null) - throw new IllegalStateException("No entity found with internal name " + internalName + " and id " + id); - return type; - } - - public static Optional getSpawnEggEntityTypeIfPresent(ItemMeta meta) { - try { - return Optional.of(getSpawnEggEntityType(meta)); - } catch (IllegalArgumentException | IllegalStateException e) { - return Optional.empty(); - } - } - - public static ItemMeta createMetaWithEntityType(ItemMeta meta, EntityType entityType) { - NBTTagCompound entityTag = new NBTTagCompound(); - String internalName = EntityTypes.getName(EntityTypes.a(entityType.getTypeId())); - if (internalName == null) throw new AssertionError("Couldn't find internal name for type: " + entityType); - entityTag.setString("id", internalName); - NBTTagCompound tag = getTagFromMeta(Material.MONSTER_EGG, Preconditions.checkNotNull(meta, "Null meta")); - if (tag == null) tag = new NBTTagCompound(); - tag.set("EntityTag", entityTag); - return createMetaFromTag(Material.MONSTER_EGG, tag); - } - - - public static ItemMeta createMetaFromTag(Material type, NBTTagCompound tag) { - Item item = CraftMagicNumbers.getItem(Preconditions.checkNotNull(type, "Null type")); - ItemStack stack = new ItemStack(item); - stack.setTag(Preconditions.checkNotNull(tag, "Null nbt tag")); - return CraftItemStack.getItemMeta(stack); - } - - public static NBTTagCompound getTagFromMeta(Material type, ItemMeta meta) { - Preconditions.checkNotNull(meta, "Null meta"); - Preconditions.checkNotNull(type, "Null type"); - Preconditions.checkArgument(Bukkit.getItemFactory().isApplicable(meta, type), "Meta %s isn't applicable to %s", meta, type); - Item item = CraftMagicNumbers.getItem(type); - ItemStack stack = new ItemStack(item); - boolean worked = CraftItemStack.setItemMeta(stack, meta); - if (!worked) throw new RuntimeException("Didn't work"); - return stack.getTag(); - } -} diff --git a/settings.gradle b/settings.gradle index af29a06e..7021e124 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,7 +1,7 @@ rootProject.name = 'SonarPet' rootProject.buildFileName = "build.gradle.kts" include 'api' -List nmsVersions = ["v1_8_R3", "v1_9_R1", "v1_9_R2", "v1_10_R1", "v1_11_R1", "v1_12_R1"] +List nmsVersions = ["v1_12_R1", "v1_13_R2"] for (version in nmsVersions) { include "nms-$version" project(":nms-$version").projectDir = "$rootDir/nms/$version" as File