Add region info command
This commit is contained in:
@@ -48,8 +48,8 @@ public final class LivingWorldCommandRoot {
|
||||
context.getSource(), regionManager, moduleRegistry, simulationManager)))
|
||||
.then(Commands.literal("region")
|
||||
.then(Commands.literal("info")
|
||||
.executes(context -> placeholder(
|
||||
context.getSource(), "Region inspection is not connected yet."))))
|
||||
.executes(context -> RegionInfoCommand.execute(
|
||||
context.getSource(), regionManager))))
|
||||
.then(Commands.literal("modules")
|
||||
.then(Commands.literal("list")
|
||||
.executes(context -> listModules(
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.livingworld.commands;
|
||||
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import com.livingworld.regions.Region;
|
||||
import com.livingworld.regions.RegionManager;
|
||||
|
||||
/**
|
||||
* Prints the Living World region state at the command source position.
|
||||
*/
|
||||
public final class RegionInfoCommand {
|
||||
|
||||
private RegionInfoCommand() {
|
||||
}
|
||||
|
||||
public static int execute(
|
||||
CommandSourceStack source,
|
||||
RegionManager regionManager) {
|
||||
if (source == null) {
|
||||
throw new IllegalArgumentException("source must not be null");
|
||||
}
|
||||
if (regionManager == null) {
|
||||
throw new IllegalArgumentException("regionManager must not be null");
|
||||
}
|
||||
|
||||
Vec3 position = source.getPosition();
|
||||
String dimensionId = source.getLevel().dimension().location().toString();
|
||||
Region region = regionManager.getOrCreateRegionAtBlock(
|
||||
dimensionId,
|
||||
floorToBlock(position.x),
|
||||
floorToBlock(position.z));
|
||||
|
||||
for (String line : RegionInfoFormatter.format(region)) {
|
||||
source.sendSuccess(() -> Component.literal(line), false);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int floorToBlock(double coordinate) {
|
||||
return (int) Math.floor(coordinate);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.livingworld.commands;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.livingworld.regions.Region;
|
||||
import com.livingworld.regions.RegionFlags;
|
||||
import com.livingworld.regions.RegionMetrics;
|
||||
|
||||
/**
|
||||
* Formats region diagnostics without depending on Minecraft classes.
|
||||
*/
|
||||
public final class RegionInfoFormatter {
|
||||
|
||||
private RegionInfoFormatter() {
|
||||
}
|
||||
|
||||
public static List<String> format(Region region) {
|
||||
if (region == null) {
|
||||
throw new IllegalArgumentException("region must not be null");
|
||||
}
|
||||
|
||||
RegionMetrics metrics = region.getMetrics();
|
||||
RegionFlags flags = region.getFlags();
|
||||
Set<String> moduleIds = new TreeSet<>(region.getModuleData().moduleIds());
|
||||
|
||||
return List.of(
|
||||
"Region: " + region.getCoordinate().stableId(),
|
||||
"Lifecycle: " + region.getLifecycleState() + ", dirty=" + region.isDirty(),
|
||||
"Metrics: ecosystemHealth=" + metrics.getEcosystemHealth()
|
||||
+ ", pollution=" + metrics.getPollutionScore()
|
||||
+ ", soilQuality=" + metrics.getSoilQuality()
|
||||
+ ", waterQuality=" + metrics.getWaterQuality()
|
||||
+ ", vegetationPressure=" + metrics.getVegetationPressure()
|
||||
+ ", resourceDepletion=" + metrics.getResourceDepletion()
|
||||
+ ", recoveryPressure=" + metrics.getRecoveryPressure(),
|
||||
"Flags: playerActivity=" + flags.isHasPlayerActivity()
|
||||
+ ", highPollution=" + flags.isHasHighPollution()
|
||||
+ ", lowSoilQuality=" + flags.isHasLowSoilQuality()
|
||||
+ ", activeEcosystemEvent=" + flags.isHasActiveEcosystemEvent()
|
||||
+ ", forceLoaded=" + flags.isForceLoadedBySimulation()
|
||||
+ ", corrupted=" + flags.isCorrupted(),
|
||||
"Module data: " + (moduleIds.isEmpty() ? "none" : String.join(", ", moduleIds)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.livingworld.commands;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.livingworld.regions.Region;
|
||||
import com.livingworld.regions.RegionCoordinate;
|
||||
import com.livingworld.regions.RegionFactory;
|
||||
|
||||
class RegionInfoFormatterTest {
|
||||
|
||||
@Test
|
||||
void includesIdentityLifecycleMetricsFlagsAndSortedModuleIds() {
|
||||
Region region = new RegionFactory().createNewRegion(
|
||||
new RegionCoordinate("minecraft:overworld", -1, 2), 0);
|
||||
region.getMetrics().setPollutionScore(75);
|
||||
region.getFlags().setHasHighPollution(true);
|
||||
region.getModuleData().put("water", "data");
|
||||
region.getModuleData().put("soil", "data");
|
||||
|
||||
List<String> lines = RegionInfoFormatter.format(region);
|
||||
|
||||
assertEquals(5, lines.size());
|
||||
assertTrue(lines.get(0).contains("minecraft:overworld:-1:2"));
|
||||
assertTrue(lines.get(1).contains("ACTIVE"));
|
||||
assertTrue(lines.get(2).contains("pollution=75.0"));
|
||||
assertTrue(lines.get(3).contains("highPollution=true"));
|
||||
assertEquals("Module data: soil, water", lines.get(4));
|
||||
}
|
||||
|
||||
@Test
|
||||
void validatesRegion() {
|
||||
assertThrows(IllegalArgumentException.class, () -> RegionInfoFormatter.format(null));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user