Skip to content

Commit

Permalink
Forward Port from 1.18
Browse files Browse the repository at this point in the history
More version-agnostic helpers

Distributed room scanning over multiple ticks

On a long-lived server with many registered doors, we were encountering
crashes due to exceeding the 60 second tick limit.

Instead of trying to calculate all rooms in a single tick, we now detect
individual rooms per tick and utilize PendingTownRooms
to collect and register them once they've all been detected.

Updating RoomRecipes to debug some scanning problems

Added debug mode for debugging room scans

Switched debug from config to command

Remove debug configs
  • Loading branch information
bradsk88 committed Mar 14, 2024
1 parent 5f4a15c commit a52c873
Show file tree
Hide file tree
Showing 19 changed files with 716 additions and 180 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ dependencies {

implementation fg.deobf("mezz.jei:jei-1.19.2-forge:11.5.0.297")

implementation 'ca.bradj:RoomRecipes:1.19.2-0.0.4-alpha.2'
implementation 'ca.bradj:RoomRecipes:1.19.2-0.0.5-alpha.1'

compileOnly fg.deobf("vazkii.patchouli:Patchouli:1.19.2-77:api")
runtimeOnly fg.deobf("vazkii.patchouli:Patchouli:1.19.2-77")
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/ca/bradj/questown/commands/CommandEvents.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@ public static void on(RegisterCommandsEvent event) {
FreezeCommand.register(event.getDispatcher());
ConfigCommand.register(event.getDispatcher());
FlagCommand.register(event.getDispatcher());
DebugCommand.register(event.getDispatcher());
DebugDoorsCommand.register(event.getDispatcher());
}
}
36 changes: 36 additions & 0 deletions src/main/java/ca/bradj/questown/commands/DebugCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package ca.bradj.questown.commands;

import ca.bradj.questown.town.TownFlagBlockEntity;
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.entity.BlockEntity;

public class DebugCommand {
public static void register(CommandDispatcher<CommandSourceStack> p_137808_) {
p_137808_.register(Commands.literal("qtdebug")
.requires((p_137812_) -> {
return p_137812_.hasPermission(2);
})
.then(Commands.argument("pos", BlockPosArgument.blockPos())
.executes(css -> {
return startDebug(css.getSource(), BlockPosArgument.getLoadedBlockPos(css, "pos"));
})));
}

private static int startDebug(
CommandSourceStack source,
BlockPos target
) {
BlockEntity e = source.getLevel().getBlockEntity(target);
if (!(e instanceof TownFlagBlockEntity tfbe)) {
// TODO: Better error handling?
return -1;
}

tfbe.toggleDebugMode();
return 0;
}
}
50 changes: 50 additions & 0 deletions src/main/java/ca/bradj/questown/commands/DebugDoorsCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package ca.bradj.questown.commands;

import ca.bradj.questown.blocks.TownFlagBlock;
import ca.bradj.questown.core.init.items.ItemsInit;
import ca.bradj.questown.town.TownFlagBlockEntity;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
import net.minecraft.core.BlockPos;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity;

