From 83ed16afb71087f08d1a7eb5bd141759e471f1b2 Mon Sep 17 00:00:00 2001 From: PrimordialMoros Date: Mon, 12 Feb 2024 22:43:30 +0200 Subject: [PATCH] Replace fabric metadata impl with data attachment api --- .../moros/bending/fabric/FabricBending.java | 6 -- .../bending/fabric/listener/UserListener.java | 10 +- .../fabric/listener/WorldListener.java | 2 - .../fabric/platform/FabricDataHolder.java | 50 +++++++++ .../fabric/platform/FabricMetadata.java | 101 ------------------ .../fabric/platform/FabricPlatform.java | 14 +++ .../fabric/platform/PlatformAdapter.java | 17 +++ .../fabric/platform/entity/FabricEntity.java | 15 ++- .../fabric/platform/world/FabricWorld.java | 4 +- gradle/libs.versions.toml | 2 +- 10 files changed, 99 insertions(+), 122 deletions(-) create mode 100644 fabric/src/main/java/me/moros/bending/fabric/platform/FabricDataHolder.java delete mode 100644 fabric/src/main/java/me/moros/bending/fabric/platform/FabricMetadata.java diff --git a/fabric/src/main/java/me/moros/bending/fabric/FabricBending.java b/fabric/src/main/java/me/moros/bending/fabric/FabricBending.java index 0907f3ca..f1a03fe0 100644 --- a/fabric/src/main/java/me/moros/bending/fabric/FabricBending.java +++ b/fabric/src/main/java/me/moros/bending/fabric/FabricBending.java @@ -22,7 +22,6 @@ import java.nio.file.Path; import java.util.Collection; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; @@ -32,7 +31,6 @@ import me.moros.bending.api.addon.Addon; import me.moros.bending.api.game.Game; import me.moros.bending.api.platform.Platform; -import me.moros.bending.api.util.Tasker; import me.moros.bending.api.util.functional.Suppliers; import me.moros.bending.common.AbstractBending; import me.moros.bending.common.command.Commander; @@ -49,7 +47,6 @@ import me.moros.bending.fabric.listener.WorldListener; import me.moros.bending.fabric.platform.CommandSender; import me.moros.bending.fabric.platform.CommandSender.PlayerCommandSender; -import me.moros.bending.fabric.platform.FabricMetadata; import me.moros.bending.fabric.platform.FabricPermissionInitializer; import me.moros.bending.fabric.platform.FabricPlatform; import me.moros.tasker.fabric.FabricExecutor; @@ -72,8 +69,6 @@ final class FabricBending extends AbstractBending { injectTasker(new FabricExecutor()); - Tasker.async().repeat(FabricMetadata.INSTANCE::removeEmpty, 5, TimeUnit.MINUTES); - listeners = List.of( new BlockListener(this::game), new UserListener(this::game), @@ -113,7 +108,6 @@ private void onEnable(MinecraftServer server) { private void onDisable(boolean fullShutdown) { if (phase == LoadPhase.LOADED) { - FabricMetadata.INSTANCE.cleanup(); if (fullShutdown) { disable(); } else { diff --git a/fabric/src/main/java/me/moros/bending/fabric/listener/UserListener.java b/fabric/src/main/java/me/moros/bending/fabric/listener/UserListener.java index f3646c04..9f257d87 100644 --- a/fabric/src/main/java/me/moros/bending/fabric/listener/UserListener.java +++ b/fabric/src/main/java/me/moros/bending/fabric/listener/UserListener.java @@ -44,7 +44,6 @@ import me.moros.bending.fabric.event.ServerInventoryEvents; import me.moros.bending.fabric.event.ServerItemEvents; import me.moros.bending.fabric.event.ServerPlayerEvents; -import me.moros.bending.fabric.platform.FabricMetadata; import me.moros.bending.fabric.platform.PlatformAdapter; import me.moros.bending.fabric.platform.entity.FabricEntity; import me.moros.bending.fabric.platform.item.ItemUtil; @@ -121,9 +120,8 @@ private void onPlayerRespawn(Entity originalEntity, Entity newEntity, boolean al private boolean onArrowHit(Projectile projectile, HitResult hitResult) { if (!disabledWorld(projectile) && projectile instanceof Arrow) { - var data = FabricMetadata.INSTANCE.metadata(projectile).get(MetalCable.CABLE_KEY); - if (data.isPresent()) { - MetalCable cable = data.get(); + MetalCable cable = projectile.getAttached(PlatformAdapter.dataType(MetalCable.CABLE_KEY)); + if (cable != null) { if (hitResult instanceof BlockHitResult blockHit) { var pos = blockHit.getBlockPos(); var world = PlatformAdapter.fromFabricWorld((ServerLevel) projectile.level()); @@ -286,7 +284,7 @@ private boolean onItemMerge(ItemEntity first, ItemEntity second) { } private boolean isNotGlove(Entity entity) { - return !FabricMetadata.INSTANCE.has(entity, EarthGlove.GLOVE_KEY); + return !entity.hasAttached(PlatformAdapter.dataType(EarthGlove.GLOVE_KEY)); } private boolean onInventoryClick(ServerPlayer player, ItemStack stack) { @@ -352,7 +350,7 @@ private double onEntityDamage(LivingEntity entity, DamageSource source, double d Vector3d origin = null; var sourceEntity = source.getEntity(); if (sourceEntity != null) { - if (sourceEntity instanceof Arrow && FabricMetadata.INSTANCE.has(sourceEntity, MetalCable.CABLE_KEY)) { + if (sourceEntity instanceof Arrow && sourceEntity.hasAttached(PlatformAdapter.dataType(MetalCable.CABLE_KEY))) { return 0; } else if (ActionLimiter.isLimited(sourceEntity.getUUID(), ActionType.DAMAGE)) { return 0; diff --git a/fabric/src/main/java/me/moros/bending/fabric/listener/WorldListener.java b/fabric/src/main/java/me/moros/bending/fabric/listener/WorldListener.java index bd3b92f3..51755ea6 100644 --- a/fabric/src/main/java/me/moros/bending/fabric/listener/WorldListener.java +++ b/fabric/src/main/java/me/moros/bending/fabric/listener/WorldListener.java @@ -26,7 +26,6 @@ import me.moros.bending.api.registry.Registries; import me.moros.bending.api.user.User; import me.moros.bending.common.util.Initializer; -import me.moros.bending.fabric.platform.FabricMetadata; import me.moros.bending.fabric.platform.entity.FabricEntity; import net.fabricmc.fabric.api.entity.event.v1.ServerEntityWorldChangeEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; @@ -48,7 +47,6 @@ public void init() { private void onWorldUnload(MinecraftServer server, ServerLevel world) { var key = world.dimension().location(); game().worldManager().onWorldUnload(key); - FabricMetadata.INSTANCE.cleanup(key); } private void onChangeWorld(Entity originalEntity, Entity newEntity, ServerLevel origin, ServerLevel destination) { diff --git a/fabric/src/main/java/me/moros/bending/fabric/platform/FabricDataHolder.java b/fabric/src/main/java/me/moros/bending/fabric/platform/FabricDataHolder.java new file mode 100644 index 00000000..f026641e --- /dev/null +++ b/fabric/src/main/java/me/moros/bending/fabric/platform/FabricDataHolder.java @@ -0,0 +1,50 @@ +/* + * Copyright 2020-2024 Moros + * + * This file is part of Bending. + * + * Bending is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Bending is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bending. If not, see . + */ + +package me.moros.bending.fabric.platform; + +import java.util.Optional; + +import me.moros.bending.api.util.data.DataHolder; +import me.moros.bending.api.util.data.DataKey; +import net.fabricmc.fabric.api.attachment.v1.AttachmentTarget; + +public record FabricDataHolder(AttachmentTarget handle) implements DataHolder { + @Override + public Optional get(DataKey key) { + var type = PlatformAdapter.dataTypeIfExists(key); + if (type == null) { + return Optional.empty(); + } + return Optional.ofNullable(handle().getAttached(type)); + } + + @Override + public void add(DataKey key, T value) { + handle().setAttached(PlatformAdapter.dataType(key), value); + } + + @Override + public void remove(DataKey key) { + var type = PlatformAdapter.dataTypeIfExists(key); + if (type != null) { + handle().removeAttached(type); + } + } +} diff --git a/fabric/src/main/java/me/moros/bending/fabric/platform/FabricMetadata.java b/fabric/src/main/java/me/moros/bending/fabric/platform/FabricMetadata.java deleted file mode 100644 index 8828cc22..00000000 --- a/fabric/src/main/java/me/moros/bending/fabric/platform/FabricMetadata.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2020-2024 Moros - * - * This file is part of Bending. - * - * Bending is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Bending is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bending. If not, see . - */ - -package me.moros.bending.fabric.platform; - -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; - -import me.moros.bending.api.util.data.DataContainer; -import me.moros.bending.api.util.data.DataHolder; -import me.moros.bending.api.util.data.DataKey; -import me.moros.math.Position; -import me.moros.math.Vector3i; -import net.kyori.adventure.key.Key; -import net.minecraft.world.entity.Entity; - -public enum FabricMetadata { - INSTANCE; - - private final Map> worlds = new ConcurrentHashMap<>(); - - private Pair worldData(Key key) { - return worlds.computeIfAbsent(key, u -> new Pair<>(new ConcurrentHashMap<>(), new ConcurrentHashMap<>())); - } - - private DataHolder blockData(Map dataMap, int x, int y, int z) { - return dataMap.computeIfAbsent(Vector3i.of(x, y, z), p -> DataContainer.simple()); - } - - private DataHolder entityData(Map dataMap, UUID uuid) { - return dataMap.computeIfAbsent(uuid, id -> DataContainer.simple()); - } - - public DataHolder metadata(Key world, int x, int y, int z) { - return blockData(worldData(world).map1(), x, y, z); - } - - public DataHolder metadata(Key world, UUID uuid) { - return entityData(worldData(world).map2(), uuid); - } - - public DataHolder metadata(Entity entity) { - return metadata(entity.level().dimension().location(), entity.getUUID()); - } - - public boolean has(Key world, int x, int y, int z, DataKey key) { - return has(world, key, p -> p.map1().get(Vector3i.of(x, y, z))); - } - - public boolean has(Entity entity, DataKey key) { - return has(entity.level().dimension().location(), key, p -> p.map2().get(entity.getUUID())); - } - - private boolean has(Key worldKey, DataKey key, Function, DataHolder> mapper) { - var pair = worlds.get(worldKey); - if (pair == null) { - return false; - } - var dataHolder = mapper.apply(pair); - return dataHolder != null && dataHolder.has(key); - } - - // Cleanup empty data containers to avoid memory leaks - public void removeEmpty() { - worlds.entrySet().removeIf(e -> e.getValue().cleanup()); - } - - public void cleanup() { - worlds.clear(); - } - - public void cleanup(Key world) { - worlds.remove(world); - } - - private record Pair(Map map1, Map map2) { - private boolean cleanup() { - map1().entrySet().removeIf(e -> e.getValue().isEmpty()); - map2().entrySet().removeIf(e -> e.getValue().isEmpty()); - return map1.isEmpty() && map2.isEmpty(); - } - } -} diff --git a/fabric/src/main/java/me/moros/bending/fabric/platform/FabricPlatform.java b/fabric/src/main/java/me/moros/bending/fabric/platform/FabricPlatform.java index 39a71feb..f69026a5 100644 --- a/fabric/src/main/java/me/moros/bending/fabric/platform/FabricPlatform.java +++ b/fabric/src/main/java/me/moros/bending/fabric/platform/FabricPlatform.java @@ -21,6 +21,7 @@ import java.util.Optional; +import com.mojang.serialization.Codec; import me.moros.bending.api.ability.element.ElementHandler; import me.moros.bending.api.adapter.NativeAdapter; import me.moros.bending.api.gui.Board; @@ -34,13 +35,26 @@ import me.moros.bending.api.platform.item.ItemBuilder; import me.moros.bending.api.platform.item.ItemSnapshot; import me.moros.bending.api.user.User; +import me.moros.bending.api.util.metadata.Metadata; import me.moros.bending.fabric.adapter.NativeAdapterImpl; import me.moros.bending.fabric.gui.BoardImpl; import me.moros.bending.fabric.gui.ElementMenu; import me.moros.bending.fabric.platform.item.FabricItemBuilder; +import net.fabricmc.fabric.api.attachment.v1.AttachmentRegistry; +import net.fabricmc.fabric.api.attachment.v1.AttachmentType; import net.minecraft.server.MinecraftServer; public class FabricPlatform implements Platform, PlatformFactory { + public static final AttachmentType NPC = AttachmentRegistry.createPersistent( + PlatformAdapter.rsl(Metadata.NPC), Codec.BOOL + ); + public static final AttachmentType ARMOR = AttachmentRegistry.createPersistent( + PlatformAdapter.rsl(Metadata.ARMOR_KEY), Codec.BOOL + ); + public static final AttachmentType METAL_KEY = AttachmentRegistry.createPersistent( + PlatformAdapter.rsl(Metadata.ARMOR_KEY), Codec.STRING + ); + private final MinecraftServer server; private final NativeAdapter adapter; diff --git a/fabric/src/main/java/me/moros/bending/fabric/platform/PlatformAdapter.java b/fabric/src/main/java/me/moros/bending/fabric/platform/PlatformAdapter.java index 46245915..b925d180 100644 --- a/fabric/src/main/java/me/moros/bending/fabric/platform/PlatformAdapter.java +++ b/fabric/src/main/java/me/moros/bending/fabric/platform/PlatformAdapter.java @@ -34,12 +34,16 @@ import me.moros.bending.api.platform.potion.PotionEffect; import me.moros.bending.api.platform.potion.PotionEffectTag; import me.moros.bending.api.platform.world.World; +import me.moros.bending.api.util.data.DataKey; import me.moros.bending.fabric.platform.block.FabricBlockState; import me.moros.bending.fabric.platform.entity.FabricEntity; import me.moros.bending.fabric.platform.entity.FabricLivingEntity; import me.moros.bending.fabric.platform.entity.FabricPlayer; import me.moros.bending.fabric.platform.item.FabricItem; import me.moros.bending.fabric.platform.world.FabricWorld; +import net.fabricmc.fabric.api.attachment.v1.AttachmentRegistry; +import net.fabricmc.fabric.api.attachment.v1.AttachmentType; +import net.fabricmc.fabric.impl.attachment.AttachmentRegistryImpl; import net.kyori.adventure.key.Key; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; @@ -53,6 +57,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; +import org.checkerframework.checker.nullness.qual.Nullable; public final class PlatformAdapter { private PlatformAdapter() { @@ -108,6 +113,18 @@ public static ResourceLocation rsl(Key key) { return (ResourceLocation) key.key(); } + @SuppressWarnings("unchecked") + public static AttachmentType dataType(DataKey key) { + var id = rsl(key); + var type = AttachmentRegistryImpl.get(id); + return type == null ? AttachmentRegistry.create(id) : (AttachmentType) type; + } + + @SuppressWarnings("unchecked") + public static @Nullable AttachmentType dataTypeIfExists(DataKey key) { + return (AttachmentType) AttachmentRegistryImpl.get(rsl(key)); + } + public static World fromFabricWorld(ServerLevel world) { return new FabricWorld(world); } diff --git a/fabric/src/main/java/me/moros/bending/fabric/platform/entity/FabricEntity.java b/fabric/src/main/java/me/moros/bending/fabric/platform/entity/FabricEntity.java index fbc56d1a..3548f233 100644 --- a/fabric/src/main/java/me/moros/bending/fabric/platform/entity/FabricEntity.java +++ b/fabric/src/main/java/me/moros/bending/fabric/platform/entity/FabricEntity.java @@ -32,7 +32,7 @@ import me.moros.bending.api.util.data.DataKey; import me.moros.bending.api.util.functional.Suppliers; import me.moros.bending.fabric.mixin.accessor.EntityAccess; -import me.moros.bending.fabric.platform.FabricMetadata; +import me.moros.bending.fabric.platform.PlatformAdapter; import me.moros.bending.fabric.platform.world.FabricWorld; import me.moros.math.FastMath; import me.moros.math.Position; @@ -239,17 +239,24 @@ public boolean teleport(Position position) { @Override public Optional get(DataKey key) { - return FabricMetadata.INSTANCE.metadata(handle()).get(key); + var type = PlatformAdapter.dataTypeIfExists(key); + if (type == null) { + return Optional.empty(); + } + return Optional.ofNullable(handle().getAttached(type)); } @Override public void add(DataKey key, T value) { - FabricMetadata.INSTANCE.metadata(handle()).add(key, value); + handle().setAttached(PlatformAdapter.dataType(key), value); } @Override public void remove(DataKey key) { - FabricMetadata.INSTANCE.metadata(handle()).remove(key); + var type = PlatformAdapter.dataTypeIfExists(key); + if (type != null) { + handle().removeAttached(type); + } } @Override diff --git a/fabric/src/main/java/me/moros/bending/fabric/platform/world/FabricWorld.java b/fabric/src/main/java/me/moros/bending/fabric/platform/world/FabricWorld.java index 660e9f2d..c9bf71df 100644 --- a/fabric/src/main/java/me/moros/bending/fabric/platform/world/FabricWorld.java +++ b/fabric/src/main/java/me/moros/bending/fabric/platform/world/FabricWorld.java @@ -38,7 +38,7 @@ import me.moros.bending.api.util.data.DataHolder; import me.moros.bending.fabric.mixin.accessor.ChunkMapAccess; import me.moros.bending.fabric.mixin.accessor.FallingBlockEntityAccess; -import me.moros.bending.fabric.platform.FabricMetadata; +import me.moros.bending.fabric.platform.FabricDataHolder; import me.moros.bending.fabric.platform.PlatformAdapter; import me.moros.bending.fabric.platform.particle.ParticleMapper; import me.moros.math.Position; @@ -90,7 +90,7 @@ public AABB blockBounds(int x, int y, int z) { @Override public DataHolder blockMetadata(int x, int y, int z) { - return FabricMetadata.INSTANCE.metadata(key(), x, y, z); + return new FabricDataHolder(handle()); } private @Nullable BlockEntity blockEntity(int x, int y, int z) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a5f108b7..b25c5c13 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,7 @@ sponge-api = "11.0.0-SNAPSHOT" sponge-common = "1.20.1-11.0.0-SNAPSHOT" minecraft = "1.20.4" fabric-loom = "1.5.7" -fabric-api = "0.95.4+1.20.4" +fabric-api = "0.96.1+1.20.4" fabric-loader = "0.15.6" shadow = "8.1.1" flyway = "10.7.1"