mirror of https://github.com/Minestom/Minestom.git
feat: functional components, but at what cost
This commit is contained in:
parent
f1f1246230
commit
c873d72f64
|
@ -34,6 +34,7 @@ import net.minestom.server.item.Material;
|
|||
import net.minestom.server.monitoring.BenchmarkManager;
|
||||
import net.minestom.server.monitoring.TickMonitor;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
import net.minestom.server.utils.Unit;
|
||||
import net.minestom.server.utils.time.TimeUnit;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
|
||||
|
@ -114,6 +115,14 @@ public class PlayerInit {
|
|||
.build();
|
||||
player.getInventory().addItemStack(bundle);
|
||||
|
||||
try {
|
||||
player.getInventory().addItemStack(ItemStack.builder(Material.STICK)
|
||||
.set(ItemComponent.CREATIVE_SLOT_LOCK, Unit.INSTANCE)
|
||||
.build());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
if (event.isFirstSpawn()) {
|
||||
Notification notification = new Notification(
|
||||
Component.text("Welcome!"),
|
||||
|
|
|
@ -36,12 +36,18 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
|||
// DESERIALIZATION
|
||||
|
||||
private @NotNull Component deserializeAnyComponent(@NotNull BinaryTag nbt) {
|
||||
if (nbt instanceof CompoundBinaryTag compound) {
|
||||
return deserializeComponent(compound);
|
||||
} else {
|
||||
//todo raw string + list
|
||||
throw new UnsupportedOperationException("Unknown NBT type: " + nbt.getClass().getName());
|
||||
}
|
||||
return switch (nbt) {
|
||||
case CompoundBinaryTag compound -> deserializeComponent(compound);
|
||||
case StringBinaryTag string -> Component.text(string.value());
|
||||
case ListBinaryTag list -> {
|
||||
var builder = Component.text();
|
||||
for (var element : list) {
|
||||
builder.append(deserializeAnyComponent(element));
|
||||
}
|
||||
yield builder.build();
|
||||
}
|
||||
default -> throw new UnsupportedOperationException("Unknown NBT type: " + nbt.getClass().getName());
|
||||
};
|
||||
}
|
||||
|
||||
private @NotNull Component deserializeComponent(@NotNull CompoundBinaryTag compound) {
|
||||
|
|
|
@ -744,6 +744,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
|||
|
||||
// Load the nearby chunks and queue them to be sent to them
|
||||
ChunkUtils.forChunksInRange(spawnPosition, settings.getEffectiveViewDistance(), chunkAdder);
|
||||
sendPendingChunks(); // Send available first chunk immediately to prevent falling through the floor
|
||||
}
|
||||
|
||||
synchronizePositionAfterTeleport(spawnPosition, 0); // So the player doesn't get stuck
|
||||
|
|
|
@ -4,6 +4,7 @@ import net.kyori.adventure.text.Component;
|
|||
import net.minestom.server.color.Color;
|
||||
import net.minestom.server.item.component.*;
|
||||
import net.minestom.server.network.NetworkBuffer;
|
||||
import net.minestom.server.utils.Unit;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -30,7 +31,7 @@ public final class ItemComponent {
|
|||
public static final ItemComponentType<Void> HIDE_ADDITIONAL_TOOLTIP = declare("hide_additional_tooltip", NetworkBuffer.NOTHING, BinaryTagSerializer.NOTHING);
|
||||
public static final ItemComponentType<Void> HIDE_TOOLTIP = declare("hide_tooltip", NetworkBuffer.NOTHING, BinaryTagSerializer.NOTHING);
|
||||
public static final ItemComponentType<Integer> REPAIR_COST = declare("repair_cost", NetworkBuffer.VAR_INT, BinaryTagSerializer.INT);
|
||||
public static final ItemComponentType<Void> CREATIVE_SLOT_LOCK = declare("creative_slot_lock", NetworkBuffer.NOTHING, null);
|
||||
public static final ItemComponentType<Unit> CREATIVE_SLOT_LOCK = declare("creative_slot_lock", NetworkBuffer.NOTHING_V2, null);
|
||||
public static final ItemComponentType<Boolean> ENCHANTMENT_GLINT_OVERRIDE = declare("enchantment_glint_override", NetworkBuffer.BOOLEAN, BinaryTagSerializer.BOOLEAN);
|
||||
public static final ItemComponentType<Void> INTANGIBLE_PROJECTILE = declare("intangible_projectile", null, BinaryTagSerializer.NOTHING);
|
||||
public static final ItemComponentType<Void> FOOD = declare("food", null, null); //todo
|
||||
|
|
|
@ -40,7 +40,7 @@ record ItemComponentPatch(@NotNull Int2ObjectMap<Object> patch) {
|
|||
//noinspection unchecked
|
||||
ItemComponentType<Object> type = (ItemComponentType<Object>) ItemComponentType.fromId(entry.getIntKey());
|
||||
assert type != null;
|
||||
type.write(entry.getValue());
|
||||
type.write(buffer, entry.getValue());
|
||||
}
|
||||
}
|
||||
for (Int2ObjectMap.Entry<Object> entry : value.patch.int2ObjectEntrySet()) {
|
||||
|
|
|
@ -18,15 +18,21 @@ record ItemStackImpl(Material material, int amount, ItemComponentPatch component
|
|||
static final NetworkBuffer.Type<ItemStack> NETWORK_TYPE = new NetworkBuffer.Type<>() {
|
||||
@Override
|
||||
public void write(@NotNull NetworkBuffer buffer, ItemStack value) {
|
||||
buffer.write(NetworkBuffer.VAR_INT, value.material().id());
|
||||
if (value.isAir()) {
|
||||
buffer.write(NetworkBuffer.VAR_INT, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.write(NetworkBuffer.VAR_INT, value.amount());
|
||||
buffer.write(NetworkBuffer.VAR_INT, value.material().id());
|
||||
buffer.write(ItemComponentPatch.NETWORK_TYPE, ((ItemStackImpl) value).components);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack read(@NotNull NetworkBuffer buffer) {
|
||||
Material material = Material.fromId(buffer.read(NetworkBuffer.VAR_INT));
|
||||
int amount = buffer.read(NetworkBuffer.VAR_INT);
|
||||
if (amount <= 0) return ItemStack.AIR;
|
||||
Material material = Material.fromId(buffer.read(NetworkBuffer.VAR_INT));
|
||||
ItemComponentPatch components = buffer.read(ItemComponentPatch.NETWORK_TYPE);
|
||||
return new ItemStackImpl(material, amount, components);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import net.minestom.server.entity.metadata.other.PaintingMeta;
|
|||
import net.minestom.server.network.packet.server.play.data.WorldPos;
|
||||
import net.minestom.server.particle.Particle;
|
||||
import net.minestom.server.utils.Direction;
|
||||
import net.minestom.server.utils.Unit;
|
||||
import net.minestom.server.utils.nbt.BinaryTagReader;
|
||||
import net.minestom.server.utils.nbt.BinaryTagWriter;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
|
@ -29,7 +30,8 @@ import java.util.function.Function;
|
|||
|
||||
@ApiStatus.Experimental
|
||||
public final class NetworkBuffer {
|
||||
public static final Type<Void> NOTHING = new NetworkBufferTypeImpl.NothingType();
|
||||
public static final Type<Void> NOTHING = new NetworkBufferTypeImpl.NothingType<>();
|
||||
public static final Type<Unit> NOTHING_V2 = new NetworkBufferTypeImpl.NothingType<>();
|
||||
public static final Type<Boolean> BOOLEAN = new NetworkBufferTypeImpl.BooleanType();
|
||||
public static final Type<Byte> BYTE = new NetworkBufferTypeImpl.ByteType();
|
||||
public static final Type<Short> SHORT = new NetworkBufferTypeImpl.ShortType();
|
||||
|
|
|
@ -25,13 +25,13 @@ interface NetworkBufferTypeImpl<T> extends NetworkBuffer.Type<T> {
|
|||
int SEGMENT_BITS = 0x7F;
|
||||
int CONTINUE_BIT = 0x80;
|
||||
|
||||
record NothingType() implements NetworkBufferTypeImpl<Void> {
|
||||
record NothingType<T>() implements NetworkBufferTypeImpl<T> {
|
||||
@Override
|
||||
public void write(@NotNull NetworkBuffer buffer, Void value) {
|
||||
public void write(@NotNull NetworkBuffer buffer, T value) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void read(@NotNull NetworkBuffer buffer) {
|
||||
public T read(@NotNull NetworkBuffer buffer) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import net.minestom.server.collision.Shape;
|
|||
import net.minestom.server.entity.EntitySpawnType;
|
||||
import net.minestom.server.entity.EquipmentSlot;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.item.ItemComponent;
|
||||
import net.minestom.server.item.ItemComponentMap;
|
||||
import net.minestom.server.item.ItemComponentType;
|
||||
import net.minestom.server.item.Material;
|
||||
|
@ -474,16 +473,18 @@ public final class Registry {
|
|||
|
||||
public static final class MaterialEntry implements Entry {
|
||||
private final NamespaceID namespace;
|
||||
private final Properties main;
|
||||
private final int id;
|
||||
private final String translationKey;
|
||||
private final Supplier<Block> blockSupplier;
|
||||
private final ItemComponentMap prototype;
|
||||
private ItemComponentMap prototype;
|
||||
|
||||
private final EquipmentSlot equipmentSlot;
|
||||
// private final EntityType entityType; //todo
|
||||
private final Properties custom;
|
||||
|
||||
private MaterialEntry(String namespace, Properties main, Properties custom) {
|
||||
this.main = main;
|
||||
this.custom = custom;
|
||||
this.namespace = NamespaceID.from(namespace);
|
||||
this.id = main.getInt("id");
|
||||
|
@ -492,34 +493,6 @@ public final class Registry {
|
|||
final String blockNamespace = main.getString("correspondingBlock", null);
|
||||
this.blockSupplier = blockNamespace != null ? () -> Block.fromNamespaceId(blockNamespace) : () -> null;
|
||||
}
|
||||
try {
|
||||
|
||||
try {
|
||||
Class.forName(ItemComponent.class.getName());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
ItemComponentMap.Builder builder = ItemComponentMap.builder();
|
||||
for (Map.Entry<String, Object> entry : main.section("components")) {
|
||||
try {
|
||||
//noinspection unchecked
|
||||
ItemComponentType<Object> component = (ItemComponentType<Object>) ItemComponentType.fromNamespaceId(entry.getKey());
|
||||
Check.notNull(component, "Unknown component: " + entry.getKey());
|
||||
|
||||
byte[] rawValue = Base64.getDecoder().decode((String) entry.getValue());
|
||||
BinaryTagReader reader = new BinaryTagReader(new DataInputStream(new ByteArrayInputStream(rawValue)));
|
||||
|
||||
//todo remove this try/catch, just so i dont need to impl all comps yet
|
||||
builder.set(component, component.read(reader.readNameless()));
|
||||
} catch (NullPointerException e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
this.prototype = builder.build();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("failed to parse material registry: " + namespace, e);
|
||||
}
|
||||
{
|
||||
final Properties armorProperties = main.section("armorProperties");
|
||||
if (armorProperties != null) {
|
||||
|
@ -561,6 +534,30 @@ public final class Registry {
|
|||
}
|
||||
|
||||
public @NotNull ItemComponentMap prototype() {
|
||||
if (prototype == null) {
|
||||
try {
|
||||
ItemComponentMap.Builder builder = ItemComponentMap.builder();
|
||||
for (Map.Entry<String, Object> entry : main.section("components")) {
|
||||
try {
|
||||
//noinspection unchecked
|
||||
ItemComponentType<Object> component = (ItemComponentType<Object>) ItemComponentType.fromNamespaceId(entry.getKey());
|
||||
Check.notNull(component, "Unknown component: " + entry.getKey());
|
||||
|
||||
byte[] rawValue = Base64.getDecoder().decode((String) entry.getValue());
|
||||
BinaryTagReader reader = new BinaryTagReader(new DataInputStream(new ByteArrayInputStream(rawValue)));
|
||||
|
||||
//todo remove this try/catch, just so i dont need to impl all comps yet
|
||||
builder.set(component, component.read(reader.readNameless()));
|
||||
} catch (NullPointerException e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
this.prototype = builder.build();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("failed to parse material registry: " + namespace, e);
|
||||
}
|
||||
}
|
||||
|
||||
return prototype;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package net.minestom.server.utils;
|
||||
|
||||
public final class Unit {
|
||||
//todo would rather just support void
|
||||
|
||||
public static final Unit INSTANCE = new Unit();
|
||||
}
|
Loading…
Reference in New Issue