mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-08 01:17:47 +01:00
Merge branch 'master' into new-block-api
# Conflicts: # src/main/java/net/minestom/server/instance/Chunk.java # src/main/java/net/minestom/server/instance/Instance.java
This commit is contained in:
commit
4f4afbbe6d
@ -14,6 +14,7 @@ import net.minestom.server.adventure.AdventurePacketConvertor;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.message.ChatPosition;
|
||||
import net.minestom.server.message.Messenger;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.play.*;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -44,6 +45,14 @@ public interface PacketGroupingAudience extends ForwardingAudience {
|
||||
*/
|
||||
@NotNull Collection<Player> getPlayers();
|
||||
|
||||
/**
|
||||
* Broadcast a ServerPacket to all players of this audience
|
||||
* @param packet the packet to broadcast
|
||||
*/
|
||||
default void sendGroupedPacket(ServerPacket packet) {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
default void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) {
|
||||
Messenger.sendMessage(this.getPlayers(), message, ChatPosition.fromMessageType(type), source.uuid());
|
||||
@ -51,28 +60,28 @@ public interface PacketGroupingAudience extends ForwardingAudience {
|
||||
|
||||
@Override
|
||||
default void sendActionBar(@NotNull Component message) {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), new ActionBarPacket(message));
|
||||
sendGroupedPacket(new ActionBarPacket(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
default void sendPlayerListHeaderAndFooter(@NotNull Component header, @NotNull Component footer) {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), new PlayerListHeaderAndFooterPacket(header, footer));
|
||||
sendGroupedPacket(new PlayerListHeaderAndFooterPacket(header, footer));
|
||||
}
|
||||
|
||||
@Override
|
||||
default void showTitle(@NotNull Title title) {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), new SetTitleTextPacket(title.title()));
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), new SetTitleSubTitlePacket(title.subtitle()));
|
||||
sendGroupedPacket(new SetTitleTextPacket(title.title()));
|
||||
sendGroupedPacket(new SetTitleSubTitlePacket(title.subtitle()));
|
||||
}
|
||||
|
||||
@Override
|
||||
default void clearTitle() {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), new ClearTitlesPacket());
|
||||
sendGroupedPacket(new ClearTitlesPacket());
|
||||
}
|
||||
|
||||
@Override
|
||||
default void resetTitle() {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), new ClearTitlesPacket(true));
|
||||
sendGroupedPacket(new ClearTitlesPacket(true));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -87,13 +96,13 @@ public interface PacketGroupingAudience extends ForwardingAudience {
|
||||
|
||||
@Override
|
||||
default void playSound(@NotNull Sound sound, double x, double y, double z) {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), AdventurePacketConvertor.createSoundPacket(sound, x, y, z));
|
||||
sendGroupedPacket(AdventurePacketConvertor.createSoundPacket(sound, x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
default void playSound(@NotNull Sound sound, Sound.@NotNull Emitter emitter) {
|
||||
if (emitter != Sound.Emitter.self()) {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), AdventurePacketConvertor.createSoundPacket(sound, emitter));
|
||||
sendGroupedPacket(AdventurePacketConvertor.createSoundPacket(sound, emitter));
|
||||
} else {
|
||||
// if we're playing on self, we need to delegate to each audience member
|
||||
for (Audience audience : this.audiences()) {
|
||||
@ -104,7 +113,7 @@ public interface PacketGroupingAudience extends ForwardingAudience {
|
||||
|
||||
@Override
|
||||
default void stopSound(@NotNull SoundStop stop) {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), AdventurePacketConvertor.createSoundStopPacket(stop));
|
||||
sendGroupedPacket(AdventurePacketConvertor.createSoundStopPacket(stop));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
package net.minestom.server.attribute;
|
||||
|
||||
import io.netty.util.internal.ThreadLocalRandom;
|
||||
import net.minestom.server.utils.UniqueIdUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* Represent an attribute modifier.
|
||||
|
@ -19,9 +19,10 @@ public interface DataContainer {
|
||||
* meaning that this will be null if no data has been defined.
|
||||
*
|
||||
* @return the {@link Data} of this container, can be null
|
||||
* @deprecated use the tag API https://wiki.minestom.com/feature/tags
|
||||
*/
|
||||
@Nullable
|
||||
Data getData();
|
||||
@Deprecated
|
||||
@Nullable Data getData();
|
||||
|
||||
/**
|
||||
* Sets the {@link Data} of this container.
|
||||
@ -30,7 +31,8 @@ public interface DataContainer {
|
||||
* on your use-case.
|
||||
*
|
||||
* @param data the new {@link Data} of this container, null to remove it
|
||||
* @deprecated use the tag API https://wiki.minestom.com/feature/tags
|
||||
*/
|
||||
@Deprecated
|
||||
void setData(@Nullable Data data);
|
||||
|
||||
}
|
@ -8,8 +8,11 @@ import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.LivingEntity;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.sound.SoundEvent;
|
||||
import net.minestom.server.tag.Tag;
|
||||
import net.minestom.server.tag.TagHandler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
|
||||
/**
|
||||
* Represents a type of damage, required when calling {@link LivingEntity#damage(DamageType, float)}
|
||||
@ -19,7 +22,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
* Be aware that this class implements {@link DataContainer}
|
||||
* so you can add your own data to an already existing damage type without any wrapper.
|
||||
*/
|
||||
public class DamageType implements DataContainer {
|
||||
public class DamageType implements TagHandler, DataContainer {
|
||||
|
||||
public static final DamageType VOID = new DamageType("attack.outOfWorld");
|
||||
public static final DamageType GRAVITY = new DamageType("attack.fall");
|
||||
@ -30,6 +33,8 @@ public class DamageType implements DataContainer {
|
||||
}
|
||||
};
|
||||
private final String identifier;
|
||||
private final Object nbtLock = new Object();
|
||||
private final NBTCompound nbt = new NBTCompound();
|
||||
private Data data;
|
||||
|
||||
/**
|
||||
@ -159,4 +164,18 @@ public class DamageType implements DataContainer {
|
||||
public void setData(Data data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T getTag(@NotNull Tag<T> tag) {
|
||||
synchronized (nbtLock) {
|
||||
return tag.read(nbt);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void setTag(@NotNull Tag<T> tag, @Nullable T value) {
|
||||
synchronized (nbtLock) {
|
||||
tag.write(nbt, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,11 +16,15 @@ import net.minestom.server.network.packet.server.play.ChunkDataPacket;
|
||||
import net.minestom.server.network.packet.server.play.UpdateLightPacket;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
import net.minestom.server.utils.ArrayUtils;
|
||||
import net.minestom.server.tag.Tag;
|
||||
import net.minestom.server.tag.TagHandler;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.chunk.ChunkSupplier;
|
||||
import net.minestom.server.world.biomes.Biome;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -38,7 +42,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* You generally want to avoid storing references of this object as this could lead to a huge memory leak,
|
||||
* you should store the chunk coordinates instead.
|
||||
*/
|
||||
public abstract class Chunk implements BlockGetter, BlockSetter, Viewable, Tickable, DataContainer {
|
||||
public abstract class Chunk implements BlockGetter, BlockSetter, Viewable, Tickable, TagHandler, DataContainer {
|
||||
|
||||
public static final int CHUNK_SIZE_X = 16;
|
||||
public static final int CHUNK_SIZE_Z = 16;
|
||||
@ -63,6 +67,7 @@ public abstract class Chunk implements BlockGetter, BlockSetter, Viewable, Ticka
|
||||
protected PFColumnarSpace columnarSpace;
|
||||
|
||||
// Data
|
||||
private final NBTCompound nbt = new NBTCompound();
|
||||
protected Data data;
|
||||
|
||||
public Chunk(@NotNull Instance instance, @Nullable Biome[] biomes, int chunkX, int chunkZ, boolean shouldGenerate) {
|
||||
@ -367,6 +372,16 @@ public abstract class Chunk implements BlockGetter, BlockSetter, Viewable, Ticka
|
||||
return unmodifiableViewers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T getTag(@NotNull Tag<T> tag) {
|
||||
return tag.read(nbt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void setTag(@NotNull Tag<T> tag, @Nullable T value) {
|
||||
tag.write(nbt, value);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Data getData() {
|
||||
|
@ -26,6 +26,8 @@ import net.minestom.server.instance.block.*;
|
||||
import net.minestom.server.network.packet.server.play.BlockActionPacket;
|
||||
import net.minestom.server.network.packet.server.play.TimeUpdatePacket;
|
||||
import net.minestom.server.storage.StorageLocation;
|
||||
import net.minestom.server.tag.Tag;
|
||||
import net.minestom.server.tag.TagHandler;
|
||||
import net.minestom.server.thread.ThreadProvider;
|
||||
import net.minestom.server.utils.BlockPosition;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
@ -41,6 +43,7 @@ import net.minestom.server.world.DimensionType;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -58,7 +61,7 @@ import java.util.function.Consumer;
|
||||
* you need to be sure to signal the {@link UpdateManager} of the changes using
|
||||
* {@link UpdateManager#signalChunkLoad(Chunk)} and {@link UpdateManager#signalChunkUnload(Chunk)}.
|
||||
*/
|
||||
public abstract class Instance implements BlockGetter, BlockSetter, Tickable, EventHandler<InstanceEvent>, DataContainer, PacketGroupingAudience {
|
||||
public abstract class Instance implements BlockGetter, BlockSetter, Tickable,TagHandler, EventHandler<InstanceEvent>, DataContainer, PacketGroupingAudience {
|
||||
|
||||
protected static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager();
|
||||
protected static final UpdateManager UPDATE_MANAGER = MinecraftServer.getUpdateManager();
|
||||
@ -99,6 +102,8 @@ public abstract class Instance implements BlockGetter, BlockSetter, Tickable, Ev
|
||||
protected final Queue<Consumer<Instance>> nextTick = new ConcurrentLinkedQueue<>();
|
||||
|
||||
// instance custom data
|
||||
private final Object nbtLock = new Object();
|
||||
private final NBTCompound nbt = new NBTCompound();
|
||||
private Data data;
|
||||
|
||||
// the explosion supplier
|
||||
@ -867,6 +872,20 @@ public abstract class Instance implements BlockGetter, BlockSetter, Tickable, Ev
|
||||
this.worldBorder.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T getTag(@NotNull Tag<T> tag) {
|
||||
synchronized (nbtLock) {
|
||||
return tag.read(nbt);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void setTag(@NotNull Tag<T> tag, @Nullable T value) {
|
||||
synchronized (nbtLock) {
|
||||
tag.write(nbt, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an explosion at the given position with the given strength.
|
||||
* The algorithm used to compute damages is provided by {@link #getExplosionSupplier()}.
|
||||
|
@ -5,10 +5,13 @@ import net.minestom.server.data.DataContainer;
|
||||
import net.minestom.server.inventory.click.InventoryClickProcessor;
|
||||
import net.minestom.server.inventory.condition.InventoryCondition;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.tag.Tag;
|
||||
import net.minestom.server.tag.TagHandler;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -19,7 +22,7 @@ import java.util.function.UnaryOperator;
|
||||
/**
|
||||
* Represents an inventory where items can be modified/retrieved.
|
||||
*/
|
||||
public abstract class AbstractInventory implements InventoryClickHandler, DataContainer {
|
||||
public abstract class AbstractInventory implements InventoryClickHandler, TagHandler, DataContainer {
|
||||
|
||||
private final int size;
|
||||
protected final ItemStack[] itemStacks;
|
||||
@ -29,6 +32,8 @@ public abstract class AbstractInventory implements InventoryClickHandler, DataCo
|
||||
// the click processor which process all the clicks in the inventory
|
||||
protected final InventoryClickProcessor clickProcessor = new InventoryClickProcessor();
|
||||
|
||||
private final Object nbtLock = new Object();
|
||||
private final NBTCompound nbt = new NBTCompound();
|
||||
private Data data;
|
||||
|
||||
protected AbstractInventory(int size) {
|
||||
@ -210,6 +215,20 @@ public abstract class AbstractInventory implements InventoryClickHandler, DataCo
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T getTag(@NotNull Tag<T> tag) {
|
||||
synchronized (nbtLock) {
|
||||
return tag.read(nbt);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void setTag(@NotNull Tag<T> tag, @Nullable T value) {
|
||||
synchronized (nbtLock) {
|
||||
tag.write(nbt, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Data getData() {
|
||||
return data;
|
||||
|
@ -164,12 +164,7 @@ public class ItemMeta implements TagReadable, Writeable {
|
||||
@Deprecated
|
||||
@Contract(pure = true)
|
||||
public <T> T getOrDefault(@NotNull Tag<T> tag, @Nullable T defaultValue) {
|
||||
var key = tag.getKey();
|
||||
if (nbt.containsKey(key)) {
|
||||
return tag.read(toNBT());
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
return tag.defaultValue(defaultValue).read(toNBT());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13,7 +13,8 @@ public class ExplosionPacket implements ServerPacket {
|
||||
public byte[] records = new byte[0];
|
||||
public float playerMotionX, playerMotionY, playerMotionZ;
|
||||
|
||||
public ExplosionPacket() {}
|
||||
public ExplosionPacket() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull BinaryWriter writer) {
|
||||
@ -21,7 +22,7 @@ public class ExplosionPacket implements ServerPacket {
|
||||
writer.writeFloat(y);
|
||||
writer.writeFloat(z);
|
||||
writer.writeFloat(radius);
|
||||
writer.writeInt(records.length/3); // each record is 3 bytes long
|
||||
writer.writeVarInt(records.length / 3); // each record is 3 bytes long
|
||||
for (byte record : records)
|
||||
writer.writeByte(record);
|
||||
writer.writeFloat(playerMotionX);
|
||||
|
@ -6,7 +6,11 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTException;
|
||||
import org.jglrxavpok.hephaistos.nbt.SNBTParser;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
@ -21,7 +25,36 @@ import java.util.function.Supplier;
|
||||
@ApiStatus.NonExtendable
|
||||
public class Tag<T> {
|
||||
|
||||
private static final String EMPTY_KEY = "";
|
||||
/**
|
||||
* Handles the snbt of the tag holder.
|
||||
* <p>
|
||||
* Writing will override all tags. Proceed with caution.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public static final Tag<String> SNBT = new Tag<>(null, NBTCompound::toSNBT, (original, snbt) -> {
|
||||
try {
|
||||
final var updated = new SNBTParser(new StringReader(snbt)).parse();
|
||||
if (!(updated instanceof NBTCompound))
|
||||
throw new IllegalArgumentException("'" + snbt + "' is not a compound!");
|
||||
NBTCompound updatedCompound = (NBTCompound) updated;
|
||||
original.clear();
|
||||
updatedCompound.getKeys().forEach(s ->
|
||||
original.set(s, Objects.requireNonNull(updatedCompound.get(s))));
|
||||
} catch (NBTException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, null);
|
||||
|
||||
/**
|
||||
* Handles the complete tag holder compound.
|
||||
* <p>
|
||||
* Writing will override all tags. Proceed with caution.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public static final Tag<NBTCompound> NBT = new Tag<>(null, NBTCompound::deepClone, (original, updated) -> {
|
||||
original.clear();
|
||||
updated.getKeys().forEach(s -> original.set(s, Objects.requireNonNull(updated.get(s))));
|
||||
}, null);
|
||||
|
||||
private final String key;
|
||||
private final Function<NBTCompound, T> readFunction;
|
||||
@ -29,23 +62,31 @@ public class Tag<T> {
|
||||
|
||||
private final Supplier<T> defaultValue;
|
||||
|
||||
protected Tag(@NotNull String key,
|
||||
protected Tag(@Nullable String key,
|
||||
@NotNull Function<NBTCompound, T> readFunction,
|
||||
@NotNull BiConsumer<NBTCompound, T> writeConsumer,
|
||||
@Nullable BiConsumer<NBTCompound, T> writeConsumer,
|
||||
@Nullable Supplier<T> defaultValue) {
|
||||
this.key = key;
|
||||
this.readFunction = readFunction;
|
||||
this.writeConsumer = writeConsumer;
|
||||
this.writeConsumer = Objects.requireNonNullElse(writeConsumer, (compound, t) -> {
|
||||
});
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
protected Tag(@NotNull String key,
|
||||
protected Tag(@Nullable String key,
|
||||
@NotNull Function<NBTCompound, T> readFunction,
|
||||
@NotNull BiConsumer<NBTCompound, T> writeConsumer) {
|
||||
@Nullable BiConsumer<NBTCompound, T> writeConsumer) {
|
||||
this(key, readFunction, writeConsumer, null);
|
||||
}
|
||||
|
||||
public @NotNull String getKey() {
|
||||
/**
|
||||
* Returns the key used to navigate inside the holder nbt.
|
||||
* <p>
|
||||
* Can be null if unused (e.g. {@link #View(TagSerializer)}, {@link #SNBT} and {@link #NBT}).
|
||||
*
|
||||
* @return the tag key
|
||||
*/
|
||||
public @Nullable String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@ -96,7 +137,7 @@ public class Tag<T> {
|
||||
}
|
||||
|
||||
public void write(@NotNull NBTCompound nbtCompound, @Nullable T value) {
|
||||
if (value != null || key.equals(EMPTY_KEY)) {
|
||||
if (key == null || value != null) {
|
||||
this.writeConsumer.accept(nbtCompound, value);
|
||||
} else {
|
||||
nbtCompound.removeTag(key);
|
||||
@ -208,7 +249,7 @@ public class Tag<T> {
|
||||
}
|
||||
|
||||
public static <T> @NotNull Tag<T> View(@NotNull TagSerializer<T> serializer) {
|
||||
return new Tag<>(EMPTY_KEY,
|
||||
return new Tag<>(null,
|
||||
nbtCompound -> serializer.read(TagReadable.fromCompound(nbtCompound)),
|
||||
(nbtCompound, value) -> serializer.write(TagWritable.fromCompound(nbtCompound), value));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user