Clean repo for open source release
Remove build artifacts, dev tool configs, unused dependencies, and third-party source dumps. Add proper README, update .gitignore, clean up Makefile.
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
package com.tiedup.remake.events.camp;
|
||||
|
||||
import com.tiedup.remake.cells.CampMaidManager;
|
||||
import com.tiedup.remake.cells.CampOwnership;
|
||||
import com.tiedup.remake.core.TiedUpMod;
|
||||
import com.tiedup.remake.entities.EntityMaid;
|
||||
import com.tiedup.remake.entities.EntitySlaveTrader;
|
||||
import com.tiedup.remake.entities.ModEntities;
|
||||
// Prison system v2
|
||||
import com.tiedup.remake.prison.PrisonerManager;
|
||||
import com.tiedup.remake.prison.service.PrisonerService;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
/**
|
||||
* Handles camp management tasks including maid respawn.
|
||||
*
|
||||
* When a maid dies:
|
||||
* - Camp remains alive (trader still exists)
|
||||
* - Prisoners are paused (no new tasks)
|
||||
* - After 5 minutes (6000 ticks), a new maid spawns
|
||||
* - Prisoners are notified and labor resumes
|
||||
*/
|
||||
@Mod.EventBusSubscriber(
|
||||
modid = TiedUpMod.MOD_ID,
|
||||
bus = Mod.EventBusSubscriber.Bus.FORGE
|
||||
)
|
||||
public class CampManagementHandler {
|
||||
|
||||
// Check every 100 ticks (5 seconds) - optimized for performance
|
||||
private static final int CHECK_INTERVAL_TICKS = 100;
|
||||
|
||||
private static int tickCounter = 0;
|
||||
|
||||
/**
|
||||
* Periodically check for camps needing maid respawn.
|
||||
*/
|
||||
@SubscribeEvent
|
||||
public static void onServerTick(TickEvent.ServerTickEvent event) {
|
||||
if (event.phase != TickEvent.Phase.END) return;
|
||||
|
||||
tickCounter++;
|
||||
if (tickCounter < CHECK_INTERVAL_TICKS) return;
|
||||
tickCounter = 0;
|
||||
|
||||
// Process all worlds
|
||||
for (ServerLevel level : event.getServer().getAllLevels()) {
|
||||
processCampManagement(level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process camp management for a specific level.
|
||||
*/
|
||||
private static void processCampManagement(ServerLevel level) {
|
||||
// IMPORTANT: Always use server-level registry to avoid dimension fragmentation
|
||||
CampOwnership ownership = CampOwnership.get(level.getServer());
|
||||
long currentTime = level.getGameTime();
|
||||
|
||||
// Get camps that need maid respawn
|
||||
List<UUID> campsNeedingMaid = CampMaidManager.getCampsNeedingMaidRespawn(
|
||||
currentTime, level
|
||||
);
|
||||
|
||||
for (UUID campId : campsNeedingMaid) {
|
||||
spawnNewMaidForCamp(level, ownership, campId);
|
||||
}
|
||||
|
||||
// Prison system v2 - tick escape service (handles escape detection)
|
||||
PrisonerService.get().tick(level.getServer(), currentTime);
|
||||
|
||||
// Prison system v2 - tick protection expiry
|
||||
PrisonerManager.get(level).tickProtectionExpiry(currentTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn a new maid for a camp that needs one.
|
||||
*
|
||||
* @param level The server level
|
||||
* @param ownership The camp ownership data
|
||||
* @param campId The camp UUID
|
||||
*/
|
||||
private static void spawnNewMaidForCamp(
|
||||
ServerLevel level,
|
||||
CampOwnership ownership,
|
||||
UUID campId
|
||||
) {
|
||||
CampOwnership.CampData campData = ownership.getCamp(campId);
|
||||
if (campData == null || !campData.isAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BlockPos center = campData.getCenter();
|
||||
if (center == null) {
|
||||
TiedUpMod.LOGGER.warn(
|
||||
"[CampManagementHandler] Cannot spawn maid - camp {} has no center position",
|
||||
campId.toString().substring(0, 8)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
UUID traderUUID = campData.getTraderUUID();
|
||||
if (traderUUID == null) {
|
||||
TiedUpMod.LOGGER.warn(
|
||||
"[CampManagementHandler] Cannot spawn maid - camp {} has no trader",
|
||||
campId.toString().substring(0, 8)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the trader entity
|
||||
Entity traderEntity = level.getEntity(traderUUID);
|
||||
EntitySlaveTrader trader = null;
|
||||
if (traderEntity instanceof EntitySlaveTrader t) {
|
||||
trader = t;
|
||||
} else {
|
||||
// Trader not loaded - search near camp center
|
||||
trader = findTraderNearPosition(level, center, 50);
|
||||
}
|
||||
|
||||
if (trader == null) {
|
||||
TiedUpMod.LOGGER.warn(
|
||||
"[CampManagementHandler] Cannot spawn maid - trader not found for camp {}",
|
||||
campId.toString().substring(0, 8)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new maid
|
||||
EntityMaid maid = ModEntities.MAID.get().create(level);
|
||||
if (maid == null) {
|
||||
TiedUpMod.LOGGER.error(
|
||||
"[CampManagementHandler] Failed to create maid entity for camp {}",
|
||||
campId.toString().substring(0, 8)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Find spawn position near trader (slightly offset)
|
||||
BlockPos spawnPos = findSafeSpawnPosition(
|
||||
level,
|
||||
trader.blockPosition()
|
||||
);
|
||||
|
||||
// Position the maid
|
||||
maid.moveTo(
|
||||
spawnPos.getX() + 0.5,
|
||||
spawnPos.getY(),
|
||||
spawnPos.getZ() + 0.5,
|
||||
trader.getYRot() + 180, // Face opposite direction from trader
|
||||
0
|
||||
);
|
||||
|
||||
// Link maid to trader
|
||||
maid.setMasterTraderUUID(trader.getUUID());
|
||||
|
||||
// Add to world
|
||||
level.addFreshEntity(maid);
|
||||
|
||||
// Update camp ownership with new maid
|
||||
CampMaidManager.assignNewMaid(campId, maid.getUUID(), level);
|
||||
|
||||
// Update trader's maid reference
|
||||
trader.setMaidUUID(maid.getUUID());
|
||||
|
||||
TiedUpMod.LOGGER.info(
|
||||
"[CampManagementHandler] Spawned replacement maid {} for camp {} at {}",
|
||||
maid.getNpcName(),
|
||||
campId.toString().substring(0, 8),
|
||||
spawnPos.toShortString()
|
||||
);
|
||||
|
||||
// Notify prisoners
|
||||
notifyPrisonersOfNewMaid(level, campId, maid.getNpcName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a trader near the given position.
|
||||
*/
|
||||
private static EntitySlaveTrader findTraderNearPosition(
|
||||
ServerLevel level,
|
||||
BlockPos pos,
|
||||
int radius
|
||||
) {
|
||||
List<EntitySlaveTrader> traders = level.getEntitiesOfClass(
|
||||
EntitySlaveTrader.class,
|
||||
new net.minecraft.world.phys.AABB(pos).inflate(radius)
|
||||
);
|
||||
return traders.isEmpty() ? null : traders.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a safe position to spawn the maid.
|
||||
* Tries positions around the target, prioritizing nearby valid spots.
|
||||
*/
|
||||
private static BlockPos findSafeSpawnPosition(
|
||||
ServerLevel level,
|
||||
BlockPos targetPos
|
||||
) {
|
||||
// Try offsets in a spiral pattern
|
||||
int[][] offsets = {
|
||||
{ 1, 0 },
|
||||
{ 0, 1 },
|
||||
{ -1, 0 },
|
||||
{ 0, -1 },
|
||||
{ 1, 1 },
|
||||
{ -1, 1 },
|
||||
{ -1, -1 },
|
||||
{ 1, -1 },
|
||||
{ 2, 0 },
|
||||
{ 0, 2 },
|
||||
{ -2, 0 },
|
||||
{ 0, -2 },
|
||||
};
|
||||
|
||||
for (int[] offset : offsets) {
|
||||
BlockPos testPos = targetPos.offset(offset[0], 0, offset[1]);
|
||||
|
||||
// Check if position is safe (solid ground, air above)
|
||||
if (isValidSpawnPosition(level, testPos)) {
|
||||
return testPos;
|
||||
}
|
||||
|
||||
// Try one block down
|
||||
BlockPos downPos = testPos.below();
|
||||
if (isValidSpawnPosition(level, downPos)) {
|
||||
return downPos;
|
||||
}
|
||||
|
||||
// Try one block up
|
||||
BlockPos upPos = testPos.above();
|
||||
if (isValidSpawnPosition(level, upPos)) {
|
||||
return upPos;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: use target position
|
||||
return targetPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a position is valid for spawning.
|
||||
*/
|
||||
private static boolean isValidSpawnPosition(
|
||||
ServerLevel level,
|
||||
BlockPos pos
|
||||
) {
|
||||
// Ground must be solid
|
||||
if (!level.getBlockState(pos.below()).isSolid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Position and above must be passable (air or similar)
|
||||
if (!level.getBlockState(pos).isAir()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!level.getBlockState(pos.above()).isAir()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all prisoners of this camp that a new maid has arrived.
|
||||
*/
|
||||
private static void notifyPrisonersOfNewMaid(
|
||||
ServerLevel level,
|
||||
UUID campId,
|
||||
String maidName
|
||||
) {
|
||||
PrisonerManager manager = PrisonerManager.get(level);
|
||||
for (UUID prisonerId : manager.getPrisonersInCamp(campId)) {
|
||||
ServerPlayer player = level
|
||||
.getServer()
|
||||
.getPlayerList()
|
||||
.getPlayer(prisonerId);
|
||||
if (player != null) {
|
||||
player.sendSystemMessage(
|
||||
Component.literal(
|
||||
"A new maid, " +
|
||||
maidName +
|
||||
", has arrived. Work resumes."
|
||||
).withStyle(ChatFormatting.GOLD)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user