samples = new HashMap<>(64);
for (int posX = 0; posX < 16; posX += 4) {
for (int posZ = 0; posZ < 16; posZ += 4) {
samples.clear();
for (int posY = 0; posY < 256; posY += 16) {
VirtualBiome biome = biomes[/*SimpleChunk.getBiomeIndex(posX, posY, posZ)*/(posY >> 2 & 63) << 4 | (posZ >> 2 & 3) << 2 | posX >> 2 & 3];
- samples.put(biome.getID(), samples.getOrDefault(biome.getID(), 0) + 1);
+ samples.put(biome.getId(), samples.getOrDefault(biome.getId(), 0) + 1);
}
int id = samples.entrySet()
.stream()
@@ -42,7 +42,7 @@ public BiomeData(ChunkSnapshot chunk) {
.getKey();
for (int i = posX; i < posX + 4; ++i) {
for (int j = posZ; j < posZ + 4; ++j) {
- this.pre115Biomes[(j << 4) + i] = (byte) id;
+ this.pre115Biomes[(j << 4) + i] = id;
}
}
}
@@ -53,7 +53,7 @@ public int[] getPost115Biomes() {
return this.post115Biomes;
}
- public byte[] getPre115Biomes() {
+ public int[] getPre115Biomes() {
return this.pre115Biomes;
}
}
diff --git a/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/BlockPos.java b/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/BlockPos.java
new file mode 100644
index 00000000..dc6db112
--- /dev/null
+++ b/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/BlockPos.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2021 - 2024 Elytrium
+ *
+ * The LimboAPI (excluding the LimboAPI plugin) is licensed under the terms of the MIT License. For more details,
+ * reference the LICENSE file in the api top-level directory.
+ */
+
+package net.elytrium.limboapi.api.protocol.packets.data;
+
+public record BlockPos(int posX, int posY, int posZ) implements EntityDataValue.Particle.VibrationParticle.PositionSource {
+
+}
diff --git a/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/EntityDataValue.java b/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/EntityDataValue.java
new file mode 100644
index 00000000..c18c7891
--- /dev/null
+++ b/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/EntityDataValue.java
@@ -0,0 +1,514 @@
+/*
+ * Copyright (C) 2021 - 2024 Elytrium
+ *
+ * The LimboAPI (excluding the LimboAPI plugin) is licensed under the terms of the MIT License. For more details,
+ * reference the LICENSE file in the api top-level directory.
+ */
+
+package net.elytrium.limboapi.api.protocol.packets.data;
+
+import com.velocitypowered.api.network.ProtocolVersion;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.OptionalInt;
+import java.util.UUID;
+import net.elytrium.limboapi.api.player.LimboPlayer;
+import net.kyori.adventure.nbt.BinaryTag;
+import net.kyori.adventure.nbt.CompoundBinaryTag;
+import net.kyori.adventure.nbt.EndBinaryTag;
+import net.kyori.adventure.text.Component;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.checkerframework.common.value.qual.IntRange;
+
+/**
+ * The value can be one of the following data types (note that some are version-specific):
+ *
+ * {@link Byte},
+ * {@link Short} (2-byte short <1.9, VarInt >=1.9),
+ * {@link Integer} (4-byte int <=1.8, VarInt >1.8),
+ * {@link Long} (4-byte int <=1.8, VarInt <=1.19.2, VarLong >1.19.2),
+ * {@link Float}, {@link String}, {@link NBTComponent}, {@link Component}, {@link OptionalNBTComponent}, {@link OptionalComponent}, {@link ItemStack},
+ * {@link Boolean}, (serialized as byte data type <=1.8, boolean >1.8)
+ * {@link Rotations}, {@link BlockPos}, {@link OptionalBlockPos}, {@link Direction}, {@link OptionalUUID}, {@link BlockState}, {@link OptionalBlockState},
+ * {@link CompoundBinaryTag} ({@link EndBinaryTag#endBinaryTag()} Should be used instead as null),
+ * {@link Particle}, {@link Particles}, {@link VillagerData},
+ * {@link OptionalInt} (Also known as OptionalUnsignedInt) (4-byte int <=1.8, VarInt <=1.13.2, OptionalInt >1.13.2),
+ * {@link Pose}, {@link CatVariant}, {@link WolfVariant}, {@link FrogVariant}, {@link OptionalGlobalPos}, {@link PaintingVariant},
+ * {@link SnifferState}, {@link ArmadilloState}, {@link Vector3}, {@link Quaternion}.
+ *
+ *
+ * @see LimboPlayer#setEntityData(int, Collection)
+ */
+public record EntityDataValue(int id, @Nullable T value) {
+
+ //public EntityDataValue {
+ // System.out.println(value);
+ //}
+
+ public record OptionalComponent(@Nullable Component component) {
+
+ public static final OptionalComponent EMPTY = new OptionalComponent(null);
+ }
+
+ /**
+ * Modern {@link Component} represented in compound nbt tag, used in >=1.20.3. Will be automatically converted to a JSON component when encoding for <1.20.3
+ */
+ public record NBTComponent(BinaryTag component) {
+
+ }
+
+ public record OptionalNBTComponent(@Nullable NBTComponent component) {
+
+ public static final OptionalNBTComponent EMPTY = new OptionalNBTComponent(null);
+ }
+
+ public record OptionalBlockPos(@Nullable BlockPos blockPos) {
+
+ public static final OptionalBlockPos EMPTY = new OptionalBlockPos(null);
+ }
+
+ /**
+ * @sinceMinecraft 1.8
+ */
+ public record Rotations(float posX, float posY, float posZ) {
+
+ public Rotations(float posX, float posY, float posZ) {
+ this.posX = !Float.isInfinite(posX) && !Float.isNaN(posX) ? posX % 360.0F : 0.0F;
+ this.posY = !Float.isInfinite(posY) && !Float.isNaN(posY) ? posY % 360.0F : 0.0F;
+ this.posZ = !Float.isInfinite(posZ) && !Float.isNaN(posZ) ? posZ % 360.0F : 0.0F;
+ }
+ }
+
+ public enum Direction {
+
+ DOWN,
+ UP,
+ NORTH,
+ SOUTH,
+ WEST,
+ EAST;
+
+ public static final Direction[] VALUES = Direction.values();
+ }
+
+ public record OptionalUUID(@Nullable UUID uuid) {
+
+ public static final OptionalUUID EMPTY = new OptionalUUID(null);
+ }
+
+ /**
+ * @sinceMinecraft 1.19.4
+ */
+ public record BlockState(int blockState/*TODO use existing api*/) implements Particle.ParticleData {
+
+ }
+
+ public record OptionalBlockState(@Nullable BlockState blockState) {
+
+ public static final OptionalBlockState EMPTY = new OptionalBlockState(null);
+ }
+
+ /**
+ * @sinceMinecraft 1.13
+ */
+ public record Particle(int type/*TODO enum + registry*/, @Nullable ParticleData data) {
+
+ /**
+ * @sinceMinecraft 1.20.5
+ * @param color ARGB
+ */
+ public record ColorParticleData(int color) implements ParticleData {
+
+ /**
+ * @param red must be within range [0.0, 1.0]
+ * @param green must be within range [0.0, 1.0]
+ * @param blue must be within range [0.0, 1.0]
+ */
+ public ColorParticleData(float red, float green, float blue) {
+ this(1.0F, red, green, blue);
+ }
+
+ /**
+ * @param alpha must be within range [0.0, 1.0]
+ * @param red must be within range [0.0, 1.0]
+ * @param green must be within range [0.0, 1.0]
+ * @param blue must be within range [0.0, 1.0]
+ */
+ public ColorParticleData(float alpha, float red, float green, float blue) {
+ this(ColorParticleData.as8BitChannel(alpha), ColorParticleData.as8BitChannel(red), ColorParticleData.as8BitChannel(green), ColorParticleData.as8BitChannel(blue));
+ }
+
+ /**
+ * @param red must be within range [0, 255]
+ * @param green must be within range [0, 255]
+ * @param blue must be within range [0, 255]
+ */
+ public ColorParticleData(@IntRange(from = 0, to = 255) int red, @IntRange(from = 0, to = 255) int green, @IntRange(from = 0, to = 255) int blue) {
+ this(255, red, green, blue);
+ }
+
+ /**
+ * @param alpha must be within range [0, 255]
+ * @param red must be within range [0, 255]
+ * @param green must be within range [0, 255]
+ * @param blue must be within range [0, 255]
+ */
+ public ColorParticleData(@IntRange(from = 0, to = 255) int alpha, @IntRange(from = 0, to = 255) int red, @IntRange(from = 0, to = 255) int green, @IntRange(from = 0, to = 255) int blue) {
+ this((alpha << 24) | (red << 16) | (green << 8) | blue);
+ }
+
+ public float red() {
+ return (float) (this.color >> 16 & 0xFF) / 255.0F;
+ }
+
+ public float green() {
+ return (float) (this.color >> 8 & 0xFF) / 255.0F;
+ }
+
+ public float blue() {
+ return (float) (this.color & 0xFF) / 255.0F;
+ }
+
+ public float alpha() {
+ return (float) (this.color >>> 24) / 255.0F;
+ }
+
+ private static int as8BitChannel(float f) {
+ return ColorParticleData.floor(f * 255.0F);
+ }
+
+ private static int floor(float f) {
+ int i = (int) f;
+ return f < i ? i - 1 : i;
+ }
+ }
+
+ /**
+ * @sinceMinecraft 1.17
+ * @param scale Must be within range [0.01, 4.0]
+ */
+ public record DustColorTransitionParticleData(float fromRed, float fromGreen, float fromBlue, float toRed, float toGreen, float toBlue, float scale) implements ParticleData {
+
+ public DustColorTransitionParticleData(float fromRed, float fromGreen, float fromBlue, float toRed, float toGreen, float toBlue, float scale) {
+ this.fromRed = fromRed;
+ this.fromGreen = fromGreen;
+ this.fromBlue = fromBlue;
+ this.toRed = toRed;
+ this.toGreen = toGreen;
+ this.toBlue = toBlue;
+ this.scale = scale < 0.01F ? 0.01F : Math.min(scale, 4.0F);
+ }
+ }
+
+ /**
+ * @sinceMinecraft 1.13
+ * @param scale Must be within range [0.01, 4.0]
+ */
+ public record DustParticleData(float red, float green, float blue, float scale) implements ParticleData {
+
+ /**
+ * @param scale Must be within range [0.01, 4.0]
+ */
+ public DustParticleData(float red, float green, float blue, float scale) {
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ this.scale = scale < 0.01F ? 0.01F : Math.min(scale, 4.0F);
+ }
+ }
+
+ /**
+ * @sinceMinecraft 1.19
+ */
+ public record SculkChargeParticleData(float roll) implements ParticleData {
+
+ }
+
+ /**
+ * @sinceMinecraft 1.19
+ */
+ public record ShriekParticle(int delay) implements ParticleData {
+
+ }
+
+ /**
+ * @sinceMinecraft 1.17
+ * @param origin Used only in [1.17-1.18.2]
+ */
+ public record VibrationParticle(@Deprecated @Nullable BlockPos origin, PositionSource destination, int arrivalInTicks) implements ParticleData {
+
+ public record EntityPositionSource(int entityId, float yOffset) implements PositionSource {
+
+ }
+
+ public sealed interface PositionSource permits BlockPos, EntityPositionSource {
+
+ }
+ }
+
+ /**
+ * @sinceMinecraft 1.21.2
+ */
+ public record TargetColorParticle(Vector3 target, int color) implements ParticleData {
+
+ }
+
+ public sealed interface ParticleData permits BlockState,
+ ColorParticleData, DustColorTransitionParticleData, DustParticleData,
+ ItemStack, SculkChargeParticleData, VibrationParticle, TargetColorParticle, ShriekParticle {
+
+ }
+ }
+
+ /**
+ * @sinceMinecraft 1.20.5
+ */
+ public static class Particles extends ArrayList {
+
+ public Particles() {
+
+ }
+
+ public Particles(int initialCapacity) {
+ super(initialCapacity);
+ }
+ }
+
+ /**
+ * @sinceMinecraft 1.14
+ * @param level Must be no less than 1
+ */
+ public record VillagerData(int type, int profession, int level) {
+
+ public VillagerData(int type, int profession, int level) {
+ this.type = type;
+ this.profession = profession;
+ this.level = Math.max(1, level);
+ }
+ }
+
+ /**
+ * @sinceMinecraft 1.14
+ */
+ public enum Pose { // TODO registry map
+
+ STANDING,
+ FALL_FLYING,
+ SLEEPING,
+ SWIMMING,
+ SPIN_ATTACK,
+ CROUCHING,
+ /**
+ * @sinceMinecraft 1.17
+ */
+ LONG_JUMPING,
+ DYING,
+ /**
+ * @sinceMinecraft 1.19
+ */
+ CROAKING,
+ /**
+ * @sinceMinecraft 1.19
+ */
+ USING_TONGUE,
+ /**
+ * @sinceMinecraft 1.19.3
+ */
+ SITTING,
+ /**
+ * @sinceMinecraft 1.19
+ */
+ ROARING,
+ /**
+ * @sinceMinecraft 1.19
+ */
+ SNIFFING,
+ /**
+ * @sinceMinecraft 1.19
+ */
+ EMERGING,
+ /**
+ * @sinceMinecraft 1.19
+ */
+ DIGGING,
+ /**
+ * @sinceMinecraft 1.20
+ */
+ SLIDING,
+ /**
+ * @sinceMinecraft 1.20
+ */
+ SHOOTING,
+ /**
+ * @sinceMinecraft 1.20
+ */
+ INHALING;
+
+ public static final Pose[] VALUES = Pose.values();
+
+ public int getProtocolId(ProtocolVersion version) {
+ if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20)) { // after 1.19.3 all new poses were added to end
+ return this.ordinal();
+ } else {
+ return switch (this) {
+ case STANDING -> 0;
+ case FALL_FLYING -> 1;
+ case SLEEPING -> 2;
+ case SWIMMING -> 3;
+ case SPIN_ATTACK -> 4;
+ case CROUCHING -> 5;
+ default -> version.noLessThan(ProtocolVersion.MINECRAFT_1_17) ? switch (this) {
+ // >=1.17
+ case LONG_JUMPING -> 6;
+ case DYING -> 7;
+ default -> version.noLessThan(ProtocolVersion.MINECRAFT_1_19) ? switch (this) {
+ // >=1.19
+ case CROAKING -> 8;
+ case USING_TONGUE -> 9;
+ default -> version.noLessThan(ProtocolVersion.MINECRAFT_1_19_3) ? switch (this) {
+ // >=1.19.3
+ case SITTING -> 10;
+ case ROARING -> 11;
+ case SNIFFING -> 12;
+ case EMERGING -> 13;
+ case DIGGING -> 14;
+ default -> Pose.fail(this);
+ } : switch (this) {
+ // >=1.19
+ case ROARING -> 10;
+ case SNIFFING -> 11;
+ case EMERGING -> 12;
+ case DIGGING -> 13;
+ default -> Pose.fail(this);
+ };
+ } : Pose.fail(this);
+ } : this == Pose.DYING ? 6 : Pose.fail(this);
+ };
+ }
+ }
+
+ public static Pose fromProtocolId(int id, ProtocolVersion version) {
+ if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20)) {
+ return Pose.VALUES[id];
+ } else {
+ return switch (id) {
+ case 0 -> Pose.STANDING;
+ case 1 -> Pose.FALL_FLYING;
+ case 2 -> Pose.SLEEPING;
+ case 3 -> Pose.SWIMMING;
+ case 4 -> Pose.SPIN_ATTACK;
+ case 5 -> Pose.CROUCHING;
+ default -> version.noLessThan(ProtocolVersion.MINECRAFT_1_17) ? switch (id) {
+ // >=1.17
+ case 6 -> Pose.LONG_JUMPING;
+ case 7 -> Pose.DYING;
+ default -> version.noLessThan(ProtocolVersion.MINECRAFT_1_19) ? switch (id) {
+ // >=1.19
+ case 8 -> Pose.CROAKING;
+ case 9 -> Pose.USING_TONGUE;
+ default -> version.noLessThan(ProtocolVersion.MINECRAFT_1_19_3) ? switch (id) {
+ // >=1.19.3
+ case 10 -> Pose.SITTING;
+ case 11 -> Pose.ROARING;
+ case 12 -> Pose.SNIFFING;
+ case 13 -> Pose.EMERGING;
+ case 14 -> Pose.DIGGING;
+ default -> Pose.fail(id);
+ } : switch (id) {
+ // >=1.19
+ case 10 -> Pose.ROARING;
+ case 11 -> Pose.SNIFFING;
+ case 12 -> Pose.EMERGING;
+ case 13 -> Pose.DIGGING;
+ default -> Pose.fail(id);
+ };
+ } : Pose.fail(id);
+ } : id == 6 ? Pose.DYING : Pose.fail(id);
+ };
+ }
+ }
+
+ private static T fail(Object value) {
+ throw new IllegalStateException("Unexpected value: " + value);
+ }
+ }
+
+ /**
+ * @sinceMinecraft 1.19
+ */
+ public record CatVariant(int id) {
+
+ }
+
+ /**
+ * @sinceMinecraft 1.20.5
+ */
+ public record WolfVariant(int id) {
+
+ }
+
+ /**
+ * @sinceMinecraft 1.19
+ */
+ public record FrogVariant(int id) {
+
+ }
+
+ /**
+ * @sinceMinecraft 1.19
+ */
+ public record OptionalGlobalPos(@Nullable GlobalPos globalPos) {
+
+ public static final OptionalGlobalPos EMPTY = new OptionalGlobalPos(null);
+ }
+
+ /**
+ * @sinceMinecraft 1.19
+ */
+ public record PaintingVariant(int id) {
+
+ }
+
+ /**
+ * @sinceMinecraft 1.19.4
+ */
+ public enum SnifferState {
+
+ IDLING,
+ FEELING_HAPPY,
+ SCENTING,
+ SNIFFING,
+ SEARCHING,
+ DIGGING,
+ RISING;
+
+ public static final SnifferState[] VALUES = SnifferState.values();
+ }
+
+ /**
+ * @sinceMinecraft 1.20.5
+ */
+ public enum ArmadilloState { // 🤠
+
+ IDLE,
+ ROLLING,
+ SCARED,
+ UNROLLING;
+
+ public static final ArmadilloState[] VALUES = ArmadilloState.values();
+ }
+
+ /**
+ * @sinceMinecraft 1.19.4
+ */
+ public record Vector3(float x, float y, float z) {
+
+ }
+
+ /**
+ * @sinceMinecraft 1.19.4
+ */
+ public record Quaternion(float x, float y, float z, float w) {
+
+ }
+}
diff --git a/api/src/main/templates/net/elytrium/limboapi/BuildConstants.java b/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/GlobalPos.java
similarity index 57%
rename from api/src/main/templates/net/elytrium/limboapi/BuildConstants.java
rename to api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/GlobalPos.java
index f95103dc..550932beb 100644
--- a/api/src/main/templates/net/elytrium/limboapi/BuildConstants.java
+++ b/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/GlobalPos.java
@@ -5,10 +5,11 @@
* reference the LICENSE file in the api top-level directory.
*/
-package net.elytrium.limboapi;
+package net.elytrium.limboapi.api.protocol.packets.data;
-// The constants are replaced before compilation.
-public class BuildConstants {
+/**
+ * @sinceMinecraft 1.19
+ */
+public record GlobalPos(String dimension, BlockPos blockPos) {
- public static final String LIMBO_VERSION = "${version}";
}
diff --git a/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/ItemStack.java b/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/ItemStack.java
new file mode 100644
index 00000000..c74dfe7c
--- /dev/null
+++ b/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/ItemStack.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 - 2024 Elytrium
+ *
+ * The LimboAPI (excluding the LimboAPI plugin) is licensed under the terms of the MIT License. For more details,
+ * reference the LICENSE file in the api top-level directory.
+ */
+
+package net.elytrium.limboapi.api.protocol.packets.data;
+
+import net.elytrium.limboapi.api.protocol.item.DataComponentType;
+import net.elytrium.limboapi.api.protocol.item.ItemComponentMap;
+import net.kyori.adventure.nbt.CompoundBinaryTag;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+public record ItemStack(int material/*TODO VirtualItem*/, int amount, int data, @Nullable CompoundBinaryTag nbt, @Nullable ItemComponentMap map) implements EntityDataValue.Particle.ParticleData {
+
+ public static final ItemStack EMPTY = new ItemStack(-1, 0, 0, null, null);
+
+ public ItemStack(int material, int amount, @Nullable CompoundBinaryTag nbt) {
+ this(material, amount, nbt == null ? 0 : nbt.getInt("Damage", 0), nbt, null);
+ }
+
+ public ItemStack(int material, int amount, @Nullable ItemComponentMap map) {
+ this(material, amount, map == null ? 0 : map.getOrDefault(DataComponentType.DAMAGE, 0), map);
+ }
+
+ public ItemStack(int material, int amount, int data) {
+ this(material, amount, data, null, null);
+ }
+
+ public ItemStack(int material, int amount, int data, @Nullable CompoundBinaryTag nbt) {
+ this(material, amount, data, nbt, null);
+ }
+
+ public ItemStack(int material, int amount, int data, @Nullable ItemComponentMap map) {
+ this(material, amount, data, null, map);
+ }
+
+ public boolean isEmpty(boolean checkDamage) {
+ return this == ItemStack.EMPTY || this.material <= 0 || this.amount <= 0 || (checkDamage && (this.data < -32768 || this.data > 65535));
+ }
+}
diff --git a/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/MapData.java b/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/MapData.java
index fbea44ed..99788ab2 100644
--- a/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/MapData.java
+++ b/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/MapData.java
@@ -8,62 +8,43 @@
package net.elytrium.limboapi.api.protocol.packets.data;
/**
- * For MapData packet.
+ * For MapData packet
*/
-public class MapData {
+public record MapData(int columns, int rows, int posX, int posY, byte[] data) {
public static final int MAP_DIM_SIZE = 128;
public static final int MAP_SIZE = MAP_DIM_SIZE * MAP_DIM_SIZE; // 128² == 16384
- private final int columns;
- private final int rows;
- private final int posX;
- private final int posY;
- private final byte[] data;
-
public MapData(byte[] data) {
this(0, data);
}
public MapData(int posX, byte[] data) {
- this(MAP_DIM_SIZE, MAP_DIM_SIZE, posX, 0, data);
- }
-
- public MapData(int columns, int rows, int posX, int posY, byte[] data) {
- this.columns = columns;
- this.rows = rows;
- this.posX = posX;
- this.posY = posY;
- this.data = data;
+ this(MapData.MAP_DIM_SIZE, MapData.MAP_DIM_SIZE, posX, 0, data);
}
+ @Deprecated(forRemoval = true)
public int getColumns() {
return this.columns;
}
+ @Deprecated(forRemoval = true)
public int getRows() {
return this.rows;
}
+ @Deprecated(forRemoval = true)
public int getX() {
return this.posX;
}
+ @Deprecated(forRemoval = true)
public int getY() {
return this.posY;
}
+ @Deprecated(forRemoval = true)
public byte[] getData() {
return this.data;
}
-
- @Override
- public String toString() {
- return "MapData{"
- + "columns=" + this.columns
- + ", rows=" + this.rows
- + ", posX=" + this.posX
- + ", posY=" + this.posY
- + "}";
- }
}
diff --git a/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/MapPalette.java b/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/MapPalette.java
index ef19822e..2990baf3 100644
--- a/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/MapPalette.java
+++ b/api/src/main/java/net/elytrium/limboapi/api/protocol/packets/data/MapPalette.java
@@ -23,10 +23,10 @@
public class MapPalette {
private static final Map REMAP_BUFFERS = new EnumMap<>(MapVersion.class);
- private static final byte[] MAIN_BUFFER = readBuffer("/mapping/colors_main_map");
+ private static final byte[] MAIN_BUFFER = readBuffer("/mappings/colors_main_map");
/**
- * @deprecated Use {@link java.awt.Color#WHITE} instead.
+ * @deprecated Use {@link java.awt.Color#WHITE} instead
*/
@Deprecated
public static final byte WHITE = 34;
@@ -34,7 +34,7 @@ public class MapPalette {
static {
for (MapVersion version : MapVersion.values()) {
- REMAP_BUFFERS.put(version, readBuffer("/mapping/colors_" + version.toString().toLowerCase(Locale.ROOT) + "_map"));
+ REMAP_BUFFERS.put(version, readBuffer("/mappings/colors_" + version.toString().toLowerCase(Locale.ROOT) + "_map"));
}
}
@@ -47,24 +47,24 @@ private static byte[] readBuffer(String filename) {
}
/**
- * Convert an Image to a byte[] using the palette.
- * Uses reduced set of colors, to support more colors use {@link MapPalette#imageToBytes(BufferedImage, ProtocolVersion)}
+ * Convert an Image to a byte[] using the palette
+ * Uses a reduced set of colors, to support more colors use {@link MapPalette#imageToBytes(BufferedImage, ProtocolVersion)}
*
- * @param image The image to convert.
+ * @param image The image to convert
*
- * @return A byte[] containing the pixels of the image.
+ * @return A byte[] containing the pixels of the image
*/
public static int[] imageToBytes(BufferedImage image) {
return imageToBytes(image, ProtocolVersion.MINIMUM_VERSION);
}
/**
- * Convert an Image to a byte[] using the palette.
+ * Convert an Image to a byte[] using the palette
*
- * @param image The image to convert.
- * @param version The ProtocolVersion to support more colors.
+ * @param image The image to convert
+ * @param version The ProtocolVersion to support more colors
*
- * @return A byte[] containing the pixels of the image.
+ * @return A byte[] containing the pixels of the image
*/
public static int[] imageToBytes(BufferedImage image, ProtocolVersion version) {
int[] result = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());
@@ -72,25 +72,25 @@ public static int[] imageToBytes(BufferedImage image, ProtocolVersion version) {
}
/**
- * Convert an image to a byte[] using the palette.
+ * Convert an image to a byte[] using the palette
*
- * @param image The image to convert.
- * @param version The ProtocolVersion to support more colors.
+ * @param image The image to convert
+ * @param version The ProtocolVersion to support more colors
*
- * @return A byte[] containing the pixels of the image.
+ * @return A byte[] containing the pixels of the image
*/
public static int[] imageToBytes(int[] image, ProtocolVersion version) {
return imageToBytes(image, new int[image.length], version);
}
/**
- * Convert an image to a byte[] using the palette.
+ * Convert an image to a byte[] using the palette
*
- * @param from The image to convert.
- * @param to Output image.
- * @param version The ProtocolVersion to support more colors.
+ * @param from The image to convert
+ * @param to Output image
+ * @param version The ProtocolVersion to support more colors
*
- * @return A byte[] containing the pixels of the image.
+ * @return A byte[] containing the pixels of the image
*/
public static int[] imageToBytes(int[] from, int[] to, ProtocolVersion version) {
for (int i = 0; i < from.length; ++i) {
@@ -101,13 +101,13 @@ public static int[] imageToBytes(int[] from, int[] to, ProtocolVersion version)
}
/**
- * Convert an image to a byte[] using the palette.
+ * Convert an image to a byte[] using the palette
*
- * @param from The image to convert.
- * @param to Output image.
- * @param version The ProtocolVersion to support more colors.
+ * @param from The image to convert
+ * @param to Output image
+ * @param version The ProtocolVersion to support more colors
*
- * @return A byte[] containing the pixels of the image.
+ * @return A byte[] containing the pixels of the image
*/
public static byte[] imageToBytes(int[] from, byte[] to, ProtocolVersion version) {
for (int i = 0; i < from.length; ++i) {
@@ -118,23 +118,23 @@ public static byte[] imageToBytes(int[] from, byte[] to, ProtocolVersion version
}
/**
- * Get the index of the closest matching color in the palette to the given
- * color. Uses caching and downscaling of color values.
+ * Get the index of the closest matching color in the palette to the given color
+ * Uses caching and downscaling of color values
*
- * @param rgb The Color to match.
+ * @param rgb The Color to match
*
- * @return The index in the palette.
+ * @return The index in the palette
*/
public static byte tryFastMatchColor(int rgb, ProtocolVersion version) {
if (getAlpha(rgb) < 128) {
return TRANSPARENT;
} else {
MapVersion mapVersion = MapVersion.fromProtocolVersion(version);
- byte originalColorID = MAIN_BUFFER[rgb & 0xFFFFFF];
+ byte originalColorId = MAIN_BUFFER[rgb & 0xFFFFFF];
if (mapVersion == MapVersion.MAXIMUM_VERSION) {
- return originalColorID;
+ return originalColorId;
} else {
- return remapByte(REMAP_BUFFERS.get(mapVersion), originalColorID);
+ return remapByte(REMAP_BUFFERS.get(mapVersion), originalColorId);
}
}
}
@@ -146,10 +146,10 @@ private static int getAlpha(int rgb) {
/**
* Convert an image from MapVersion.MAXIMUM_VERSION to the desired version
*
- * @param image The image to convert.
- * @param version The ProtocolVersion to support more colors.
+ * @param image The image to convert
+ * @param version The ProtocolVersion to support more colors
*
- * @return A byte[] containing the pixels of the image.
+ * @return A byte[] containing the pixels of the image
*/
public static int[] convertImage(int[] image, MapVersion version) {
return convertImage(image, new int[image.length], version);
@@ -158,11 +158,11 @@ public static int[] convertImage(int[] image, MapVersion version) {
/**
* Convert an image from MapVersion.MAXIMUM_VERSION to the desired version
*
- * @param from The image to convert.
- * @param to Output image.
- * @param version The ProtocolVersion to support more colors.
+ * @param from The image to convert
+ * @param to Output image
+ * @param version The ProtocolVersion to support more colors
*
- * @return A byte[] containing the pixels of the image.
+ * @return A byte[] containing the pixels of the image
*/
public static int[] convertImage(int[] from, int[] to, MapVersion version) {
byte[] remapBuffer = REMAP_BUFFERS.get(version);
@@ -176,11 +176,11 @@ public static int[] convertImage(int[] from, int[] to, MapVersion version) {
/**
* Convert an image from MapVersion.MAXIMUM_VERSION to the desired version
*
- * @param from The image to convert.
- * @param to Output image.
- * @param version The ProtocolVersion to support more colors.
+ * @param from The image to convert
+ * @param to Output image
+ * @param version The ProtocolVersion to support more colors
*
- * @return A byte[] containing the pixels of the image.
+ * @return A byte[] containing the pixels of the image
*/
public static byte[] convertImage(byte[] from, byte[] to, MapVersion version) {
byte[] remapBuffer = REMAP_BUFFERS.get(version);
@@ -194,11 +194,11 @@ public static byte[] convertImage(byte[] from, byte[] to, MapVersion version) {
/**
* Convert an image from MapVersion.MAXIMUM_VERSION to the desired version
*
- * @param from The image to convert.
- * @param to Output image.
- * @param version The ProtocolVersion to support more colors.
+ * @param from The image to convert
+ * @param to Output image
+ * @param version The ProtocolVersion to support more colors
*
- * @return A byte[] containing the pixels of the image.
+ * @return A byte[] containing the pixels of the image
*/
public static byte[] convertImage(int[] from, byte[] to, MapVersion version) {
byte[] remapBuffer = REMAP_BUFFERS.get(version);
@@ -210,7 +210,7 @@ public static byte[] convertImage(int[] from, byte[] to, MapVersion version) {
}
private static byte remapByte(byte[] remapBuffer, byte oldByte) {
- return remapBuffer[Byte.toUnsignedInt(oldByte)];
+ return remapBuffer[oldByte & 0xFF];
}
public enum MapVersion {
diff --git a/build.gradle b/build.gradle
index 0ffa818b..d85ae7ea 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,71 +1,99 @@
-//file:noinspection GroovyAssignabilityCheck
-
plugins() {
id("java")
- id("checkstyle")
- id("com.github.spotbugs").version("6.0.12").apply(false)
- id("org.cadixdev.licenser").version("0.6.1").apply(false)
+ id("org.ajoberstar.grgit").version("5.2.2")
+
+ id("com.diffplug.spotless").version("6.25.0").apply(false)
+ id("com.github.spotbugs").version("6.0.19").apply(false)
+
+ id("io.github.goooler.shadow").version("8.1.8")
+}
+
+this.group = "net.elytrium"
+this.version = "1.2.0-SNAPSHOT"
+
+if (this.version.endsWith("-SNAPSHOT")) {
+ this.version += "+${grgit.head().abbreviatedId}"
}
-allprojects() {
+subprojects() {
+ apply(plugin: "java-library")
+
+ //apply(plugin: "com.diffplug.spotless")
apply(plugin: "checkstyle")
apply(plugin: "com.github.spotbugs")
- apply(plugin: "org.cadixdev.licenser")
- setGroup("net.elytrium.limboapi")
- setVersion("1.1.27")
+ tasks.withType(JavaCompile).configureEach() {
+ options.setEncoding("UTF-8")
+ }
+
+ java() {
+ sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17
+ }
- compileJava() {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
+ configurations() {
+ api.extendsFrom(shadowApi)
}
repositories() {
mavenCentral()
maven() {
- setName("elytrium-repo")
- setUrl("https://maven.elytrium.net/repo/")
+ name = "elytrium"
+ url = "https://maven.elytrium.net/repo/"
}
+
maven() {
- setName("papermc-repo")
- setUrl("https://papermc.io/repo/repository/maven-public/")
+ name = "papermc"
+ url = "https://repo.papermc.io/repository/maven-public/"
}
}
+ //spotless() {
+ // java() {
+ // licenseHeaderFile(rootProject.file("HEADER.txt"))
+ // }
+ //}
+
checkstyle() {
- toolVersion = "10.12.1"
- configFile = file("$rootDir/config/checkstyle/checkstyle.xml")
- configProperties = ["configDirectory": "$rootDir/config/checkstyle"]
+ toolVersion = "10.17.0"
+
+ configFile = rootProject.file(".config/checkstyle/checkstyle.xml")
maxErrors = 0
maxWarnings = 0
}
- spotbugs() {
- excludeFilter = file("${this.getRootDir()}/config/spotbugs/suppressions.xml")
-
- if (this.project != rootProject) {
- reports.register("html") {
+ spotbugsMain() {
+ excludeFilter.set(rootProject.file(".config/spotbugs/suppressions.xml"))
+ reports() {
+ html() {
required = true
- outputLocation.value(layout.buildDirectory.file("reports/spotbugs/main/spotbugs.html"))
+ outputLocation.value(layout.buildDirectory.file("reports/spotbugs/spotbugs.html"))
stylesheet = "fancy-hist.xsl"
}
}
}
}
-String getCurrentShortRevision() {
- OutputStream outputStream = new ByteArrayOutputStream()
- exec {
- if (System.getProperty("os.name").toLowerCase().contains("win")) {
- commandLine("cmd", "/c", "git rev-parse --short HEAD")
- } else {
- commandLine("bash", "-c", "git rev-parse --short HEAD")
- }
+gradle.projectsEvaluated() {
+ shadowJar() {
+ archiveClassifier = null
+
+ //enableRelocation = true
+ //relocationPrefix = "${this.group}.${this.rootProject.getName()}.3rdparty"
+ // TODO remove
+ relocate("org.bstats", "net.elytrium.limboapi.thirdparty.org.bstats")
+ relocate("net.elytrium.fastprepare", "net.elytrium.limboapi.thirdparty.fastprepare")
+ relocate("net.elytrium.commons.velocity", "net.elytrium.limboapi.thirdparty.commons.velocity")
+ relocate("net.elytrium.commons.kyori", "net.elytrium.limboapi.thirdparty.commons.kyori")
+ relocate("net.elytrium.commons.config", "net.elytrium.limboapi.thirdparty.commons.config")
- setStandardOutput(outputStream)
+ configurations = []
+ this.subprojects.forEach(project -> {
+ configurations.add(project.configurations.shadowApi)
+ from(project.sourceSets.main.output)
+ })
}
- return outputStream.toString().trim()
+ assemble.dependsOn(shadowJar)
}
diff --git a/gradle.properties b/gradle.properties
index 0fd62712..ea880281 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,11 +1,11 @@
-org.gradle.jvmargs=-Xmx4096m
-fastPrepareVersion=1.0.13
-velocityVersion=3.4.0-SNAPSHOT
-nettyVersion=4.1.86.Final
-fastutilVersion=8.5.11
-bstatsVersion=3.0.0
-spotbugsVersion=4.7.3
-elytriumCommonsVersion=1.2.3
-adventureVersion=4.15.0
+org.gradle.caching=true
+org.gradle.parallel=true
+
+org.gradle.jvmargs=-Xmx4G
+
manifestUrl=https://launchermeta.mojang.com/mc/game/version_manifest.json
-cacheValidMillis=6000000
\ No newline at end of file
+# 1 week
+cacheValidMillis=604800000
+
+# Well, yeah...
+gameVersions=1.21,1.20.6,1.20.5,1.20.4,1.20.3,1.20.2,1.20.1,1.20,1.19.4,1.19.3,1.19.2,1.19.1,1.19,1.18.2,1.18.1,1.18,1.17.1,1.17,1.16.5,1.16.4,1.16.3,1.16.2,1.16.1,1.16,1.15.2,1.15.1,1.15,1.14.4,1.14.3,1.14.2,1.14.1,1.14,1.13.2,1.13.1,1.13,1.12.2,1.12.1,1.12,1.11.2,1.11.1,1.11,1.10.2,1.10.1,1.10,1.9.4,1.9.3,1.9.2,1.9.1,1.9,1.8.9,1.8.8,1.8.7,1.8.6,1.8.5,1.8.4,1.8.3,1.8.2,1.8.1,1.8,1.7.10,1.7.9,1.7.8,1.7.7,1.7.6,1.7.5,1.7.4,1.7.3,1.7.2
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
new file mode 100644
index 00000000..c740b1b3
--- /dev/null
+++ b/gradle/libs.versions.toml
@@ -0,0 +1,19 @@
+[versions]
+velocity = "3.4.0-SNAPSHOT"
+
+# TODO
+[libraries]
+velocity-api = { module = "com.velocitypowered:velocity-api", version.ref = "velocity" }
+velocity-proxy = { module = "com.velocitypowered:velocity-proxy", version.ref = "velocity" } # from Elytrium repo
+
+[bundles]
+velocity = ["velocity-proxy"]
+
+[plugins]
+grgit = "org.ajoberstar.grgit:5.2.2"
+buildconfig = "com.github.gmazzo.buildconfig:5.3.5" # kotlin 💀
+
+spotless = "com.diffplug.spotless:6.25.0"
+spotbugs = "com.github.spotbugs:6.0.13"
+
+modrinth = "com:1"
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 41d9927a..2c352119 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 48c0a02c..7cf748e7 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-all.zip
+networkTimeout=10000
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 1b6c7873..f5feea6d 100755
--- a/gradlew
+++ b/gradlew
@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+# SPDX-License-Identifier: Apache-2.0
+#
##############################################################################
#
@@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -80,13 +82,12 @@ do
esac
done
-APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
-
-APP_NAME="Gradle"
+# This is normally unused
+# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
+' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -133,22 +134,29 @@ location of your Java installation."
fi
else
JAVACMD=java
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
+ fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -193,11 +201,15 @@ if "$cygwin" || "$msys" ; then
done
fi
-# Collect all arguments for the java command;
-# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
-# shell script including quotes and variable substitutions, so put them in
-# double quotes to make sure that they get re-expanded; and
-# * put everything else in single quotes, so that it's not re-expanded.
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
@@ -205,6 +217,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \
"$@"
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
diff --git a/gradlew.bat b/gradlew.bat
index 107acd32..9d21a218 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -13,8 +13,10 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
+@rem SPDX-License-Identifier: Apache-2.0
+@rem
-@if "%DEBUG%" == "" @echo off
+@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,7 +27,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@@ -40,13 +43,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
+if %ERRORLEVEL% equ 0 goto execute
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
@@ -56,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
@@ -75,13 +78,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
+if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
diff --git a/lobb.nbt b/lobb.nbt
new file mode 100644
index 00000000..35bb061a
Binary files /dev/null and b/lobb.nbt differ
diff --git a/mappings-1.13to1.12.nbt b/mappings-1.13to1.12.nbt
new file mode 100644
index 00000000..e246587a
Binary files /dev/null and b/mappings-1.13to1.12.nbt differ
diff --git a/plugin/build.gradle b/plugin/build.gradle
index 5bf07b13..05e0bb29 100644
--- a/plugin/build.gradle
+++ b/plugin/build.gradle
@@ -1,699 +1,39 @@
-//file:noinspection GroovyAssignabilityCheck
-
-buildscript() {
- dependencies() {
- classpath("commons-io:commons-io:2.6")
- classpath("com.google.guava:guava:28.0-jre")
- }
-}
+//file:noinspection VulnerableLibrariesLocal
plugins() {
- id("java")
- id("io.github.goooler.shadow").version("8.1.8")
+ id("com.modrinth.minotaur").version("2.8.7")
}
-compileJava() {
- getOptions().getRelease().set(17)
- getOptions().setEncoding("UTF-8")
-}
+apply(from: "mappings_generator.gradle")
dependencies() {
- implementation(project(":api"))
- implementation("net.elytrium.commons:config:$elytriumCommonsVersion")
- implementation("net.elytrium.commons:utils:$elytriumCommonsVersion")
- implementation("net.elytrium.commons:velocity:$elytriumCommonsVersion")
- implementation("net.elytrium.commons:kyori:$elytriumCommonsVersion")
-
- implementation("net.elytrium:fastprepare:$fastPrepareVersion")
- compileOnly("com.velocitypowered:velocity-api:$velocityVersion")
- annotationProcessor("com.velocitypowered:velocity-api:$velocityVersion")
- compileOnly("com.velocitypowered:velocity-proxy:$velocityVersion") // From Elytrium Repo.
- compileOnly("com.velocitypowered:velocity-native:$velocityVersion")
-
- // Needs for some velocity methods.
- compileOnly("io.netty:netty-codec:$nettyVersion")
- compileOnly("io.netty:netty-handler:$nettyVersion")
- compileOnly("it.unimi.dsi:fastutil-core:$fastutilVersion")
-
- implementation("org.bstats:bstats-velocity:$bstatsVersion")
-
- compileOnly("com.github.spotbugs:spotbugs-annotations:$spotbugsVersion")
-}
-
-shadowJar() {
- getArchiveClassifier().set("")
- setArchiveFileName("limboapi-${project.version}.jar")
-
- exclude("META-INF/versions/**")
- exclude("net/kyori/**")
-
- relocate("org.bstats", "net.elytrium.limboapi.thirdparty.org.bstats")
- relocate("net.elytrium.fastprepare", "net.elytrium.limboapi.thirdparty.fastprepare")
- relocate("net.elytrium.commons.velocity", "net.elytrium.limboapi.thirdparty.commons.velocity")
- relocate("net.elytrium.commons.kyori", "net.elytrium.limboapi.thirdparty.commons.kyori")
- relocate("net.elytrium.commons.config", "net.elytrium.limboapi.thirdparty.commons.config")
-}
-
-license() {
- matching(includes: ["**/mcprotocollib/**"]) {
- setHeader(getRootProject().file("HEADER_MCPROTOCOLLIB.txt"))
- }
- matching(includes: ["**/LoginListener.java", "**/KickListener.java", "**/LoginTasksQueue.java", "**/MinecraftLimitedCompressDecoder.java"]) {
- setHeader(getRootProject().file("HEADER_MIXED.txt"))
- }
-
- setHeader(getRootProject().file("HEADER.txt"))
-}
-
-tasks.register("finalize") {
- doLast {
- file("build/libs/${project.name}-${project.version}.jar").delete()
- }
-}
-
-assemble.dependsOn(shadowJar)
-build.finalizedBy(finalize)
-
-import groovy.io.FileType
-import groovy.json.JsonOutput
-import groovy.json.JsonSlurper
-import org.apache.commons.io.FilenameUtils
-import org.apache.commons.io.FileUtils
-import com.google.common.hash.Hashing
-import com.google.common.io.Files
-
-import java.nio.file.Path
-import java.util.function.Function
-import java.util.stream.Collectors
-
-enum MinecraftVersion {
- MINECRAFT_1_7_2(4),
- MINECRAFT_1_7_6(5),
- MINECRAFT_1_8(47),
- MINECRAFT_1_9(107),
- MINECRAFT_1_9_1(108),
- MINECRAFT_1_9_2(109),
- MINECRAFT_1_9_4(110),
- MINECRAFT_1_10(210),
- MINECRAFT_1_11(315),
- MINECRAFT_1_11_1(316),
- MINECRAFT_1_12(335),
- MINECRAFT_1_12_1(338),
- MINECRAFT_1_12_2(340),
- MINECRAFT_1_13(393),
- MINECRAFT_1_13_1(401),
- MINECRAFT_1_13_2(404),
- MINECRAFT_1_14(477),
- MINECRAFT_1_14_1(480),
- MINECRAFT_1_14_2(485),
- MINECRAFT_1_14_3(490),
- MINECRAFT_1_14_4(498),
- MINECRAFT_1_15(573),
- MINECRAFT_1_15_1(575),
- MINECRAFT_1_15_2(578),
- MINECRAFT_1_16(735),
- MINECRAFT_1_16_1(736),
- MINECRAFT_1_16_2(751),
- MINECRAFT_1_16_3(753),
- MINECRAFT_1_16_4(754),
- MINECRAFT_1_17(755),
- MINECRAFT_1_17_1(756),
- MINECRAFT_1_18(757),
- MINECRAFT_1_18_2(758),
- MINECRAFT_1_19(759),
- MINECRAFT_1_19_1(760),
- MINECRAFT_1_19_3(761),
- MINECRAFT_1_19_4(762),
- MINECRAFT_1_20(763),
- MINECRAFT_1_20_2(764),
- MINECRAFT_1_20_3(765),
- MINECRAFT_1_20_5(766),
- MINECRAFT_1_21(767),
- MINECRAFT_1_21_2(768)
-
- public static final List WORLD_VERSIONS = List.of(
- MINECRAFT_1_13,
- MINECRAFT_1_13_2,
- MINECRAFT_1_14,
- MINECRAFT_1_15,
- MINECRAFT_1_16,
- MINECRAFT_1_16_2,
- MINECRAFT_1_17,
- MINECRAFT_1_19,
- MINECRAFT_1_19_3,
- MINECRAFT_1_19_4,
- MINECRAFT_1_20,
- MINECRAFT_1_20_3,
- MINECRAFT_1_20_5,
- MINECRAFT_1_21_2
- )
-
- public static final MinecraftVersion MINIMUM_VERSION = MINECRAFT_1_7_2
- public static final MinecraftVersion MAXIMUM_VERSION = values()[values().length - 1]
-
- static MinecraftVersion fromVersionName(String name) {
- return valueOf("MINECRAFT_" + name.replace('.', '_'))
- }
-
- // Cache version name to reduce memory usage in general
- final String versionName = this.toString().substring(10).replace('_', '.')
- final int protocolVersion
-
- MinecraftVersion(int protocolVersion) {
- this.protocolVersion = protocolVersion
- }
-
- int getProtocolVersion() {
- return this.protocolVersion
- }
-
- String getVersionName() {
- return this.versionName
- }
-}
-
-project.ext.dataDirectory = new File(this.getLayout().getBuildDirectory().get().getAsFile(), "minecraft")
-project.ext.generatedDir = new File(this.getLayout().getBuildDirectory().get().getAsFile(), "generated/minecraft")
-project.ext.versionManifestFile = new File(dataDirectory, "manifest.json")
-
-sourceSets {
- main {
- resources {
- srcDirs += generatedDir
- }
- }
-}
-
-tasks.register("downloadManifest") {
- this.println("> Downloading version manifest...")
- versionManifestFile.getParentFile().mkdirs()
- if (checkIsCacheValid(versionManifestFile)) {
- FileUtils.copyURLToFile(new URL(manifestUrl), versionManifestFile)
- }
-}
-
-boolean checkIsCacheValid(File file) {
- if (file.exists() && System.currentTimeMillis() - file.lastModified() < Long.parseLong(cacheValidMillis)) {
- println("> Found cached " + file.getName())
- return false
- }
-
- return true
-}
-File downloadVersionManifest(String version) {
- this.println("> Downloading ${version} manifest...")
-
- Object manifest = new JsonSlurper().parse(versionManifestFile)
- def optional = manifest.versions.stream().filter({ it.id == version }).findFirst()
- if (optional.empty()) {
- throw new RuntimeException("Couldn't find version: ${version}")
- }
-
- File output = new File(dataDirectory, "${version}/manifest.json")
- output.getParentFile().mkdirs()
- FileUtils.copyURLToFile(new URL(optional.get().url), output)
- return output
-}
-
-@SuppressWarnings('GrMethodMayBeStatic')
-File getGeneratedCache(MinecraftVersion version) {
- File generated = new File(dataDirectory, "${version.getVersionName()}/generated")
- return new File(generated, "reports/blocks.json").exists()
- && new File(generated, "reports/${version >= MinecraftVersion.MINECRAFT_1_14 ? "registries" : "items"}.json").exists()
- && new File(generated, "data/minecraft/tags").exists()
- ? generated : null
-}
-
-static boolean validateServer(File file, String expected) {
- if (file == null || !file.exists()) {
- return false
- }
-
- def hash = Files.asByteSource(file).hash(Hashing.sha1())
- StringBuilder hashBuilder = new StringBuilder()
- hash.asBytes().each({hashBuilder.append(Integer.toString((it & 0xFF) + 0x100, 16).substring(1))})
- return hashBuilder.toString() == expected
-}
-
-File getServerJar(String version) {
- File manifestFile = this.downloadVersionManifest(version)
- Object manifest = new JsonSlurper().parse(manifestFile)
-
- File jarFile = new File(dataDirectory, "${version}/server.jar")
- if (!validateServer(jarFile, manifest.downloads.server.sha1)) {
- this.println("> Downloading ${version} server...")
- jarFile.getParentFile().mkdirs()
- FileUtils.copyURLToFile(new URL(manifest.downloads.server.url), jarFile)
- }
-
- return jarFile
-}
-
-File generateData(MinecraftVersion version) {
- File cache = getGeneratedCache(version)
- if (cache != null) {
- return cache
- }
-
- File jarFile = this.getServerJar(version.getVersionName())
- File targetDir = new File(jarFile.getParentFile(), "generated")
-
- try {
- FileUtils.deleteDirectory(targetDir)
- } catch (IOException ignored) {
- // Ignored.
- }
-
- String command
- if (version >= MinecraftVersion.MINECRAFT_1_18) {
- command = "\"%s\" -DbundlerMainClass=net.minecraft.data.Main -jar \"${jarFile.getAbsolutePath()}\" --reports --server"
- } else {
- command = "\"%s\" -cp \"${jarFile.getAbsolutePath()}\" net.minecraft.data.Main --reports --server"
- }
-
- exec {
- if (System.getProperty("os.name").toLowerCase().contains("win")) {
- File java = new File(System.getProperty("java.home"), "bin/java.exe")
- commandLine("cmd", "/c", String.format(command, java))
- } else {
- File java = new File(System.getProperty("java.home"), "bin/java")
- commandLine("bash", "-c", String.format(command, java))
- }
-
- workingDir(jarFile.getParentFile())
- }
-
- return targetDir
-}
-
-static Map> getDefaultProperties(Object data) {
- Map> defaultProperties = new HashMap<>()
-
- data.forEach({ key, block ->
- if (!block.containsKey("properties")) {
- return
- }
-
- for (Object blockState : block.states) {
- if (!blockState.containsKey("default") || !blockState.default) {
- continue
- }
-
- Map properties = blockState["properties"]
- defaultProperties.put(key, properties)
- break
- }
- })
-
- return defaultProperties
-}
-
-static Map> loadFallbackMapping(File file) {
- Object map = new JsonSlurper().parse(file)
- return MinecraftVersion.values().collectEntries({ version ->
- [version, map.getOrDefault(version.toString(), Collections.emptyMap())]
- })
-}
-
-static Map> loadLegacyMapping(File file) {
- return new JsonSlurper().parse(file).collectEntries({ version, mapping ->
- [MinecraftVersion.valueOf(version), mapping.collectEntries({ block, id ->
- [block, Integer.parseInt(id)]
- })]
- })
-}
-
-static int getBlockID(String block,
- Map> mappings,
- Map>> properties,
- Map> fallback,
- MinecraftVersion version) {
- Map> defaultProperties
- if (version >= MinecraftVersion.MINECRAFT_1_13) {
- defaultProperties = properties[version]
- } else {
- defaultProperties = properties[MinecraftVersion.MINECRAFT_1_18_2]
- }
-
- String[] split = block.split("\\[")
- String noArgBlock = split[0]
-
- MinecraftVersion fallbackVersion = MinecraftVersion.MAXIMUM_VERSION
- while (fallbackVersion != version) {
- --fallbackVersion
- noArgBlock = fallback[fallbackVersion].getOrDefault(noArgBlock, noArgBlock)
- }
-
- Map blockProperties = defaultProperties[noArgBlock]
- String targetBlockID
- if (blockProperties == null) {
- targetBlockID = noArgBlock
- } else {
- Map currentProperties = new TreeMap<>(blockProperties)
- if (split.length > 1) {
- String[] args = split[1].split(",")
- Map input = Arrays.stream(args)
- .map(arg -> arg.replace("]", "").split("="))
- .collect(Collectors.toMap(parts -> parts[0], parts -> parts[1]))
-
- input.forEach({ key, value ->
- if (currentProperties.containsKey(key)) {
- currentProperties.put(key, value)
- }
- })
- }
-
- targetBlockID = noArgBlock + Arrays.toString(
- currentProperties.collect({ k, v -> k + "=" + v }).toArray()
- ).replace(" ", "")
- }
-
- Integer id = mappings[version][targetBlockID]
- if (id == null && blockProperties != null) {
- targetBlockID = noArgBlock + Arrays.toString(
- new TreeMap<>(blockProperties).collect({ k, v -> k + "=" + v }).toArray()
- ).replace(" ", "")
- id = mappings[version][targetBlockID]
- }
-
- if (id == null) {
- System.err.println("No ${version.getVersionName()} fallback data for ${noArgBlock}, replacing with minecraft:stone")
- id = 1
- }
-
- return id
-}
-
-static Map getBlockMappings(Object data, Map> defaultPropertiesMap) {
- Map mapping = new HashMap<>()
-
- data.forEach({ blockID, blockData ->
- for (Object blockState : blockData.states) {
- int protocolID = blockState.id
-
- if (blockState.containsKey("properties")) {
- Map stateProperties = blockState["properties"]
- Map properties = new TreeMap<>(
- defaultPropertiesMap.getOrDefault(blockID, Collections.emptyMap()))
-
- properties.putAll(stateProperties)
-
- String stateID = blockID + Arrays.toString(
- properties.collect({ k, v -> k + "=" + v }).toArray()
- ).replace(" ", "")
-
- mapping.put(stateID, protocolID)
- } else {
- mapping.put(blockID, protocolID)
- }
- }
- })
-
- return mapping
-}
-
-void generateBlockMappings(File targetDir, Map blockReports) {
- File defaultBlockPropertiesFile = new File(targetDir, "defaultblockproperties.json")
- File blockStatesFile = new File(targetDir, "blockstates.json")
- File blockStatesMappingFile = new File(targetDir, "blockstates_mapping.json")
- File legacyBlocksFile = new File(targetDir, "legacyblocks.json")
-
- if (checkIsCacheValid(defaultBlockPropertiesFile) || checkIsCacheValid(blockStatesFile)
- || checkIsCacheValid(blockStatesMappingFile) || checkIsCacheValid(legacyBlocksFile)) {
- this.println("> Generating default block properties...")
-
- Map>> defaultProperties =
- blockReports.collectEntries({ version, report ->
- [version, getDefaultProperties(report)]
- })
-
- defaultBlockPropertiesFile.write(JsonOutput.prettyPrint(
- JsonOutput.toJson(defaultProperties[MinecraftVersion.MAXIMUM_VERSION].sort())), "UTF-8")
-
- this.println("> Generating blockstates...")
-
- Map> mappings = loadLegacyMapping(
- new File(this.getProjectDir(), "mapping/legacyblockmapping.json"))
-
- blockReports.forEach({ version, report ->
- mappings.put(version, getBlockMappings(report, defaultProperties[version]))
- })
-
- Map blocks = mappings[MinecraftVersion.MAXIMUM_VERSION]
-
- blockStatesFile.write(
- JsonOutput.prettyPrint(JsonOutput.toJson(
- blocks.sort(Map.Entry::getValue)
- .collectEntries({ k, v -> [k, String.valueOf(v)] })
- )), "UTF-8")
-
-
-
- this.println("> Generating blockstates mapping...")
-
- Map> fallbackMapping = loadFallbackMapping(
- new File(this.getProjectDir(), "mapping/fallbackdata.json"))
-
- Map> blockstateMapping = new LinkedHashMap<>()
- blocks.sort(Map.Entry::getValue)
- .forEach({ block, modernID ->
- Map blockMapping = new LinkedHashMap<>()
-
- int lastID = -1
- for (MinecraftVersion version : MinecraftVersion.values()) {
- int id = getBlockID(block, mappings, defaultProperties, fallbackMapping, version)
- if (lastID != id) {
- blockMapping.put(version.getVersionName(), String.valueOf(lastID = id))
- }
- }
-
- blockstateMapping.put(String.valueOf(modernID), blockMapping)
- })
-
- blockStatesMappingFile.write(
- JsonOutput.prettyPrint(JsonOutput.toJson(blockstateMapping)), "UTF-8")
-
- this.println("> Generating legacy blocks...")
-
- Map legacyData = new JsonSlurper().parse(
- new File(this.getProjectDir(), "mapping/legacyblocks.json"))
-
- legacyData = legacyData.collectEntries({ legacy, modern ->
- [legacy, String.valueOf(getBlockID(modern, mappings, defaultProperties, fallbackMapping, MinecraftVersion.MAXIMUM_VERSION))]
- })
-
- legacyBlocksFile.write(
- JsonOutput.prettyPrint(JsonOutput.toJson(legacyData)), "UTF-8")
- }
-}
-
-static Map> sortRegistryMapping(Map> mapping) {
- return mapping.collectEntries({ modernID, map ->
- [modernID, map.sort({
- if (it.getKey().contains(".")) {
- return MinecraftVersion.fromVersionName(it.getKey())
- } else {
- return MinecraftVersion.MINIMUM_VERSION
- }
- })]
- }).sort()
-}
-
-void generateRegistryMapping(String target, File targetDir, Map registriesReports) {
- File targetFile = new File(targetDir, "${target}s.json");
- File targetMappingFile = new File(targetDir, "${target}s_mapping.json");
- if (checkIsCacheValid(targetFile) || checkIsCacheValid(targetMappingFile)) {
- this.println("> Generating ${target}s...")
-
- Map> idMap =
- registriesReports.collectEntries({ version, registry ->
- Object entries = registry["minecraft:${target}"].entries
- return [version, entries.collectEntries({ name, id -> [name, String.valueOf(id["protocol_id"])] })]
- })
-
- Map modernIDs = Collections.max(idMap.entrySet(), Map.Entry.comparingByKey()).getValue()
-
- targetFile.write(JsonOutput.prettyPrint(
- JsonOutput.toJson(modernIDs.sort({Integer.parseInt(it.getValue()) }))), "UTF-8")
-
- this.println("> Generating ${target}s mapping...")
-
- Map> mapping = new JsonSlurper()
- .parse(new File(this.getProjectDir(), "mapping/legacy_${target}s_mapping.json"))
- .collectEntries({ key, value -> {
- if (modernIDs[key] == null) {
- throw new IllegalStateException("No modern id found for $key")
- }
-
- return [modernIDs[key], value]
- } })
-
- idMap.forEach({ version, ids ->
- ids.forEach({ key, id ->
- if (!modernIDs.containsKey(key)) {
- return
- }
-
- mapping.computeIfAbsent(modernIDs[key], _ -> new LinkedHashMap<>()).put(version.getVersionName(), id)
- })
- })
-
- mapping = sortRegistryMapping(mapping)
- targetMappingFile.write(JsonOutput.prettyPrint(
- JsonOutput.toJson(mapping.sort({ Integer.parseInt(it.getKey()) }))), "UTF-8")
- }
-}
-
-void generateRegistryMappings(File targetDir, Map registriesReports) {
- this.generateRegistryMapping("item", targetDir, registriesReports
- .findAll({ e -> MinecraftVersion.WORLD_VERSIONS.contains(e.getKey()) }))
- this.generateRegistryMapping("block", targetDir, registriesReports)
- this.generateRegistryMapping("data_component_type", targetDir, registriesReports
- .findAll({ e -> e.getKey() >= MinecraftVersion.MINECRAFT_1_20_5 }))
-
- File blockEntitiesMappingFile = new File(targetDir, "blockentities_mapping.json");
-
- if (checkIsCacheValid(blockEntitiesMappingFile)) {
- this.println("> Generating blockentities mapping...")
-
- Map> blockentities = new JsonSlurper()
- .parse(new File(this.getProjectDir(), "mapping/legacy_blockentities_mapping.json"))
-
- registriesReports.forEach({ version, registries ->
- if (version < MinecraftVersion.MINECRAFT_1_19) {
- return
- }
-
- registries["minecraft:block_entity_type"].entries.forEach({ key, value ->
- int id = value.protocol_id
- blockentities.computeIfAbsent(key, _ -> new LinkedHashMap<>())
- .put(version.getVersionName(), String.valueOf(id))
- })
- })
-
- blockentities = sortRegistryMapping(blockentities)
- blockEntitiesMappingFile.write(
- JsonOutput.prettyPrint(JsonOutput.toJson(blockentities)), "UTF-8")
- }
-}
-
-static Map>> getTags(File tagDir, Map tagTypes) {
- Map>> tags = new LinkedHashMap<>()
-
- tagTypes.forEach({ directory, key ->
- File directoryFile = new File(tagDir, directory)
- if (!directoryFile.exists()) {
- return
- }
-
- Map> typeTags = new HashMap<>()
- Map> tempTags = new HashMap<>()
-
- directoryFile.eachFileRecurse(FileType.FILES, { file ->
- List values = new JsonSlurper().parse(file).values
- Path relativePath = directoryFile.toPath().relativize(file.toPath())
- String name = FilenameUtils.removeExtension(relativePath.toString()).replace(File.separatorChar, '/' as char)
- typeTags.put("minecraft:" + name, values)
- })
-
- boolean flatten = false
- while (!flatten) {
- flatten = true
-
- typeTags.forEach({ name, currentTags ->
- List newTags = new ArrayList<>()
- currentTags.forEach({ currentTag ->
- if (currentTag.startsWith("#")) {
- newTags.addAll(typeTags.get(currentTag.substring(1)))
- flatten = false
- } else {
- newTags.add(currentTag)
- }
- })
-
- tempTags.put(name, newTags)
- })
-
- typeTags = tempTags
- tempTags = new HashMap<>()
- }
-
- tags.put(key, typeTags)
- })
-
- return tags
-}
-
-void generateTags(File targetDir, Map tagDirs) {
- File tagsFile = new File(targetDir, "tags.json");
- if (checkIsCacheValid(tagsFile)) {
- this.println("> Generating tags...")
-
- Map tagTypes = new JsonSlurper().parse(new File(getProjectDir(), "mapping/tag_types.json"))
-
- Map>>> allTags =
- tagDirs.collectEntries({ version, dir ->
- [version, getTags(dir, tagTypes.tag_types)]
- })
-
- Map>> mergedTags = new LinkedHashMap<>()
-
- allTags.forEach({ version, tags ->
- tags.forEach({ type, typeTags -> {
- Map> mergedTypeTags = mergedTags.computeIfAbsent(type, _ -> new HashMap<>())
- typeTags.forEach({ name, values ->
- Set mergedValues = mergedTypeTags.computeIfAbsent(name, _ -> new HashSet<>())
- if (!tagTypes.supported_tag_types.contains(type)) {
- return
- }
-
- mergedValues.addAll(values)
- })
- }})
- })
-
- mergedTags = mergedTags.collectEntries({ type, typeTags ->
- [type, typeTags.collectEntries({ name, values ->
- [name, values.sort()]
- }).sort()]
- })
-
- tagsFile.write(JsonOutput.prettyPrint(JsonOutput.toJson(mergedTags)), "UTF-8")
- }
-}
-
-tasks.register("generateMappings") {
- dependsOn(downloadManifest)
-
- File targetDir = new File(generatedDir, "mapping")
- targetDir.mkdirs()
-
- this.println("> Generating Minecraft data...")
-
- Map generated = Arrays.stream(MinecraftVersion.values())
- .dropWhile({ it < MinecraftVersion.MINECRAFT_1_13 })
- .collect(Collectors.toMap(Function.identity(), this::generateData))
-
- Map blockReports = generated.collectEntries({ version, directory ->
- [version, new JsonSlurper().parse(new File(directory, "reports/blocks.json"))]
- })
+ annotationProcessor(libs.velocity.api)
+ compileOnly("com.velocitypowered:velocity-proxy:3.4.0-SNAPSHOT") // From Elytrium repo
+ compileOnly("com.velocitypowered:velocity-native:3.3.0-SNAPSHOT")
- this.generateBlockMappings(targetDir, blockReports)
+ compileOnly("io.netty:netty-codec:4.1.86.Final")
+ compileOnly("io.netty:netty-handler:4.1.86.Final")
+ compileOnly("it.unimi.dsi:fastutil-core:8.5.11")
- Map registriesReports = generated
- .findAll({ it.getKey() >= MinecraftVersion.MINECRAFT_1_14 })
- .collectEntries({ version, directory ->
- [version, new JsonSlurper().parse(new File(directory, "reports/registries.json"))]
- })
+ compileOnly(project(":api"))
+ // TODO remove
+ shadowApi("net.elytrium.commons:config:1.2.3")
+ shadowApi("net.elytrium.commons:kyori:1.2.3")
- this.generateRegistryMappings(targetDir, registriesReports)
+ shadowApi("net.elytrium:fastprepare:1.0.13")
- Map tags = generated
- .collectEntries({ version, directory ->
- [version, new File(directory, "data/minecraft/tags")]
- })
+ shadowApi("org.bstats:bstats-velocity:3.0.0")
- this.generateTags(targetDir, tags)
+ compileOnly("com.github.spotbugs:spotbugs-annotations:4.7.3")
}
-processResources.dependsOn(generateMappings)
\ No newline at end of file
+//license() {
+// matching(includes: ["**/mcprotocollib/**"]) {
+// setHeader(getRootProject().file("HEADER_MCPROTOCOLLIB.txt"))
+// }
+// matching(includes: ["**/LoginListener.java", "**/LoginTasksQueue.java", "**/MinecraftLimitedCompressDecoder.java"]) {
+// setHeader(getRootProject().file("HEADER_MIXED.txt"))
+// }
+//
+// setHeader(getRootProject().file("HEADER.txt"))
+//}
diff --git a/plugin/mapping/legacy_blockentities_mapping.json b/plugin/mapping/legacy_blockentities_mapping.json
deleted file mode 100644
index c5d3ea3f..00000000
--- a/plugin/mapping/legacy_blockentities_mapping.json
+++ /dev/null
@@ -1,116 +0,0 @@
-{
- "minecraft:banner": {
- "legacy": "18"
- },
- "minecraft:barrel": {
- "legacy": "25"
- },
- "minecraft:beacon": {
- "legacy": "13"
- },
- "minecraft:bed": {
- "legacy": "23"
- },
- "minecraft:beehive": {
- "legacy": "32"
- },
- "minecraft:bell": {
- "legacy": "29"
- },
- "minecraft:blast_furnace": {
- "legacy": "27"
- },
- "minecraft:brewing_stand": {
- "legacy": "10"
- },
- "minecraft:campfire": {
- "legacy": "31"
- },
- "minecraft:chest": {
- "legacy": "1"
- },
- "minecraft:chiseled_bookshelf": {
- "legacy": "36"
- },
- "minecraft:command_block": {
- "legacy": "21"
- },
- "minecraft:comparator": {
- "legacy": "17"
- },
- "minecraft:conduit": {
- "legacy": "24"
- },
- "minecraft:daylight_detector": {
- "legacy": "15"
- },
- "minecraft:dispenser": {
- "legacy": "5"
- },
- "minecraft:dropper": {
- "legacy": "6"
- },
- "minecraft:enchanting_table": {
- "legacy": "11"
- },
- "minecraft:end_gateway": {
- "legacy": "20"
- },
- "minecraft:end_portal": {
- "legacy": "12"
- },
- "minecraft:ender_chest": {
- "legacy": "3"
- },
- "minecraft:furnace": {
- "legacy": "0"
- },
- "minecraft:hanging_sign": {
- "legacy": "7"
- },
- "minecraft:hopper": {
- "legacy": "16"
- },
- "minecraft:jigsaw": {
- "legacy": "30"
- },
- "minecraft:jukebox": {
- "legacy": "4"
- },
- "minecraft:lectern": {
- "legacy": "28"
- },
- "minecraft:mob_spawner": {
- "legacy": "8"
- },
- "minecraft:piston": {
- "legacy": "9"
- },
- "minecraft:sculk_catalyst": {
- "legacy": "34"
- },
- "minecraft:sculk_sensor": {
- "legacy": "33"
- },
- "minecraft:sculk_shrieker": {
- "legacy": "35"
- },
- "minecraft:shulker_box": {
- "legacy": "22"
- },
- "minecraft:sign": {
- "legacy": "7"
- },
- "minecraft:skull": {
- "legacy": "14"
- },
- "minecraft:smoker": {
- "legacy": "26"
- },
- "minecraft:structure_block": {
- "legacy": "19"
- },
- "minecraft:trapped_chest": {
- "legacy": "2"
- }
-}
\ No newline at end of file
diff --git a/plugin/mapping/fallbackdata.json b/plugin/mappings/fallback_data.json
old mode 100755
new mode 100644
similarity index 99%
rename from plugin/mapping/fallbackdata.json
rename to plugin/mappings/fallback_data.json
index b2177026..7f010f63
--- a/plugin/mapping/fallbackdata.json
+++ b/plugin/mappings/fallback_data.json
@@ -427,7 +427,7 @@
"minecraft:bee_nest": "minecraft:birch_planks",
"minecraft:beehive": "minecraft:birch_planks",
"minecraft:honeycomb_block": "minecraft:yellow_glazed_terracotta",
- "minecraft:honey_block": "minecraft:yellow_stained_glass"
+ "minecraft:honey_block": "minecraft:yellow_stained_glass"
},
"MINECRAFT_1_13_2": {
"minecraft:lily_of_the_valley": "minecraft:white_tulip",
diff --git a/plugin/mappings/legacy_block_entity_types_mappings.json b/plugin/mappings/legacy_block_entity_types_mappings.json
new file mode 100644
index 00000000..b395147e
--- /dev/null
+++ b/plugin/mappings/legacy_block_entity_types_mappings.json
@@ -0,0 +1,130 @@
+{
+ "minecraft:banner": {
+ "1.11": 19,
+ "1.12": 19,
+ "1.13": 18
+ },
+ "minecraft:beacon": {
+ "1.11": 13,
+ "1.12": 13,
+ "1.13": 13
+ },
+ "minecraft:bed": {
+ "1.12": 24,
+ "1.13": 23
+ },
+ "minecraft:brewing_stand": {
+ "1.11": 10,
+ "1.12": 10,
+ "1.13": 10
+ },
+ "minecraft:chest": {
+ "1.11": 1,
+ "1.12": 1,
+ "1.13": 1
+ },
+ "minecraft:command_block": {
+ "1.11": 22,
+ "1.12": 22,
+ "1.13": 21
+ },
+ "minecraft:comparator": {
+ "1.11": 17,
+ "1.12": 17,
+ "1.13": 17
+ },
+ "minecraft:conduit": {
+ "1.13": 24
+ },
+ "minecraft:daylight_detector": {
+ "1.11": 15,
+ "1.12": 15,
+ "1.13": 15
+ },
+ "minecraft:dispenser": {
+ "1.11": 4,
+ "1.12": 4,
+ "1.13": 5
+ },
+ "minecraft:dropper": {
+ "1.11": 5,
+ "1.12": 5,
+ "1.13": 6
+ },
+ "minecraft:enchanting_table": {
+ "1.11": 11,
+ "1.12": 11,
+ "1.13": 11
+ },
+ "minecraft:end_gateway": {
+ "1.11": 21,
+ "1.12": 21,
+ "1.13": 20
+ },
+ "minecraft:end_portal": {
+ "1.11": 12,
+ "1.12": 12,
+ "1.13": 12
+ },
+ "minecraft:ender_chest": {
+ "1.11": 2,
+ "1.12": 2,
+ "1.13": 3
+ },
+ "minecraft:flower_pot": {
+ "1.11": 18,
+ "1.12": 18
+ },
+ "minecraft:furnace": {
+ "1.11": 0,
+ "1.12": 0,
+ "1.13": 0
+ },
+ "minecraft:hopper": {
+ "1.11": 16,
+ "1.12": 16,
+ "1.13": 16
+ },
+ "minecraft:jukebox": {
+ "1.11": 3,
+ "1.12": 3,
+ "1.13": 4
+ },
+ "minecraft:mob_spawner": {
+ "1.11": 7,
+ "1.12": 7,
+ "1.13": 8
+ },
+ "minecraft:noteblock": {
+ "1.11": 8,
+ "1.12": 8
+ },
+ "minecraft:piston": {
+ "1.11": 9,
+ "1.12": 9,
+ "1.13": 9
+ },
+ "minecraft:shulker_box": {
+ "1.11": 23,
+ "1.12": 23,
+ "1.13": 22
+ },
+ "minecraft:sign": {
+ "1.11": 6,
+ "1.12": 6,
+ "1.13": 7
+ },
+ "minecraft:skull": {
+ "1.11": 14,
+ "1.12": 14,
+ "1.13": 14
+ },
+ "minecraft:structure_block": {
+ "1.11": 20,
+ "1.12": 20,
+ "1.13": 19
+ },
+ "minecraft:trapped_chest": {
+ "1.13": 2
+ }
+}
\ No newline at end of file
diff --git a/plugin/mapping/legacyblockmapping.json b/plugin/mappings/legacy_block_mappings.json
old mode 100755
new mode 100644
similarity index 100%
rename from plugin/mapping/legacyblockmapping.json
rename to plugin/mappings/legacy_block_mappings.json
diff --git a/plugin/mapping/legacyblocks.json b/plugin/mappings/legacy_blocks.json
similarity index 100%
rename from plugin/mapping/legacyblocks.json
rename to plugin/mappings/legacy_blocks.json
diff --git a/plugin/mapping/legacy_blocks_mapping.json b/plugin/mappings/legacy_blocks_mappings.json
similarity index 100%
rename from plugin/mapping/legacy_blocks_mapping.json
rename to plugin/mappings/legacy_blocks_mappings.json
diff --git a/plugin/mapping/legacy_data_component_types_mapping.json b/plugin/mappings/legacy_data_component_types_mappings.json
similarity index 100%
rename from plugin/mapping/legacy_data_component_types_mapping.json
rename to plugin/mappings/legacy_data_component_types_mappings.json
diff --git a/plugin/mapping/legacy_items_mapping.json b/plugin/mappings/legacy_items_mappings.json
similarity index 100%
rename from plugin/mapping/legacy_items_mapping.json
rename to plugin/mappings/legacy_items_mappings.json
diff --git a/plugin/mappings/legacy_particle_types_mappings.json b/plugin/mappings/legacy_particle_types_mappings.json
new file mode 100644
index 00000000..ae8f35bf
--- /dev/null
+++ b/plugin/mappings/legacy_particle_types_mappings.json
@@ -0,0 +1,252 @@
+{
+ "minecraft:ambient_entity_effect": {
+ "1.13": "0",
+ "1.13.1": "0",
+ "1.13.2": "0"
+ },
+ "minecraft:angry_villager": {
+ "1.13": "1",
+ "1.13.1": "1",
+ "1.13.2": "1"
+ },
+ "minecraft:barrier": {
+ "1.13": "2",
+ "1.13.1": "2",
+ "1.13.2": "2"
+ },
+ "minecraft:block": {
+ "1.13": "3",
+ "1.13.1": "3",
+ "1.13.2": "3"
+ },
+ "minecraft:bubble": {
+ "1.13": "4",
+ "1.13.1": "4",
+ "1.13.2": "4"
+ },
+ "minecraft:cloud": {
+ "1.13": "5",
+ "1.13.1": "5",
+ "1.13.2": "5"
+ },
+ "minecraft:crit": {
+ "1.13": "6",
+ "1.13.1": "6",
+ "1.13.2": "6"
+ },
+ "minecraft:damage_indicator": {
+ "1.13": "7",
+ "1.13.1": "7",
+ "1.13.2": "7"
+ },
+ "minecraft:dragon_breath": {
+ "1.13": "8",
+ "1.13.1": "8",
+ "1.13.2": "8"
+ },
+ "minecraft:dripping_lava": {
+ "1.13": "9",
+ "1.13.1": "9",
+ "1.13.2": "9"
+ },
+ "minecraft:dripping_water": {
+ "1.13": "10",
+ "1.13.1": "10",
+ "1.13.2": "10"
+ },
+ "minecraft:dust": {
+ "1.13": "11",
+ "1.13.1": "11",
+ "1.13.2": "11"
+ },
+ "minecraft:effect": {
+ "1.13": "12",
+ "1.13.1": "12",
+ "1.13.2": "12"
+ },
+ "minecraft:elder_guardian": {
+ "1.13": "13",
+ "1.13.1": "13",
+ "1.13.2": "13"
+ },
+ "minecraft:enchanted_hit": {
+ "1.13": "14",
+ "1.13.1": "14",
+ "1.13.2": "14"
+ },
+ "minecraft:enchant": {
+ "1.13": "15",
+ "1.13.1": "15",
+ "1.13.2": "15"
+ },
+ "minecraft:end_rod": {
+ "1.13": "16",
+ "1.13.1": "16",
+ "1.13.2": "16"
+ },
+ "minecraft:entity_effect": {
+ "1.13": "17",
+ "1.13.1": "17",
+ "1.13.2": "17"
+ },
+ "minecraft:explosion_emitter": {
+ "1.13": "18",
+ "1.13.1": "18",
+ "1.13.2": "18"
+ },
+ "minecraft:explosion": {
+ "1.13": "19",
+ "1.13.1": "19",
+ "1.13.2": "19"
+ },
+ "minecraft:falling_dust": {
+ "1.13": "20",
+ "1.13.1": "20",
+ "1.13.2": "20"
+ },
+ "minecraft:firework": {
+ "1.13": "21",
+ "1.13.1": "21",
+ "1.13.2": "21"
+ },
+ "minecraft:fishing": {
+ "1.13": "22",
+ "1.13.1": "22",
+ "1.13.2": "22"
+ },
+ "minecraft:flame": {
+ "1.13": "23",
+ "1.13.1": "23",
+ "1.13.2": "23"
+ },
+ "minecraft:happy_villager": {
+ "1.13": "24",
+ "1.13.1": "24",
+ "1.13.2": "24"
+ },
+ "minecraft:heart": {
+ "1.13": "25",
+ "1.13.1": "25",
+ "1.13.2": "25"
+ },
+ "minecraft:instant_effect": {
+ "1.13": "26",
+ "1.13.1": "26",
+ "1.13.2": "26"
+ },
+ "minecraft:item": {
+ "1.13": "27",
+ "1.13.1": "27",
+ "1.13.2": "27"
+ },
+ "minecraft:item_slime": {
+ "1.13": "28",
+ "1.13.1": "28",
+ "1.13.2": "28"
+ },
+ "minecraft:item_snowball": {
+ "1.13": "29",
+ "1.13.1": "29",
+ "1.13.2": "29"
+ },
+ "minecraft:large_smoke": {
+ "1.13": "30",
+ "1.13.1": "30",
+ "1.13.2": "30"
+ },
+ "minecraft:lava": {
+ "1.13": "31",
+ "1.13.1": "31",
+ "1.13.2": "31"
+ },
+ "minecraft:mycelium": {
+ "1.13": "32",
+ "1.13.1": "32",
+ "1.13.2": "32"
+ },
+ "minecraft:note": {
+ "1.13": "33",
+ "1.13.1": "33",
+ "1.13.2": "33"
+ },
+ "minecraft:poof": {
+ "1.13": "34",
+ "1.13.1": "34",
+ "1.13.2": "34"
+ },
+ "minecraft:portal": {
+ "1.13": "35",
+ "1.13.1": "35",
+ "1.13.2": "35"
+ },
+ "minecraft:rain": {
+ "1.13": "36",
+ "1.13.1": "36",
+ "1.13.2": "36"
+ },
+ "minecraft:smoke": {
+ "1.13": "37",
+ "1.13.1": "37",
+ "1.13.2": "37"
+ },
+ "minecraft:spit": {
+ "1.13": "38",
+ "1.13.1": "38",
+ "1.13.2": "38"
+ },
+ "minecraft:squid_ink": {
+ "1.13": "39",
+ "1.13.1": "39",
+ "1.13.2": "39"
+ },
+ "minecraft:sweep_attack": {
+ "1.13": "40",
+ "1.13.1": "40",
+ "1.13.2": "40"
+ },
+ "minecraft:totem_of_undying": {
+ "1.13": "41",
+ "1.13.1": "41",
+ "1.13.2": "41"
+ },
+ "minecraft:underwater": {
+ "1.13": "42",
+ "1.13.1": "42",
+ "1.13.2": "42"
+ },
+ "minecraft:splash": {
+ "1.13": "43",
+ "1.13.1": "43",
+ "1.13.2": "43"
+ },
+ "minecraft:witch": {
+ "1.13": "44",
+ "1.13.1": "44",
+ "1.13.2": "44"
+ },
+ "minecraft:bubble_pop": {
+ "1.13": "45",
+ "1.13.1": "45",
+ "1.13.2": "45"
+ },
+ "minecraft:current_down": {
+ "1.13": "46",
+ "1.13.1": "46",
+ "1.13.2": "46"
+ },
+ "minecraft:bubble_column_up": {
+ "1.13": "47",
+ "1.13.1": "47",
+ "1.13.2": "47"
+ },
+ "minecraft:nautilus": {
+ "1.13": "48",
+ "1.13.1": "48",
+ "1.13.2": "48"
+ },
+ "minecraft:dolphin": {
+ "1.13": "49",
+ "1.13.1": "49",
+ "1.13.2": "49"
+ }
+}
\ No newline at end of file
diff --git a/plugin/mapping/tag_types.json b/plugin/mappings/tag_types.json
similarity index 100%
rename from plugin/mapping/tag_types.json
rename to plugin/mappings/tag_types.json
diff --git a/plugin/mappings_generator.gradle b/plugin/mappings_generator.gradle
new file mode 100644
index 00000000..f04e1026
--- /dev/null
+++ b/plugin/mappings_generator.gradle
@@ -0,0 +1,454 @@
+import groovy.io.FileType
+import groovy.json.JsonOutput
+import groovy.json.JsonSlurper
+import groovy.transform.Field
+import java.security.MessageDigest
+
+enum MinecraftVersion {
+
+ MINECRAFT_1_7_2(4),
+ MINECRAFT_1_7_6(5),
+ MINECRAFT_1_8(47),
+ MINECRAFT_1_9(107),
+ MINECRAFT_1_9_1(108),
+ MINECRAFT_1_9_2(109),
+ MINECRAFT_1_9_4(110),
+ MINECRAFT_1_10(210),
+ MINECRAFT_1_11(315),
+ MINECRAFT_1_11_1(316),
+ MINECRAFT_1_12(335),
+ MINECRAFT_1_12_1(338),
+ MINECRAFT_1_12_2(340),
+ MINECRAFT_1_13(393),
+ MINECRAFT_1_13_1(401),
+ MINECRAFT_1_13_2(404),
+ MINECRAFT_1_14(477),
+ MINECRAFT_1_14_1(480),
+ MINECRAFT_1_14_2(485),
+ MINECRAFT_1_14_3(490),
+ MINECRAFT_1_14_4(498),
+ MINECRAFT_1_15(573),
+ MINECRAFT_1_15_1(575),
+ MINECRAFT_1_15_2(578),
+ MINECRAFT_1_16(735),
+ MINECRAFT_1_16_1(736),
+ MINECRAFT_1_16_2(751),
+ MINECRAFT_1_16_3(753),
+ MINECRAFT_1_16_4(754),
+ MINECRAFT_1_17(755),
+ MINECRAFT_1_17_1(756),
+ MINECRAFT_1_18(757),
+ MINECRAFT_1_18_2(758),
+ MINECRAFT_1_19(759),
+ MINECRAFT_1_19_1(760),
+ MINECRAFT_1_19_3(761),
+ MINECRAFT_1_19_4(762),
+ MINECRAFT_1_20(763),
+ MINECRAFT_1_20_2(764),
+ MINECRAFT_1_20_3(765),
+ MINECRAFT_1_20_5(766),
+ MINECRAFT_1_21(767),
+ MINECRAFT_1_21_2(768)
+
+ public static final List BLOCK_ENTITY_VERSIONS = List.of(
+ MINECRAFT_1_13,
+ MINECRAFT_1_14,
+ MINECRAFT_1_15,
+ MINECRAFT_1_17,
+ MINECRAFT_1_19,
+ MINECRAFT_1_19_3,
+ MINECRAFT_1_19_4,
+ MINECRAFT_1_20,
+ MINECRAFT_1_20_3,
+ MINECRAFT_1_20_5,
+ MINECRAFT_1_21_2
+ )
+
+ public static final List WORLD_VERSIONS = List.of(
+ MINECRAFT_1_13,
+ MINECRAFT_1_13_2,
+ MINECRAFT_1_14,
+ MINECRAFT_1_15,
+ MINECRAFT_1_16,
+ MINECRAFT_1_16_2,
+ MINECRAFT_1_17,
+ MINECRAFT_1_19,
+ MINECRAFT_1_19_3,
+ MINECRAFT_1_19_4,
+ MINECRAFT_1_20,
+ MINECRAFT_1_20_3,
+ MINECRAFT_1_20_5,
+ MINECRAFT_1_21_2
+ )
+
+ public static final MinecraftVersion MINIMUM_VERSION = MINECRAFT_1_7_2
+ public static final MinecraftVersion MAXIMUM_VERSION = values()[values().length - 1]
+
+ static MinecraftVersion fromVersionName(String name) {
+ return name.equalsIgnoreCase("legacy") ? MINIMUM_VERSION : valueOf("MINECRAFT_" + name.replace('.', '_'))
+ }
+
+ // Cache version name to reduce memory usage in general
+ final String versionName = this.toString().substring(10).replace('_', '.')
+ final int protocolVersion
+
+ MinecraftVersion(int protocolVersion) {
+ this.protocolVersion = protocolVersion
+ }
+
+ String getVersionName() {
+ return this.versionName
+ }
+}
+
+ext() {
+ File buildDirectory = this.getLayout().getBuildDirectory().get().getAsFile()
+ dataDirectory = new File(buildDirectory, "minecraft")
+ generatedDir = new File(buildDirectory, "generated/minecraft")
+ versionManifestFile = new File(dataDirectory, "manifest.json")
+}
+
+sourceSets.main.resources.srcDirs(generatedDir)
+
+tasks.register("downloadManifest") {
+ this.println("> Downloading version manifest...")
+ versionManifestFile.getParentFile().mkdirs()
+ if (checkIsCacheValid(versionManifestFile)) {
+ new URL(manifestUrl).openStream().transferTo(new FileOutputStream(versionManifestFile))
+ }
+}
+
+boolean checkIsCacheValid(File file) {
+ if (file.exists() && System.currentTimeMillis() - file.lastModified() < Long.parseLong(cacheValidMillis)) {
+ println("> Found cached " + file.getName())
+ return false
+ }
+
+ return true
+}
+
+@Field static final JsonSlurper SLURPER = new JsonSlurper()
+
+File downloadVersionManifest(String version) {
+ this.println("> Downloading ${version} manifest...")
+
+ File output = new File(dataDirectory, "${version}/manifest.json")
+ output.getParentFile().mkdirs()
+ for (Map versionInfo : (List