1.0.1
This commit is contained in:
1 parent
e75b4f309a
commit
ff1e30907c
9 files changed
+157
-7
No files matched your search
+1
-1
@@ -29,7 +29,7 @@ mod_name=ServerWarashi
|
||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||
mod_license=MIT
|
||||
# The mod version. See https://semver.org/
|
||||
mod_version=1.0.0
|
||||
mod_version=1.0.1
|
||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
||||
# This should match the base package used for the mod sources.
|
||||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.moepus.serverwarashi;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ChunkLoadInfo {
|
||||
public int blockEntityCount;
|
||||
public int entityCount;
|
||||
|
||||
public static void dumpToCsv(@NotNull HashMap<Long, ChunkLoadInfo> chunkLoadInfoMap) {
|
||||
Path logDir = Paths.get("chunk_load");
|
||||
var timestamp = LocalDateTime.now().toString().replace(":", "-").replace(".", "-");
|
||||
var fileName = "chunk_load_info_" + timestamp + ".csv";
|
||||
Path csvPath = logDir.resolve(fileName);
|
||||
|
||||
try {
|
||||
Files.createDirectories(logDir);
|
||||
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(csvPath)) {
|
||||
writer.write("chunk_x,chunk_z,block_x,block_y,block_z,blockEntityCount,entityCount");
|
||||
writer.newLine();
|
||||
|
||||
for (Map.Entry<Long, ChunkLoadInfo> entry : chunkLoadInfoMap.entrySet()) {
|
||||
long chunkLong = entry.getKey();
|
||||
ChunkLoadInfo info = entry.getValue();
|
||||
|
||||
ChunkPos chunkPos = new ChunkPos(chunkLong);
|
||||
BlockPos blockPos = chunkPos.getWorldPosition();
|
||||
|
||||
writer.write(
|
||||
chunkPos.x + "," +
|
||||
chunkPos.z + "," +
|
||||
blockPos.getX() + "," +
|
||||
0 + "," +
|
||||
blockPos.getZ() + "," +
|
||||
info.blockEntityCount + "," +
|
||||
info.entityCount
|
||||
);
|
||||
writer.newLine();
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,9 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.*;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.Ticket;
|
||||
import net.minecraft.server.level.TicketType;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
@@ -46,6 +48,21 @@ public class TicketOwner<OwnerType> {
|
||||
this.name = "Unknown entity";
|
||||
}
|
||||
}
|
||||
} else if (ticket.getType() == TicketType.PLAYER) {
|
||||
owner = "player";
|
||||
final double[] mostNearDistance = {Double.MAX_VALUE};
|
||||
BlockPos ticketPos = ((ChunkPos) key).getWorldPosition();
|
||||
level.players().forEach(serverPlayer -> {
|
||||
double distance = serverPlayer.blockPosition().distSqr(ticketPos);
|
||||
if (distance < mostNearDistance[0]) {
|
||||
mostNearDistance[0] = distance;
|
||||
this.name = serverPlayer.getName().getString();
|
||||
pos = serverPlayer.blockPosition();
|
||||
}
|
||||
});
|
||||
} else if (ticket.getType() == TicketType.START) {
|
||||
owner = "world_start";
|
||||
this.pos = level.getSharedSpawnPos();
|
||||
} else {
|
||||
owner = key;
|
||||
if (owner instanceof BlockPos blockPos) {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.moepus.serverwarashi;
|
||||
|
||||
import com.moepus.serverwarashi.mixin.DistanceManagerAccessor;
|
||||
import com.moepus.serverwarashi.mixin.EntitySectionStorageAccessor;
|
||||
import com.moepus.serverwarashi.mixin.PersistentEntitySectionManagerAccessor;
|
||||
import com.moepus.serverwarashi.mixin.ServerLevelAcessor;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.BoolArgumentType;
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
@@ -14,15 +17,20 @@ import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.server.level.*;
|
||||
import net.minecraft.util.SortedArraySet;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
import net.minecraft.world.level.entity.EntitySection;
|
||||
import net.minecraft.world.level.entity.EntitySectionStorage;
|
||||
import net.minecraft.world.level.entity.PersistentEntitySectionManager;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class WarashiCommands {
|
||||
private static final java.util.function.Predicate<CommandSourceStack> ADMIN_PERMISSION =
|
||||
@@ -119,8 +127,8 @@ public class WarashiCommands {
|
||||
|
||||
private static Ticket<?> GetTicket(SortedArraySet<Ticket<?>> tickets, boolean currentWorking) {
|
||||
for (Ticket<?> ticket : tickets) {
|
||||
if (ticket.getType() == TicketType.PLAYER) continue;
|
||||
if (ticket.getType() == TicketType.START) continue;
|
||||
// if (ticket.getType() == TicketType.PLAYER) continue;
|
||||
// if (ticket.getType() == TicketType.START) continue;
|
||||
|
||||
int level;
|
||||
if (currentWorking) {
|
||||
@@ -129,7 +137,7 @@ public class WarashiCommands {
|
||||
IPauseableTicket pauseable = (IPauseableTicket) (Object) ticket;
|
||||
level = pauseable.serverWarashi$getLevel();
|
||||
}
|
||||
if (level > 32) continue;
|
||||
if (level > 33) continue;
|
||||
return ticket;
|
||||
}
|
||||
|
||||
@@ -157,25 +165,54 @@ public class WarashiCommands {
|
||||
ownerMap.computeIfAbsent(owner, k -> new HashSet<>()).add(chunkPos);
|
||||
}
|
||||
|
||||
PersistentEntitySectionManager<Entity> entityManager = ((ServerLevelAcessor) level).getEntityManager();
|
||||
PersistentEntitySectionManagerAccessor entityAccessor = (PersistentEntitySectionManagerAccessor) entityManager;
|
||||
EntitySectionStorage<?> sectionStorage = entityAccessor.getSectionStorage();
|
||||
EntitySectionStorageAccessor sectionAccessor = (EntitySectionStorageAccessor) sectionStorage;
|
||||
|
||||
HashMap<Long, ChunkLoadInfo> chunkLoadInfoMap = new HashMap<>();
|
||||
|
||||
for (var entry : ownerMap.entrySet()) {
|
||||
TicketOwner<?> owner = entry.getKey();
|
||||
Set<Long> chunks = entry.getValue();
|
||||
message.append(owner.asComponent());
|
||||
message.append(" loads " + chunks.size() + " chunks ");
|
||||
message.append(" C:" + chunks.size() + ",");
|
||||
|
||||
// Block Entity count
|
||||
int totalBlockEntities = 0;
|
||||
for (long chunkPos : chunks) {
|
||||
ChunkPos pos = new ChunkPos(chunkPos);
|
||||
ChunkAccess chunk = level.getChunk(pos.x, pos.z, ChunkStatus.FULL, false);
|
||||
if (chunk != null) {
|
||||
totalBlockEntities += chunk.getBlockEntitiesPos().size();
|
||||
int chunkBlockEntities = chunk.getBlockEntitiesPos().size();
|
||||
totalBlockEntities += chunkBlockEntities;
|
||||
chunkLoadInfoMap.computeIfAbsent(chunkPos, k -> new ChunkLoadInfo()).blockEntityCount = chunkBlockEntities;
|
||||
}
|
||||
}
|
||||
message.append("with " + totalBlockEntities + " block entities\n");
|
||||
message.append(" BE: " + totalBlockEntities + ",");
|
||||
|
||||
// Entity count
|
||||
int totalEntities = 0;
|
||||
for (long chunkPos : chunks) {
|
||||
ChunkPos pos = new ChunkPos(chunkPos);
|
||||
AtomicInteger chunkEntities = new AtomicInteger();
|
||||
sectionAccessor.invokeGetChunkSections(pos.x, pos.z).forEach(sectionIndex -> {
|
||||
EntitySection<?> section = sectionStorage.getSection(sectionIndex);
|
||||
if (section == null)
|
||||
return;
|
||||
chunkEntities.addAndGet(section.size());
|
||||
});
|
||||
totalEntities += chunkEntities.get();
|
||||
chunkLoadInfoMap.computeIfAbsent(chunkPos, k -> new ChunkLoadInfo()).entityCount = chunkEntities.get();
|
||||
}
|
||||
message.append(" E: " + totalEntities + ".\n");
|
||||
}
|
||||
if (ownerMap.isEmpty()) {
|
||||
message.append("No tickets found\n");
|
||||
}
|
||||
if (!chunkLoadInfoMap.isEmpty()) {
|
||||
ChunkLoadInfo.dumpToCsv(chunkLoadInfoMap);
|
||||
}
|
||||
return message;
|
||||
}, true)
|
||||
;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.moepus.serverwarashi.mixin;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.LongSortedSet;
|
||||
import net.minecraft.world.level.entity.EntitySectionStorage;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
@Mixin(value = EntitySectionStorage.class, remap = false)
|
||||
public interface EntitySectionStorageAccessor {
|
||||
@Invoker
|
||||
LongSortedSet invokeGetChunkSections(int x, int z);
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.moepus.serverwarashi.mixin;
|
||||
|
||||
import net.minecraft.world.level.entity.EntitySectionStorage;
|
||||
import net.minecraft.world.level.entity.PersistentEntitySectionManager;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(value = PersistentEntitySectionManager.class, remap = false)
|
||||
public interface PersistentEntitySectionManagerAccessor {
|
||||
@Accessor
|
||||
EntitySectionStorage<?> getSectionStorage();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.moepus.serverwarashi.mixin;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.entity.PersistentEntitySectionManager;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(value = ServerLevel.class, remap = false)
|
||||
public interface ServerLevelAcessor {
|
||||
@Accessor
|
||||
PersistentEntitySectionManager<Entity> getEntityManager();
|
||||
}
|
||||
@@ -5,6 +5,9 @@
|
||||
"compatibilityLevel": "JAVA_21",
|
||||
"mixins": [
|
||||
"DistanceManagerAccessor",
|
||||
"EntitySectionStorageAccessor",
|
||||
"PersistentEntitySectionManagerAccessor",
|
||||
"ServerLevelAcessor",
|
||||
"TicketMixin"
|
||||
],
|
||||
"client": [
|
||||
|
||||
Reference in new issue
Block a user