From 4d45579d2bf57b417d5d3eca041c2131177183e4 Mon Sep 17 00:00:00 2001 From: Luck Date: Sat, 25 Jun 2022 22:48:55 +0100 Subject: Add providers for world (entity/chunk) statistics --- .../spark/fabric/FabricWorldInfoProvider.java | 145 +++++++++++++++++++++ .../fabric/mixin/ClientEntityManagerAccessor.java | 36 +++++ .../spark/fabric/mixin/ClientWorldAccessor.java | 36 +++++ .../fabric/mixin/ServerEntityManagerAccessor.java | 36 +++++ .../spark/fabric/mixin/ServerWorldAccessor.java | 36 +++++ .../fabric/plugin/FabricClientSparkPlugin.java | 12 ++ .../fabric/plugin/FabricServerSparkPlugin.java | 12 ++ spark-fabric/src/main/resources/fabric.mod.json | 3 + spark-fabric/src/main/resources/spark.mixins.json | 14 ++ 9 files changed, 330 insertions(+) create mode 100644 spark-fabric/src/main/java/me/lucko/spark/fabric/FabricWorldInfoProvider.java create mode 100644 spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ClientEntityManagerAccessor.java create mode 100644 spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ClientWorldAccessor.java create mode 100644 spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ServerEntityManagerAccessor.java create mode 100644 spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ServerWorldAccessor.java create mode 100644 spark-fabric/src/main/resources/spark.mixins.json (limited to 'spark-fabric/src') diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricWorldInfoProvider.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricWorldInfoProvider.java new file mode 100644 index 0000000..fddcf58 --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricWorldInfoProvider.java @@ -0,0 +1,145 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package me.lucko.spark.fabric; + +import it.unimi.dsi.fastutil.longs.LongIterator; +import it.unimi.dsi.fastutil.longs.LongSet; + +import me.lucko.spark.common.platform.world.AbstractChunkInfo; +import me.lucko.spark.common.platform.world.CountMap; +import me.lucko.spark.common.platform.world.WorldInfoProvider; +import me.lucko.spark.fabric.mixin.ClientEntityManagerAccessor; +import me.lucko.spark.fabric.mixin.ClientWorldAccessor; +import me.lucko.spark.fabric.mixin.ServerEntityManagerAccessor; +import me.lucko.spark.fabric.mixin.ServerWorldAccessor; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.world.ClientEntityManager; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerEntityManager; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.entity.EntityTrackingSection; +import net.minecraft.world.entity.SectionedEntityCache; +import net.minecraft.world.level.ServerWorldProperties; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.stream.Stream; + +public abstract class FabricWorldInfoProvider implements WorldInfoProvider { + + protected List getChunksFromCache(SectionedEntityCache cache) { + LongSet loadedChunks = cache.getChunkPositions(); + List list = new ArrayList<>(loadedChunks.size()); + + for (LongIterator iterator = loadedChunks.iterator(); iterator.hasNext(); ) { + long chunkPos = iterator.nextLong(); + Stream> sections = cache.getTrackingSections(chunkPos); + + list.add(new FabricChunkInfo(chunkPos, sections)); + } + + return list; + } + + public static final class Server extends FabricWorldInfoProvider { + private final MinecraftServer server; + + public Server(MinecraftServer server) { + this.server = server; + } + + @Override + public Result poll() { + Result data = new Result<>(); + + for (ServerWorld world : this.server.getWorlds()) { + ServerEntityManager entityManager = ((ServerWorldAccessor) world).getEntityManager(); + SectionedEntityCache cache = ((ServerEntityManagerAccessor) entityManager).getCache(); + + List list = getChunksFromCache(cache); + data.put(((ServerWorldProperties) world.getLevelProperties()).getLevelName(), list); + } + + return data; + } + } + + public static final class Client extends FabricWorldInfoProvider { + private final MinecraftClient client; + + public Client(MinecraftClient client) { + this.client = client; + } + + @Override + public Result poll() { + Result data = new Result<>(); + + ClientWorld world = this.client.world; + if (world == null) { + return null; + } + + ClientEntityManager entityManager = ((ClientWorldAccessor) world).getEntityManager(); + SectionedEntityCache cache = ((ClientEntityManagerAccessor) entityManager).getCache(); + + List list = getChunksFromCache(cache); + data.put(world.getDimensionKey().getValue().getPath(), list); + + return data; + } + } + + static final class FabricChunkInfo extends AbstractChunkInfo> { + private final CountMap> entityCounts; + + FabricChunkInfo(long chunkPos, Stream> entities) { + super(ChunkPos.getPackedX(chunkPos), ChunkPos.getPackedZ(chunkPos)); + + this.entityCounts = new CountMap.Simple<>(new HashMap<>()); + entities.forEach(section -> { + if (section.getStatus().shouldTrack()) { + section.stream().forEach(entity -> + this.entityCounts.increment(entity.getType()) + ); + } + }); + } + + @Override + public CountMap> getEntityCounts() { + return this.entityCounts; + } + + @Override + public String entityTypeName(EntityType type) { + return EntityType.getId(type).toString(); + } + } + +} + diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ClientEntityManagerAccessor.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ClientEntityManagerAccessor.java new file mode 100644 index 0000000..88c9521 --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ClientEntityManagerAccessor.java @@ -0,0 +1,36 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package me.lucko.spark.fabric.mixin; + +import net.minecraft.client.world.ClientEntityManager; +import net.minecraft.entity.Entity; +import net.minecraft.world.entity.SectionedEntityCache; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ClientEntityManager.class) +public interface ClientEntityManagerAccessor { + + @Accessor + SectionedEntityCache getCache(); + +} diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ClientWorldAccessor.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ClientWorldAccessor.java new file mode 100644 index 0000000..01562ef --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ClientWorldAccessor.java @@ -0,0 +1,36 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package me.lucko.spark.fabric.mixin; + +import net.minecraft.client.world.ClientEntityManager; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.Entity; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ClientWorld.class) +public interface ClientWorldAccessor { + + @Accessor + ClientEntityManager getEntityManager(); + +} diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ServerEntityManagerAccessor.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ServerEntityManagerAccessor.java new file mode 100644 index 0000000..160a12b --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ServerEntityManagerAccessor.java @@ -0,0 +1,36 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package me.lucko.spark.fabric.mixin; + +import net.minecraft.entity.Entity; +import net.minecraft.server.world.ServerEntityManager; +import net.minecraft.world.entity.SectionedEntityCache; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ServerEntityManager.class) +public interface ServerEntityManagerAccessor { + + @Accessor + SectionedEntityCache getCache(); + +} diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ServerWorldAccessor.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ServerWorldAccessor.java new file mode 100644 index 0000000..cf2e7e8 --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ServerWorldAccessor.java @@ -0,0 +1,36 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package me.lucko.spark.fabric.mixin; + +import net.minecraft.entity.Entity; +import net.minecraft.server.world.ServerEntityManager; +import net.minecraft.server.world.ServerWorld; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ServerWorld.class) +public interface ServerWorldAccessor { + + @Accessor + ServerEntityManager getEntityManager(); + +} diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricClientSparkPlugin.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricClientSparkPlugin.java index e94d697..1876658 100644 --- a/spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricClientSparkPlugin.java +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricClientSparkPlugin.java @@ -29,6 +29,7 @@ import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import me.lucko.spark.common.platform.PlatformInfo; +import me.lucko.spark.common.platform.world.WorldInfoProvider; import me.lucko.spark.common.tick.TickHook; import me.lucko.spark.common.tick.TickReporter; import me.lucko.spark.fabric.FabricCommandSender; @@ -36,6 +37,7 @@ import me.lucko.spark.fabric.FabricPlatformInfo; import me.lucko.spark.fabric.FabricSparkMod; import me.lucko.spark.fabric.FabricTickHook; import me.lucko.spark.fabric.FabricTickReporter; +import me.lucko.spark.fabric.FabricWorldInfoProvider; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; @@ -112,6 +114,11 @@ public class FabricClientSparkPlugin extends FabricSparkPlugin implements Comman return Stream.of(new FabricCommandSender(this.minecraft.player, this)); } + @Override + public void executeSync(Runnable task) { + this.minecraft.executeSync(task); + } + @Override public TickHook createTickHook() { return new FabricTickHook.Client(); @@ -122,6 +129,11 @@ public class FabricClientSparkPlugin extends FabricSparkPlugin implements Comman return new FabricTickReporter.Client(); } + @Override + public WorldInfoProvider createWorldInfoProvider() { + return new FabricWorldInfoProvider.Client(this.minecraft); + } + @Override public PlatformInfo getPlatformInfo() { return new FabricPlatformInfo(PlatformInfo.Type.CLIENT); diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricServerSparkPlugin.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricServerSparkPlugin.java index 3d1a0e7..2283a84 100644 --- a/spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricServerSparkPlugin.java +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricServerSparkPlugin.java @@ -31,6 +31,7 @@ import com.mojang.brigadier.suggestion.SuggestionsBuilder; import me.lucko.fabric.api.permissions.v0.Permissions; import me.lucko.spark.common.monitor.ping.PlayerPingProvider; import me.lucko.spark.common.platform.PlatformInfo; +import me.lucko.spark.common.platform.world.WorldInfoProvider; import me.lucko.spark.common.tick.TickHook; import me.lucko.spark.common.tick.TickReporter; import me.lucko.spark.fabric.FabricCommandSender; @@ -39,6 +40,7 @@ import me.lucko.spark.fabric.FabricPlayerPingProvider; import me.lucko.spark.fabric.FabricSparkMod; import me.lucko.spark.fabric.FabricTickHook; import me.lucko.spark.fabric.FabricTickReporter; +import me.lucko.spark.fabric.FabricWorldInfoProvider; import me.lucko.spark.fabric.placeholder.SparkFabricPlaceholderApi; import net.fabricmc.loader.api.FabricLoader; @@ -126,6 +128,11 @@ public class FabricServerSparkPlugin extends FabricSparkPlugin implements Comman ).map(sender -> new FabricCommandSender(sender, this)); } + @Override + public void executeSync(Runnable task) { + this.server.executeSync(task); + } + @Override public TickHook createTickHook() { return new FabricTickHook.Server(); @@ -141,6 +148,11 @@ public class FabricServerSparkPlugin extends FabricSparkPlugin implements Comman return new FabricPlayerPingProvider(this.server); } + @Override + public WorldInfoProvider createWorldInfoProvider() { + return new FabricWorldInfoProvider.Server(this.server); + } + @Override public PlatformInfo getPlatformInfo() { return new FabricPlatformInfo(PlatformInfo.Type.SERVER); diff --git a/spark-fabric/src/main/resources/fabric.mod.json b/spark-fabric/src/main/resources/fabric.mod.json index e2e600d..f1f0ad4 100644 --- a/spark-fabric/src/main/resources/fabric.mod.json +++ b/spark-fabric/src/main/resources/fabric.mod.json @@ -23,6 +23,9 @@ "me.lucko.spark.fabric.FabricSparkMod::initializeClient" ] }, + "mixins": [ + "spark.mixins.json" + ], "depends": { "fabricloader": ">=0.4.0", "fabric-api-base": "*", diff --git a/spark-fabric/src/main/resources/spark.mixins.json b/spark-fabric/src/main/resources/spark.mixins.json new file mode 100644 index 0000000..09587fe --- /dev/null +++ b/spark-fabric/src/main/resources/spark.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "package": "me.lucko.spark.fabric.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [], + "client": [ + "ClientEntityManagerAccessor", + "ClientWorldAccessor" + ], + "server": [ + "ServerEntityManagerAccessor", + "ServerWorldAccessor" + ] +} \ No newline at end of file -- cgit