public class DebugDoorsCommand {
public static void register(CommandDispatcher<CommandSourceStack> p_137808_) {
p_137808_.register(Commands.literal("qtdebugdoors")
.requires((p_137812_) -> {
return p_137812_.hasPermission(2);
})
.then(Commands.argument("pos", BlockPosArgument.blockPos())
.executes(css -> {
return giveDebug(css.getSource(), BlockPosArgument.getLoadedBlockPos(css, "pos"));
})));
}

private static int giveDebug(
CommandSourceStack source,
BlockPos target
) {
BlockEntity e = source.getLevel().getBlockEntity(target);
if (!(e instanceof TownFlagBlockEntity tfbe)) {
// TODO: Better error handling?
return -1;
}

ItemStack debugItem = ItemsInit.TOWN_DOOR_TESTER.get()
.getDefaultInstance();
TownFlagBlock.StoreParentOnNBT(
debugItem,
target
);
try {
source.getPlayerOrException().getInventory().add(debugItem);
} catch (CommandSyntaxException ex) {
throw new RuntimeException(ex);
}
return 0;
}
}
19 changes: 15 additions & 4 deletions src/main/java/ca/bradj/questown/core/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public class Config {
public static final ForgeConfigSpec.ConfigValue<Boolean> JOB_BOARD_ENABLED;
public static final ForgeConfigSpec.ConfigValue<Boolean> CRASH_ON_FAILED_WARP;
public static final ForgeConfigSpec.ConfigValue<Integer> TIME_WARP_MAX_TICKS;
public static final ForgeConfigSpec.ConfigValue<Boolean> LOG_WARP_RESULT;
public static final ForgeConfigSpec.ConfigValue<Integer> BASE_MAX_LOOP;
public static final ForgeConfigSpec.ConfigValue<Long> MAX_TICKS_WITHOUT_SUPPLIES;
public static final ForgeConfigSpec.ConfigValue<Integer> BASE_FULLNESS;
Expand All @@ -65,7 +66,8 @@ public class Config {
public static final ForgeConfigSpec.ConfigValue<Integer> NEUTRAL_MOOD;
public static final ForgeConfigSpec.ConfigValue<Long> MOOD_EFFECT_DURATION_ATE_UNCOMFORTABLY;
public static final ForgeConfigSpec.ConfigValue<Long> MOOD_EFFECT_DURATION_ATE_COMFORTABLY;

public static final ForgeConfigSpec.ConfigValue<Integer> MAX_ROOM_DIMENSION;
public static final ForgeConfigSpec.ConfigValue<Integer> MAX_ROOM_SCAN_ITERATIONS;

static {
// Scanning Config
Expand All @@ -86,6 +88,12 @@ public class Config {
BIOME_SCAN_RADIUS = BUILDER.comment(
"The radius of chunks that will be scanned outward (in a plus shape) from the flag for the purpose of populating gatherer loot"
).defineInRange("BiomeScanRadius", 20, 0, 100);
MAX_ROOM_DIMENSION = BUILDER.comment(
"The maximum length or width of a room that can be detected"
).defineInRange("MaxRoomDimension", 20, 2, 100);
MAX_ROOM_SCAN_ITERATIONS = BUILDER.comment(
"The maximum number of ticks that will be spent searching for town rooms"
).defineInRange("MaxRoomScanIterations", 1000, 1, 24000);
BUILDER.pop();

// Quests Config
Expand Down Expand Up @@ -212,6 +220,9 @@ public class Config {
"The radius of \"Meta-Rooms\" that exist around points of interest in the town. E.g." +
"There is a meta room around the town flag itself, and one around each welcome mat"
).defineInRange("MetaRoomDiameter", 2, 1, 100);
BLOCK_CLAIMS_TICK_LIMIT = BUILDER.comment(
"If a job claims a block. It will hold that claim for this many ticks. (Or until they finish their work, whatever happens first)"
).defineInRange("BlockClaimsTickLimit", 1000L, 1, 24000);

// Time Warp
BUILDER.push("TimeWarp").comment(
Expand All @@ -223,9 +234,9 @@ public class Config {
TIME_WARP_MAX_TICKS = BUILDER.comment(
"Since the player can be gone for a very long time, we enforce a maximum warp to prevent the warp taking too long to compute."
).defineInRange("MaxTicks", 200000, 1, Integer.MAX_VALUE);
BLOCK_CLAIMS_TICK_LIMIT = BUILDER.comment(
"If a job claims a block. It will hold that claim for this many ticks. (Or until they finish their work, whatever happens first)"
).defineInRange("BlockClaimsTickLimit", 1000L, 1, 24000);
LOG_WARP_RESULT = BUILDER.comment(
"Set true to enable logging of the town state after a time warp. This produces a large log message and may cause lag."
).define("LogWarpResult", false);
BUILDER.pop(); // Yep, really thrice. Getting out of nested config
BUILDER.pop();
BUILDER.pop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ public class ItemsInit {
TownDoorItem::new
);

public static final RegistryObject<Item> TOWN_DOOR_TESTER = ITEMS.register(
TownDoorTestItem.ITEM_ID,
TownDoorTestItem::new
);

public static final RegistryObject<Item> FALSE_DOOR = ITEMS.register(
FalseDoorItem.ITEM_ID,
FalseDoorItem::new
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ public String toShortString() {

@Override
public String toString() {
Collection<MCTownItem> items = new ArrayList<>();
Collection<String> items = new ArrayList<>();
for (int i = 0; i < container.getContainerSize(); i++) {
items.add(getItem(i));
items.add(getItem(i).getShortName());
}
return "MCContainer{" +
"container.items=" + items +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ public String getShortName() {
if (registryName != null) {
name = registryName.toString();
}
if (quantity > 1) {
name = String.format("%sx%s", quantity, name);
}
return name;
}

Expand Down
53 changes: 53 additions & 0 deletions src/main/java/ca/bradj/questown/items/TownDoorTestItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package ca.bradj.questown.items;

import ca.bradj.questown.Questown;
import ca.bradj.questown.blocks.TownFlagBlock;
import ca.bradj.questown.town.TownFlagBlockEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.DoorBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
import org.jetbrains.annotations.NotNull;

public class TownDoorTestItem extends Item {
public static final String ITEM_ID = "town_door_tester";

public TownDoorTestItem() {
super(Questown.DEFAULT_ITEM_PROPS);
}

@Override
public InteractionResult useOn(net.minecraft.world.item.context.UseOnContext ctx) {
return startDebug(ctx);
}

@NotNull
private static InteractionResult startDebug(net.minecraft.world.item.context.UseOnContext ctx) {
if (ctx.getLevel()
.isClientSide()) {
return InteractionResult.PASS;
}
TownFlagBlockEntity parent = TownFlagBlock.GetParentFromNBT((ServerLevel) ctx.getLevel(), ctx.getItemInHand());
BlockPos clickedPos = ctx.getClickedPos();
BlockState bs = parent.getServerLevel()
.getBlockState(clickedPos);
if (bs.getBlock() instanceof DoorBlock) {
if (DoubleBlockHalf.UPPER.equals(bs.getValue(DoorBlock.HALF))) {
clickedPos = clickedPos.below();
}
} else {
bs = parent.getServerLevel()
.getBlockState(clickedPos.above());
if (bs.getBlock() instanceof DoorBlock) {
clickedPos = clickedPos.above();
}
}
parent.startDebugTask(parent.getRoomHandle()
.getDebugTaskForDoor(clickedPos));
return InteractionResult.CONSUME;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public static Work asWork(
new ExpirationRules(
() -> Long.MAX_VALUE,
jobId -> jobId,
Config.MAX_TICKS_WITHOUT_DINING_TABLE,
Util.configGet(Config.MAX_TICKS_WITHOUT_DINING_TABLE),
jobId -> DinerNoTableWork.getIdForRoot(jobId.rootId())
)
);
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/ca/bradj/questown/mc/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import net.minecraft.world.MenuProvider;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.level.block.Block;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.network.NetworkHooks;
Expand Down Expand Up @@ -122,4 +123,8 @@ public static <X> ImmutableMap<Integer, X> realize(ImmutableMap<Integer, Supplie
theoretical.forEach((k, v) -> b.put(k, v.get()));
return b.build();
}

public static <X> Supplier<X> configGet(ForgeConfigSpec.ConfigValue<X> cfg) {
return cfg::get;
}
}
Loading

0 comments on commit a52c873

Please sign in to comment.