diff --git a/src/main/java/com/vinlanx/explosionoverhaul/BlockIndexManager.java b/src/main/java/com/vinlanx/explosionoverhaul/BlockIndexManager.java index 859914c..438d34d 100644 --- a/src/main/java/com/vinlanx/explosionoverhaul/BlockIndexManager.java +++ b/src/main/java/com/vinlanx/explosionoverhaul/BlockIndexManager.java @@ -1,1801 +1,115 @@ -/* - * Decompiled with CFR 0.152. - */ package com.vinlanx.explosionoverhaul; -import net.minecraft.core.registries.BuiltInRegistries; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.reflect.TypeToken; -import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; -import com.mojang.serialization.DynamicOps; -import com.vinlanx.explosionoverhaul.Config; -import com.vinlanx.explosionoverhaul.ExplosionOverhaul; -import com.vinlanx.explosionoverhaul.PacketHandler; -import com.vinlanx.explosionoverhaul.ScanLoadPromptPacket; -import com.vinlanx.explosionoverhaul.ScanProgressPacket; -import com.vinlanx.explosionoverhaul.ScanPromptPacket; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.ByteArrayInputStream; -import java.io.DataInput; -import java.io.DataInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; -import java.io.Reader; -import java.lang.reflect.Type; -import java.nio.file.Files; -import java.nio.file.LinkOption; -import java.nio.file.OpenOption; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.attribute.FileAttribute; -import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.IdentityHashMap; import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.atomic.LongAdder; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.zip.GZIPInputStream; -import java.util.zip.InflaterInputStream; import net.minecraft.core.BlockPos; -import net.minecraft.core.IdMap; -import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtIo; -import net.minecraft.nbt.NbtOps; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.PalettedContainer; -import net.minecraft.world.level.storage.LevelResource; -import net.neoforged.neoforge.event.TickEvent; -import net.neoforged.neoforge.event.entity.player.PlayerEvent; -import net.neoforged.neoforge.event.level.BlockEvent; -import net.neoforged.neoforge.event.level.ChunkEvent; -import net.neoforged.neoforge.event.server.ServerStartedEvent; -import net.neoforged.neoforge.event.server.ServerStoppedEvent; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.common.Mod; -import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.neoforge.server.ServerLifecycleHooks; -@EventBusSubscriber public class BlockIndexManager { - private static volatile MinecraftServer currentServer; - private static final Map, ConcurrentHashMap>> indexByDimension; - private static final ConcurrentLinkedQueue chunkScanQueue; - private static final Map, Set> pendingChunkKeys; - public static volatile boolean ENABLED; - private static final boolean SCAN_ONLY_ON_START = true; - private static volatile boolean INITIAL_SCAN_ENQUEUED; - private static volatile int totalChunksToScan; - private static volatile int chunksScanned; - private static volatile boolean scanningComplete; - private static volatile boolean abortCurrentScan; - private static volatile int lampsFound; - private static volatile int dripstonesFound; - private static volatile int glassBlocksFound; - private static volatile ResourceKey lastScannedDimension; - private static volatile boolean waitingForUserInput; - private static volatile ServerLevel pendingScanLevel; - private static volatile ResourceKey currentScannedWorld; - private static volatile boolean isSingleplayer; - private static volatile boolean serverScanPromptShown; - private static volatile boolean serverScanDecisionMade; - private static volatile boolean isRescanMode; - private static volatile ServerPlayer rescanRequestingPlayer; - private static volatile boolean userDeclinedScan; - private static volatile boolean waitingForLoadDecision; - private static volatile boolean hasSaveFile; - private static volatile String currentWorldId; - private static final List DEFAULT_REINFORCED_GLASS_BLACKLIST; - private static final Path MOD_CONFIG_DIRECTORY; - private static final Path GLASS_BLACKLIST_FILE; - private static final CopyOnWriteArrayList GLASS_BLACKLIST; - private static final AtomicReference> GLASS_BLACKLIST_LOOKUP; - - private static ConcurrentHashMap> getOrCreateDimIndex(ServerLevel level) { - ResourceKey dim = level.m_46472_(); - return indexByDimension.computeIfAbsent((ResourceKey)dim, k -> new ConcurrentHashMap()); - } - - private static Set getOrCreatePendingSet(ServerLevel level) { - ResourceKey dim = level.m_46472_(); - return pendingChunkKeys.computeIfAbsent((ResourceKey)dim, k -> Collections.newSetFromMap(new ConcurrentHashMap())); - } - - private static long chunkKey(ChunkPos cp) { - return (long)cp.f_45578_ & 0xFFFFFFFFL | ((long)cp.f_45579_ & 0xFFFFFFFFL) << 32; - } - - private static long packPos(BlockPos pos) { - return pos.m_121878_(); - } - - private static BlockPos unpackPos(long packed) { - return BlockPos.m_122022_((long)packed); - } + public static volatile boolean ENABLED = false; public static int getTotalChunksToScan() { - return totalChunksToScan; + return 0; } public static int getChunksScanned() { - return chunksScanned; + return 0; } public static float getScanProgress() { - if (totalChunksToScan == 0) { - return 1.0f; - } - return Math.min(1.0f, (float)chunksScanned / (float)totalChunksToScan); + return 0.0f; } public static boolean isScanningComplete() { - return scanningComplete; + return true; } public static int getLampsFound() { - return lampsFound; + return 0; } public static int getDripstonesFound() { - return dripstonesFound; + return 0; } public static int getGlassBlocksFound() { - return glassBlocksFound; - } - - private static void clearScanDataSilent() { - indexByDimension.clear(); - chunkScanQueue.clear(); - pendingChunkKeys.clear(); - totalChunksToScan = 0; - chunksScanned = 0; - scanningComplete = false; - currentScannedWorld = null; - lastScannedDimension = null; - lampsFound = 0; - dripstonesFound = 0; - glassBlocksFound = 0; - } - - private static void clearScanData() { - BlockIndexManager.clearScanDataSilent(); - BlockIndexManager.sendProgressUpdate(); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: cleared all scan data for world switch"); - } - - private static void clearAndSaveData() { - if (!indexByDimension.isEmpty() && scanningComplete) { - try { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - if (server != null) { - BlockIndexManager.saveIndexData(server); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: saved data before clearing"); - } - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to save data before clearing: {}", (Object)e.getMessage()); - } - } - BlockIndexManager.clearScanData(); - } - - private static void startSingleplayerScan(ServerLevel level) { - ExplosionOverhaul.LOGGER.info("BlockIndexManager: starting singleplayer scan for ALL dimensions"); - BlockIndexManager.clearScanDataSilent(); - MinecraftServer server = level.m_7654_(); - BlockIndexManager.scanExistingChunksOnServer(server); - } - - private static void startServerScan(MinecraftServer server) { - ExplosionOverhaul.LOGGER.info("BlockIndexManager: starting server-wide scan for all dimensions"); - BlockIndexManager.clearScanDataSilent(); - BlockIndexManager.scanExistingChunksOnServer(server); - } - - private static void scanSingleWorld(ServerLevel level) { - try { - chunksScanned = 0; - scanningComplete = false; - lastScannedDimension = level.m_46472_(); - lampsFound = 0; - dripstonesFound = 0; - glassBlocksFound = 0; - String dimensionName = level.m_46472_().m_135782_().toString(); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: scanning existing chunks in world: {}", (Object)dimensionName); - Set existingChunks = BlockIndexManager.getAllExistingChunks(level); - totalChunksToScan = existingChunks.size(); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: found {} chunks to scan", (Object)totalChunksToScan); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: using safe server-thread scanning for live chunks"); - BlockIndexManager.scanWithSingleThread(level, existingChunks); - } - catch (Exception ex) { - ExplosionOverhaul.LOGGER.warn("BlockIndexManager: failed to start scan: {}", (Object)ex.toString()); - } - } - - private static void scanWithSingleThread(ServerLevel level, Set existingChunks) { - for (ChunkPos cp : existingChunks) { - chunkScanQueue.add(new ScanTask((ResourceKey)level.m_46472_(), cp)); - } - BlockIndexManager.sendProgressUpdate(); - } - - private static Set getAllExistingChunks(ServerLevel level) { - Set existingChunks; - block18: { - existingChunks = Collections.newSetFromMap(new ConcurrentHashMap()); - try { - ExplosionOverhaul.LOGGER.info("BlockIndexManager: scanning for all existing chunks..."); - MinecraftServer server = level.m_7654_(); - String dimPath = level.m_46472_().m_135782_().m_135815_(); - Path worldPath = server.m_129843_(LevelResource.f_78182_); - Path regionPath = "overworld".equals(dimPath) ? worldPath.resolve("region") : ("the_nether".equals(dimPath) ? worldPath.resolve("DIM-1").resolve("region") : ("the_end".equals(dimPath) ? worldPath.resolve("DIM1").resolve("region") : worldPath.resolve("dimensions").resolve(level.m_46472_().m_135782_().m_135827_()).resolve(level.m_46472_().m_135782_().m_135815_()).resolve("region"))); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: scanning region files in: {}", (Object)regionPath); - if (Files.exists(regionPath, new LinkOption[0])) { - try (Stream regionFiles = Files.list(regionPath);){ - List mcaFiles = regionFiles.filter(path -> path.toString().endsWith(".mca")).collect(Collectors.toList()); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: found {} .mca files in region directory", (Object)mcaFiles.size()); - mcaFiles.parallelStream().forEach(regionFile -> { - block13: { - try { - int chunksInThisRegion; - int regionZ; - int regionX; - block14: { - String[] parts; - String fileName = regionFile.getFileName().toString(); - if (!fileName.startsWith("r.") || !fileName.endsWith(".mca") || (parts = fileName.substring(2, fileName.length() - 4).split("\\.")).length != 2) break block13; - regionX = Integer.parseInt(parts[0]); - regionZ = Integer.parseInt(parts[1]); - chunksInThisRegion = 0; - try (InputStream is = Files.newInputStream(regionFile, new OpenOption[0]);){ - byte[] header = new byte[4096]; - int bytesRead = is.read(header); - if (bytesRead < 4096) break block14; - for (int i = 0; i < 1024; ++i) { - int offset = i * 4; - int chunkOffset = (header[offset] & 0xFF) << 16 | (header[offset + 1] & 0xFF) << 8 | header[offset + 2] & 0xFF; - if (chunkOffset <= 0) continue; - int cx = i % 32; - int cz = i / 32; - int chunkX = regionX * 32 + cx; - int chunkZ = regionZ * 32 + cz; - ChunkPos cp = new ChunkPos(chunkX, chunkZ); - existingChunks.add(cp); - ++chunksInThisRegion; - } - } - catch (Exception readEx) { - ExplosionOverhaul.LOGGER.warn("BlockIndexManager: failed to read region file {}: {}", (Object)fileName, (Object)readEx.getMessage()); - for (int cx = 0; cx < 32; ++cx) { - for (int cz = 0; cz < 32; ++cz) { - int chunkX = regionX * 32 + cx; - int chunkZ = regionZ * 32 + cz; - ChunkPos cp = new ChunkPos(chunkX, chunkZ); - existingChunks.add(cp); - ++chunksInThisRegion; - } - } - } - } - ExplosionOverhaul.LOGGER.info("BlockIndexManager: region {},{} - found {} existing chunks (read from .mca header)", new Object[]{regionX, regionZ, chunksInThisRegion}); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("BlockIndexManager: failed to parse region file {}: {}", (Object)regionFile.getFileName(), (Object)e.getMessage()); - } - } - }); - } - ExplosionOverhaul.LOGGER.info("BlockIndexManager: scanned region files and found {} existing chunks", (Object)existingChunks.size()); - break block18; - } - ExplosionOverhaul.LOGGER.warn("BlockIndexManager: region directory not found: {}", (Object)regionPath); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.error("BlockIndexManager: failed to scan world storage: {}", (Object)e.getMessage()); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: using fallback - estimate chunks from .mca files"); - try { - String dimPath = level.m_46472_().m_135782_().m_135815_(); - MinecraftServer server = level.m_7654_(); - Path worldPath = server.m_129843_(LevelResource.f_78182_); - Path regionPath = "overworld".equals(dimPath) ? worldPath.resolve("region") : ("the_nether".equals(dimPath) ? worldPath.resolve("DIM-1").resolve("region") : ("the_end".equals(dimPath) ? worldPath.resolve("DIM1").resolve("region") : worldPath.resolve("dimensions").resolve(level.m_46472_().m_135782_().m_135827_()).resolve(level.m_46472_().m_135782_().m_135815_()).resolve("region"))); - if (!Files.exists(regionPath, new LinkOption[0])) break block18; - try (Stream regionFiles = Files.list(regionPath);){ - regionFiles.filter(path -> path.toString().endsWith(".mca")).forEach(regionFile -> { - String[] parts; - String fileName = regionFile.getFileName().toString(); - if (fileName.startsWith("r.") && fileName.endsWith(".mca") && (parts = fileName.substring(2, fileName.length() - 4).split("\\.")).length == 2) { - int regionX = Integer.parseInt(parts[0]); - int regionZ = Integer.parseInt(parts[1]); - for (int cx = 0; cx < 32; ++cx) { - for (int cz = 0; cz < 32; ++cz) { - int chunkX = regionX * 32 + cx; - int chunkZ = regionZ * 32 + cz; - ChunkPos cp = new ChunkPos(chunkX, chunkZ); - existingChunks.add(cp); - } - } - ExplosionOverhaul.LOGGER.info("BlockIndexManager: fallback added ~1024 chunks from region {},{}", (Object)regionX, (Object)regionZ); - } - }); - } - ExplosionOverhaul.LOGGER.info("BlockIndexManager: fallback found {} estimated chunks", (Object)existingChunks.size()); - } - catch (Exception fallbackEx) { - ExplosionOverhaul.LOGGER.error("BlockIndexManager: fallback also failed: {}", (Object)fallbackEx.getMessage()); - } - } - } - return existingChunks; - } - - private static void saveIndexDataAfterScan(MinecraftServer server) { - try { - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Starting auto-save after scan completion..."); - BlockIndexManager.saveIndexData(server); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to auto-save scan data: {}", (Object)e.getMessage()); - e.printStackTrace(); - } - } - - private static void sendProgressUpdate() { - try { - ExplosionOverhaul.LOGGER.debug("sendProgressUpdate: {}/{} chunks, complete={}, L:{} D:{} G:{}", new Object[]{chunksScanned, totalChunksToScan, scanningComplete, lampsFound, dripstonesFound, glassBlocksFound}); - if (scanningComplete) { - ExplosionOverhaul.LOGGER.info("BlockIndexManager: sending final progress update to OP players - {}/{} chunks, lamps={}, dripstones={}, glass={}", new Object[]{chunksScanned, totalChunksToScan, lampsFound, dripstonesFound, glassBlocksFound}); - } - ScanProgressPacket packet = new ScanProgressPacket(totalChunksToScan, chunksScanned, scanningComplete, lampsFound, dripstonesFound, glassBlocksFound); - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - if (server != null) { - for (ServerPlayer player : server.m_6846_().m_11314_()) { - if (!BlockIndexManager.isPlayerAuthorized(player)) continue; - PacketHandler.sendToPlayer(player, packet); - } - } - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to send scan progress update: {}", (Object)e.getMessage()); - } - } - - private static void sendMultiThreadProgressUpdate(int currentProcessed, int currentLamps, int currentDripstones, int currentGlass) { - try { - ScanProgressPacket packet = new ScanProgressPacket(totalChunksToScan, currentProcessed, false, currentLamps, currentDripstones, currentGlass); - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - if (server != null) { - for (ServerPlayer player : server.m_6846_().m_11314_()) { - if (!BlockIndexManager.isPlayerAuthorized(player)) continue; - PacketHandler.sendToPlayer(player, packet); - } - } - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to send multi-thread progress update: {}", (Object)e.getMessage()); - } - } - - private static void sendScanPromptPacket(ServerPlayer player) { - try { - ScanPromptPacket packet = new ScanPromptPacket(true); - PacketHandler.sendToPlayer(player, packet); - ExplosionOverhaul.LOGGER.info("Sent scan prompt to authorized player: {}", (Object)player.m_7755_().getString()); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to send scan prompt: {}", (Object)e.getMessage()); - } + return 0; } public static void startManualScan() { - if (BlockIndexManager.isChunkScanningDisabled()) { - ExplosionOverhaul.LOGGER.info("BlockIndexManager: manual scan cancelled - chunk scanning is disabled in config"); - BlockIndexManager.cancelManualScan(); - return; - } - if (waitingForUserInput && pendingScanLevel != null) { - waitingForUserInput = false; - serverScanDecisionMade = true; - userDeclinedScan = false; - if (isRescanMode) { - ExplosionOverhaul.LOGGER.info("BlockIndexManager: clearing data for rescan as user confirmed"); - BlockIndexManager.clearScanDataSilent(); - try { - MinecraftServer server = pendingScanLevel.m_7654_(); - Path saveFile = BlockIndexManager.getSaveFilePath(server); - if (Files.exists(saveFile, new LinkOption[0])) { - Files.delete(saveFile); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: deleted old save file for rescan"); - } - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to delete old save file: {}", (Object)e.getMessage()); - } - } - if (isSingleplayer || isRescanMode) { - BlockIndexManager.startSingleplayerScan(pendingScanLevel); - } else { - BlockIndexManager.startServerScan(pendingScanLevel.m_7654_()); - } - ServerPlayer requestingPlayer = rescanRequestingPlayer; - pendingScanLevel = null; - isRescanMode = false; - rescanRequestingPlayer = null; - try { - if (requestingPlayer != null && requestingPlayer.m_6084_()) { - ScanPromptPacket packet = new ScanPromptPacket(false); - PacketHandler.sendToPlayer(requestingPlayer, packet); - } else { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - if (server != null) { - for (ServerPlayer player : server.m_6846_().m_11314_()) { - if (!BlockIndexManager.isPlayerAuthorized(player)) continue; - ScanPromptPacket packet = new ScanPromptPacket(false); - PacketHandler.sendToPlayer(player, packet); - } - } - } - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to hide scan prompt: {}", (Object)e.getMessage()); - } - } } - /* - * Unable to fully structure code - */ public static void loadExistingData() { - if (BlockIndexManager.waitingForLoadDecision && BlockIndexManager.pendingScanLevel != null) { - BlockIndexManager.waitingForLoadDecision = false; - BlockIndexManager.serverScanDecisionMade = true; - server = BlockIndexManager.pendingScanLevel.m_7654_(); - loaded = BlockIndexManager.loadIndexData(server); - if (loaded) { - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Successfully loaded existing scan data"); - BlockIndexManager.sendProgressUpdate(); - try { - currentServer = ServerLifecycleHooks.getCurrentServer(); - if (currentServer != null) { - for (ServerPlayer serverPlayer : currentServer.m_6846_().m_11314_()) { - if (!BlockIndexManager.isPlayerAuthorized(serverPlayer)) continue; - packet = new ScanLoadPromptPacket(false); - PacketHandler.sendToPlayer(serverPlayer, packet); - ExplosionOverhaul.LOGGER.debug("Hidden load prompt for authorized player: {}", (Object)serverPlayer.m_7755_().getString()); - } - } - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to hide load prompt: {}", (Object)e.getMessage()); - } - } else { - ExplosionOverhaul.LOGGER.warn("BlockIndexManager: Failed to load existing data, falling back to new scan"); - BlockIndexManager.startNewScan(); - } - BlockIndexManager.pendingScanLevel = null; - } } public static void startNewScan() { - if (waitingForLoadDecision && pendingScanLevel != null) { - waitingForLoadDecision = false; - serverScanDecisionMade = true; - userDeclinedScan = false; - try { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - if (server != null) { - for (ServerPlayer serverPlayer : server.m_6846_().m_11314_()) { - if (!BlockIndexManager.isPlayerAuthorized(serverPlayer)) continue; - ScanLoadPromptPacket hideLoadPacket = new ScanLoadPromptPacket(false); - PacketHandler.sendToPlayer(serverPlayer, hideLoadPacket); - ScanPromptPacket showScanPacket = new ScanPromptPacket(true); - PacketHandler.sendToPlayer(serverPlayer, showScanPacket); - ExplosionOverhaul.LOGGER.debug("Switched prompts for authorized player: {}", (Object)serverPlayer.m_7755_().getString()); - } - } - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to switch prompts: {}", (Object)e.getMessage()); - } - waitingForUserInput = true; - serverScanDecisionMade = false; - } } public static void cancelManualScan() { - if (waitingForUserInput) { - waitingForUserInput = false; - serverScanDecisionMade = true; - userDeclinedScan = true; - pendingScanLevel = null; - ServerPlayer requestingPlayer = rescanRequestingPlayer; - isRescanMode = false; - rescanRequestingPlayer = null; - chunkScanQueue.clear(); - totalChunksToScan = 0; - chunksScanned = 0; - scanningComplete = false; - ExplosionOverhaul.LOGGER.info("BlockIndexManager: manual scan cancelled by user - cleared scan queue"); - try { - if (requestingPlayer != null && requestingPlayer.m_6084_()) { - ScanPromptPacket packet = new ScanPromptPacket(false); - PacketHandler.sendToPlayer(requestingPlayer, packet); - } else { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - if (server != null) { - for (ServerPlayer player : server.m_6846_().m_11314_()) { - if (!BlockIndexManager.isPlayerAuthorized(player)) continue; - ScanPromptPacket packet = new ScanPromptPacket(false); - PacketHandler.sendToPlayer(player, packet); - } - } - } - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to hide scan prompt: {}", (Object)e.getMessage()); - } - } } public static void resetScanState() { - waitingForUserInput = false; - waitingForLoadDecision = false; - pendingScanLevel = null; - serverScanPromptShown = false; - serverScanDecisionMade = false; - isRescanMode = false; - rescanRequestingPlayer = null; - userDeclinedScan = false; - hasSaveFile = false; - INITIAL_SCAN_ENQUEUED = false; - BlockIndexManager.clearAndSaveData(); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: scan state reset by command"); } public static void forceServerScan(MinecraftServer server) { - BlockIndexManager.resetScanState(); - BlockIndexManager.startServerScan(server); } public static void forceSingleplayerScan(ServerLevel level) { - BlockIndexManager.resetScanState(); - BlockIndexManager.startSingleplayerScan(level); } public static void showRescanPrompt(ServerPlayer player) { - isRescanMode = true; - waitingForUserInput = true; - pendingScanLevel = player.m_284548_(); - rescanRequestingPlayer = player; - serverScanPromptShown = true; - serverScanDecisionMade = false; - try { - ScanPromptPacket packet = new ScanPromptPacket(true); - PacketHandler.sendToPlayer(player, packet); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: showing rescan prompt to player: {}", (Object)player.m_7755_().getString()); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to send rescan prompt: {}", (Object)e.getMessage()); - } - } - - private static void sendScanPromptPacket(boolean show) { - try { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - if (server != null) { - for (ServerPlayer player : server.m_6846_().m_11314_()) { - if (!BlockIndexManager.isPlayerAuthorized(player)) continue; - ScanPromptPacket packet = new ScanPromptPacket(show); - PacketHandler.sendToPlayer(player, packet); - if (!show) continue; - ExplosionOverhaul.LOGGER.debug("Sent scan prompt to authorized player: {}", (Object)player.m_7755_().getString()); - } - } - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to send scan prompt packet: {}", (Object)e.getMessage()); - } - } - - private static boolean isGlassBlock(BlockState state) { - try { - String blockName = BuiltInRegistries.BLOCK.getKey(state.m_60734_()).toString().toLowerCase(Locale.ROOT); - if (BlockIndexManager.isGlassProtected(blockName)) { - return false; - } - return blockName.contains("glass"); - } - catch (Exception e) { - return state.m_60713_(Blocks.f_50058_) || state.m_60713_(Blocks.f_152498_); - } - } - - private static boolean isLampName(String name) { - return "minecraft:redstone_lamp".equals(name); - } - - private static boolean isDripstoneName(String name) { - return "minecraft:pointed_dripstone".equals(name); - } - - private static boolean isGlassName(String name) { - if (name == null) { - return false; - } - String normalized = name.toLowerCase(Locale.ROOT); - return normalized.contains("glass") && !BlockIndexManager.isGlassProtected(normalized); } public static boolean isReinforcedGlass(BlockState state) { - try { - String blockName = BuiltInRegistries.BLOCK.getKey(state.m_60734_()).toString().toLowerCase(Locale.ROOT); - return BlockIndexManager.isGlassProtected(blockName); - } - catch (Exception e) { - return false; - } + return false; } public static List getReinforcedGlassBlacklist() { - return new ArrayList(GLASS_BLACKLIST); + return Collections.emptyList(); } public static List getDefaultReinforcedGlassBlacklist() { - return new ArrayList(DEFAULT_REINFORCED_GLASS_BLACKLIST); + return Collections.emptyList(); } public static void setReinforcedGlassBlacklistFromList(List list) { - BlockIndexManager.applyGlassBlacklistList(list); - BlockIndexManager.saveGlassBlacklistToJson(); - } - - private static void ensureModConfigDirectory() { - try { - Files.createDirectories(MOD_CONFIG_DIRECTORY, new FileAttribute[0]); - } - catch (IOException e) { - ExplosionOverhaul.LOGGER.warn("BlockIndexManager: failed to create config directory for glass blacklist", (Throwable)e); - } - } - - private static void loadGlassBlacklistFromJson() { - BlockIndexManager.ensureModConfigDirectory(); - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - if (!Files.exists(GLASS_BLACKLIST_FILE, new LinkOption[0])) { - BlockIndexManager.applyGlassBlacklistList(DEFAULT_REINFORCED_GLASS_BLACKLIST); - BlockIndexManager.saveGlassBlacklistToJson(); - return; - } - try (BufferedReader reader = Files.newBufferedReader(GLASS_BLACKLIST_FILE);){ - List list = (List)gson.fromJson((Reader)reader, new TypeToken>(){}.getType()); - if (list == null) { - BlockIndexManager.applyGlassBlacklistList(DEFAULT_REINFORCED_GLASS_BLACKLIST); - return; - } - BlockIndexManager.applyGlassBlacklistList(list); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("BlockIndexManager: failed to load GlassBlacklist.json, falling back to defaults", (Throwable)e); - BlockIndexManager.applyGlassBlacklistList(DEFAULT_REINFORCED_GLASS_BLACKLIST); - } - } - - private static void saveGlassBlacklistToJson() { - BlockIndexManager.ensureModConfigDirectory(); - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - try (BufferedWriter writer = Files.newBufferedWriter(GLASS_BLACKLIST_FILE, new OpenOption[0]);){ - gson.toJson(new ArrayList(GLASS_BLACKLIST), (Appendable)writer); - } - catch (IOException e) { - ExplosionOverhaul.LOGGER.warn("BlockIndexManager: failed to save GlassBlacklist.json", (Throwable)e); - } - } - - private static void applyGlassBlacklistList(List list) { - List normalized = BlockIndexManager.normalizeBlacklist(list); - GLASS_BLACKLIST.clear(); - GLASS_BLACKLIST.addAll(normalized); - GLASS_BLACKLIST_LOOKUP.set(new HashSet(normalized)); - } - - private static List normalizeBlacklist(List entries) { - if (entries == null) { - return new ArrayList(); - } - ArrayList result = new ArrayList(); - HashSet seen = new HashSet(); - for (String raw : entries) { - String candidate; - if (raw == null || (candidate = raw.trim().toLowerCase(Locale.ROOT)).isEmpty() || !seen.add(candidate)) continue; - result.add(candidate); - } - return result; - } - - private static boolean isGlassProtected(String name) { - return GLASS_BLACKLIST_LOOKUP.get().contains(name); - } - - private static String generateWorldId(MinecraftServer server) { - try { - Path worldPath = server.m_129843_(LevelResource.f_78182_); - String worldName = server.m_129910_().m_5462_(); - String folderName = worldPath.getFileName().toString(); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: World path: {}", (Object)worldPath); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: World name from level.dat: '{}'", (Object)worldName); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Folder name: '{}'", (Object)folderName); - if (folderName == null || folderName.trim().isEmpty()) { - folderName = "world"; - } - if (worldName == null || worldName.trim().isEmpty()) { - worldName = "Unknown"; - } - String combined = folderName + "_" + worldName; - String result = combined.replaceAll("[^a-zA-Z0-9_-]", "_").toLowerCase(); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Generated world ID: '{}'", (Object)result); - return result; - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to generate world ID, using fallback: {}", (Object)e.getMessage()); - String fallback = "unknown_world_" + System.currentTimeMillis(); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Using fallback ID: '{}'", (Object)fallback); - return fallback; - } - } - - private static Path getSaveFilePath(MinecraftServer server) { - String worldId = BlockIndexManager.generateWorldId(server); - Path configDir = server.m_129843_(LevelResource.f_78182_).getParent().resolve("config").resolve("explosionoverhaul"); - try { - Files.createDirectories(configDir, new FileAttribute[0]); - ExplosionOverhaul.LOGGER.debug("BlockIndexManager: Using config directory: {}", (Object)configDir); - } - catch (IOException e) { - ExplosionOverhaul.LOGGER.error("Failed to create config directory: {}", (Object)e.getMessage()); - } - Path saveFile = configDir.resolve("block_index_" + worldId + ".json"); - ExplosionOverhaul.LOGGER.debug("BlockIndexManager: Save file path: {}", (Object)saveFile); - return saveFile; } public static void saveIndexData(MinecraftServer server) { - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Attempting to save data..."); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: IndexByDimension size: {}", (Object)indexByDimension.size()); - try { - Path saveFile = BlockIndexManager.getSaveFilePath(server); - if (!scanningComplete) { - ExplosionOverhaul.LOGGER.warn("BlockIndexManager: Scan incomplete - deleting save file instead of saving corrupted data"); - if (Files.exists(saveFile, new LinkOption[0])) { - Files.delete(saveFile); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Deleted incomplete save file: {}", (Object)saveFile); - } - return; - } - if (indexByDimension.isEmpty()) { - ExplosionOverhaul.LOGGER.warn("BlockIndexManager: No data to save - index is empty!"); - return; - } - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Saving to file: {}", (Object)saveFile); - HashMap saveData = new HashMap(); - int totalBlocks = 0; - for (Map.Entry, ConcurrentHashMap>> dimEntry : indexByDimension.entrySet()) { - String dimKey = dimEntry.getKey().m_135782_().toString(); - HashMap> chunkMap = new HashMap>(); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Processing dimension: {}", (Object)dimKey); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Chunks in dimension: {}", (Object)dimEntry.getValue().size()); - for (Map.Entry> chunkEntry : dimEntry.getValue().entrySet()) { - Set blocks = chunkEntry.getValue(); - if (blocks.isEmpty()) continue; - chunkMap.put(chunkEntry.getKey().toString(), blocks); - totalBlocks += blocks.size(); - } - if (chunkMap.isEmpty()) continue; - saveData.put(dimKey, chunkMap); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Added {} chunks with blocks to save data for dimension {}", (Object)chunkMap.size(), (Object)dimKey); - } - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Total blocks to save: {}", (Object)totalBlocks); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Dimensions to save: {}", (Object)saveData.size()); - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - String json = gson.toJson(saveData); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: JSON length: {}", (Object)json.length()); - if (json.length() < 20) { - ExplosionOverhaul.LOGGER.warn("BlockIndexManager: JSON too small ({} bytes) - skipping save to prevent corruption", (Object)json.length()); - return; - } - Files.write(saveFile, json.getBytes(), new OpenOption[0]); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Successfully saved index data to {}", (Object)saveFile); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.error("BlockIndexManager: Failed to save index data: {}", (Object)e.getMessage()); - e.printStackTrace(); - } } public static boolean loadIndexData(MinecraftServer server) { - try { - Type saveDataType; - Path saveFile = BlockIndexManager.getSaveFilePath(server); - if (!Files.exists(saveFile, new LinkOption[0])) { - ExplosionOverhaul.LOGGER.debug("BlockIndexManager: No save file found at {}", (Object)saveFile); - return false; - } - Gson gson = new Gson(); - String json = new String(Files.readAllBytes(saveFile)); - Map saveData = (Map)gson.fromJson(json, saveDataType = new TypeToken>>>(){}.getType()); - if (saveData == null || saveData.isEmpty()) { - ExplosionOverhaul.LOGGER.warn("BlockIndexManager: Save file is empty or corrupted"); - return false; - } - indexByDimension.clear(); - for (Map.Entry dimEntry : saveData.entrySet()) { - try { - ResourceKey dimKey = ResourceKey.m_135785_((ResourceKey)Registries.f_256858_, (ResourceLocation)ResourceLocation.parse((String)((String)dimEntry.getKey()))); - ConcurrentHashMap chunkMap = new ConcurrentHashMap(); - for (Map.Entry chunkEntry : ((Map)dimEntry.getValue()).entrySet()) { - Long chunkKey = Long.parseLong((String)chunkEntry.getKey()); - Set blockSet = Collections.newSetFromMap(new ConcurrentHashMap()); - blockSet.addAll((Collection)chunkEntry.getValue()); - chunkMap.put(chunkKey, blockSet); - } - indexByDimension.put((ResourceKey)dimKey, chunkMap); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("BlockIndexManager: Failed to load dimension {}: {}", dimEntry.getKey(), (Object)e.getMessage()); - } - } - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Successfully loaded index data from {}", (Object)saveFile); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Loaded {} dimensions with indexed blocks", (Object)indexByDimension.size()); - scanningComplete = true; - totalChunksToScan = 0; - chunksScanned = 0; - lampsFound = 0; - dripstonesFound = 0; - glassBlocksFound = 0; - return true; - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.error("BlockIndexManager: Failed to load index data: {}", (Object)e.getMessage()); - e.printStackTrace(); - return false; - } + return false; } public static boolean hasSaveFile(MinecraftServer server) { - Path saveFile = BlockIndexManager.getSaveFilePath(server); - return Files.exists(saveFile, new LinkOption[0]) && Files.isRegularFile(saveFile, new LinkOption[0]); - } - - private static int getChunksToScanPerTick() { - int cpuPercent = (Integer)Config.COMMON.scan.cpuUsagePercent.get(); - int baseChunks = 500; - return Math.max(1, baseChunks * cpuPercent / 100); - } - - private static boolean isChunkScanningDisabled() { - return (Boolean)Config.COMMON.scan.enableBlockIndexing.get() == false; - } - - private static boolean isScanning() { - return !chunkScanQueue.isEmpty() && totalChunksToScan > 0 && !scanningComplete; + return false; } public static boolean isRescanMode() { - return isRescanMode; + return false; } public static void register(ServerLevel level, BlockPos pos, BlockType type) { - ConcurrentHashMap> dimIndex = BlockIndexManager.getOrCreateDimIndex(level); - ChunkPos cp = new ChunkPos(pos); - long ck = BlockIndexManager.chunkKey(cp); - dimIndex.computeIfAbsent(ck, k -> Collections.newSetFromMap(new ConcurrentHashMap())).add(BlockIndexManager.packPos(pos)); } public static void unregister(ServerLevel level, BlockPos pos, BlockType type) { - ChunkPos cp; - long ck; - ConcurrentHashMap> dimIndex = BlockIndexManager.getOrCreateDimIndex(level); - Set set = dimIndex.get(ck = BlockIndexManager.chunkKey(cp = new ChunkPos(pos))); - if (set != null) { - set.remove(BlockIndexManager.packPos(pos)); - if (set.isEmpty()) { - dimIndex.remove(ck); - } - } - } - - public static void scanChunk(ServerLevel level, ChunkPos cp) { - long ck; - ConcurrentHashMap> dimIndex = BlockIndexManager.getOrCreateDimIndex(level); - if (dimIndex.containsKey(ck = BlockIndexManager.chunkKey(cp))) { - return; - } - int baseX = cp.m_45604_(); - int baseZ = cp.m_45605_(); - Set set = Collections.newSetFromMap(new ConcurrentHashMap()); - int chunkLamps = 0; - int chunkDripstones = 0; - int chunkGlass = 0; - for (int lx = 0; lx < 16; ++lx) { - for (int lz = 0; lz < 16; ++lz) { - for (int y = level.m_141937_(); y < level.m_151558_(); ++y) { - BlockPos pos = new BlockPos(baseX + lx, y, baseZ + lz); - if (!level.m_46749_(pos)) continue; - BlockState state = level.m_8055_(pos); - if (state.m_60713_(Blocks.f_50261_)) { - set.add(BlockIndexManager.packPos(pos)); - ++chunkLamps; - continue; - } - if (state.m_60713_(Blocks.f_152588_)) { - set.add(BlockIndexManager.packPos(pos)); - ++chunkDripstones; - continue; - } - if (!BlockIndexManager.isGlassBlock(state)) continue; - set.add(BlockIndexManager.packPos(pos)); - ++chunkGlass; - } - } - } - lampsFound += chunkLamps; - dripstonesFound += chunkDripstones; - glassBlocksFound += chunkGlass; - if (!set.isEmpty()) { - dimIndex.put(ck, set); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Found {} blocks in chunk {} {}: {}", new Object[]{set.size(), cp.f_45578_, cp.f_45579_, set.size() > 10 ? set.size() + " blocks" : set}); - } - if (++chunksScanned >= totalChunksToScan && totalChunksToScan > 0) { - MinecraftServer server; - scanningComplete = true; - int totalBlocksFound = 0; - for (Map.Entry, ConcurrentHashMap>> dimEntry : indexByDimension.entrySet()) { - for (Map.Entry> chunkEntry : dimEntry.getValue().entrySet()) { - totalBlocksFound += chunkEntry.getValue().size(); - } - } - ExplosionOverhaul.LOGGER.info("BlockIndexManager: chunk scanning completed! Scanned {}/{} chunks", (Object)chunksScanned, (Object)totalChunksToScan); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Found {} total blocks across {} dimensions", (Object)totalBlocksFound, (Object)indexByDimension.size()); - try { - server = ServerLifecycleHooks.getCurrentServer(); - if (server != null) { - ExplosionOverhaul.LOGGER.info("BlockIndexManager: Starting auto-save after scan completion..."); - BlockIndexManager.saveIndexData(server); - } - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to auto-save scan data: {}", (Object)e.getMessage()); - e.printStackTrace(); - } - try { - server = ServerLifecycleHooks.getCurrentServer(); - if (server != null) { - server.execute(() -> BlockIndexManager.sendProgressUpdate()); - } - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to enqueue final progress update: {}", (Object)e.getMessage()); - } - } - if (chunksScanned % 10 == 0 || scanningComplete) { - BlockIndexManager.sendProgressUpdate(); - } - } - - public static void removeChunk(ServerLevel level, ChunkPos cp) { - ConcurrentHashMap> dimIndex = BlockIndexManager.getOrCreateDimIndex(level); - long ck = BlockIndexManager.chunkKey(cp); - dimIndex.remove(ck); - Set pending = BlockIndexManager.getOrCreatePendingSet(level); - pending.remove(ck); } public static List getNearby(ServerLevel level, BlockPos center, int radius, BlockType type) { - ArrayList result = new ArrayList(); - int minX = center.m_123341_() - radius; - int maxX = center.m_123341_() + radius; - int minZ = center.m_123343_() - radius; - int maxZ = center.m_123343_() + radius; - int minChunkX = minX >> 4; - int maxChunkX = maxX >> 4; - int minChunkZ = minZ >> 4; - int maxChunkZ = maxZ >> 4; - ConcurrentHashMap> dimIndex = BlockIndexManager.getOrCreateDimIndex(level); - long r2 = (long)radius * (long)radius; - for (int cx = minChunkX; cx <= maxChunkX; ++cx) { - for (int cz = minChunkZ; cz <= maxChunkZ; ++cz) { - long ck = BlockIndexManager.chunkKey(new ChunkPos(cx, cz)); - Set set = dimIndex.get(ck); - if (set == null || set.isEmpty()) continue; - for (long packed : set) { - long dz; - long dy; - BlockPos pos = BlockIndexManager.unpackPos(packed); - long dx = pos.m_123341_() - center.m_123341_(); - if (dx * dx + (dy = (long)(pos.m_123342_() - center.m_123342_())) * dy + (dz = (long)(pos.m_123343_() - center.m_123343_())) * dz > r2) continue; - BlockState state = level.m_8055_(pos); - if (type == BlockType.LAMP && state.m_60713_(Blocks.f_50261_)) { - result.add(pos); - } - if (type == BlockType.DRIPSTONE && state.m_60713_(Blocks.f_152588_)) { - result.add(pos); - } - if (type != BlockType.GLASS || !BlockIndexManager.isGlassBlock(state)) continue; - result.add(pos); - } - } - } - return result; - } - - @SubscribeEvent - public static void onChunkLoad(ChunkEvent.Load event) { - if (!ENABLED) { - return; - } - if (BlockIndexManager.isChunkScanningDisabled()) { - return; - } - LevelAccessor levelAccessor = event.getLevel(); - if (!(levelAccessor instanceof ServerLevel)) { - return; - } - ServerLevel level = (ServerLevel)levelAccessor; - if (userDeclinedScan) { - return; - } - if (!isSingleplayer && !serverScanDecisionMade) { - return; - } - if (INITIAL_SCAN_ENQUEUED) { - return; - } - ResourceKey chunkDimension = level.m_46472_(); - if (lastScannedDimension != null && !lastScannedDimension.equals((Object)chunkDimension)) { - return; - } - if (scanningComplete) { - return; - } - long ck = BlockIndexManager.chunkKey(event.getChunk().m_7697_()); - Set pending = BlockIndexManager.getOrCreatePendingSet(level); - if (pending.add(ck)) { - chunkScanQueue.add(new ScanTask((ResourceKey)level.m_46472_(), event.getChunk().m_7697_())); - } - } - - @SubscribeEvent - public static void onChunkUnload(ChunkEvent.Unload event) { - if (!ENABLED) { - return; - } - LevelAccessor levelAccessor = event.getLevel(); - if (!(levelAccessor instanceof ServerLevel)) { - return; - } - ServerLevel level = (ServerLevel)levelAccessor; - BlockIndexManager.removeChunk(level, event.getChunk().m_7697_()); - chunkScanQueue.removeIf(t -> t.dim().equals((Object)level.m_46472_()) && t.chunkPos().equals((Object)event.getChunk().m_7697_())); - } - - @SubscribeEvent - public static void onBlockPlaced(BlockEvent.EntityPlaceEvent event) { - if (!ENABLED) { - return; - } - LevelAccessor levelAccessor = event.getLevel(); - if (!(levelAccessor instanceof ServerLevel)) { - return; - } - ServerLevel level = (ServerLevel)levelAccessor; - BlockPos pos = event.getPos(); - BlockState state = level.m_8055_(pos); - if (state.m_60713_(Blocks.f_50261_)) { - BlockIndexManager.register(level, pos, BlockType.LAMP); - } else if (state.m_60713_(Blocks.f_152588_)) { - BlockIndexManager.register(level, pos, BlockType.DRIPSTONE); - } else if (BlockIndexManager.isGlassBlock(state)) { - BlockIndexManager.register(level, pos, BlockType.GLASS); - } - } - - @SubscribeEvent - public static void onBlockBroken(BlockEvent.BreakEvent event) { - if (!ENABLED) { - return; - } - LevelAccessor levelAccessor = event.getLevel(); - if (!(levelAccessor instanceof ServerLevel)) { - return; - } - ServerLevel level = (ServerLevel)levelAccessor; - BlockPos pos = event.getPos(); - BlockIndexManager.unregister(level, pos, BlockType.LAMP); - BlockIndexManager.unregister(level, pos, BlockType.DRIPSTONE); - BlockIndexManager.unregister(level, pos, BlockType.GLASS); + return Collections.emptyList(); } public static boolean isPlayerAuthorized(ServerPlayer player) { - if (player == null) { - return false; - } - return player.hasPermissions(2) || isSingleplayer; + return true; } - @SubscribeEvent - public static void onPlayerJoinServer(PlayerEvent.PlayerLoggedInEvent event) { - if (!ENABLED) { - return; - } - if (BlockIndexManager.isChunkScanningDisabled()) { - return; - } - Player player = event.getEntity(); - if (!(player instanceof ServerPlayer)) { - return; - } - ServerPlayer player2 = (ServerPlayer)player; - if (BlockIndexManager.isPlayerAuthorized(player2)) { - ServerLevel level = player2.m_284548_(); - MinecraftServer server = level.m_7654_(); - boolean saveFileExists = BlockIndexManager.hasSaveFile(server); - if (isSingleplayer) { - if (!(waitingForUserInput || waitingForLoadDecision || scanningComplete)) { - chunkScanQueue.clear(); - totalChunksToScan = 0; - chunksScanned = 0; - } - if (!(waitingForUserInput || waitingForLoadDecision || BlockIndexManager.isScanning() || scanningComplete || userDeclinedScan)) { - pendingScanLevel = level; - if (saveFileExists) { - waitingForLoadDecision = true; - hasSaveFile = true; - try { - ScanLoadPromptPacket packet = new ScanLoadPromptPacket(true); - PacketHandler.sendToPlayer(player2, packet); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: showing load prompt for existing save file in world: {}", (Object)level.m_46472_().m_135782_()); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to send load prompt: {}", (Object)e.getMessage()); - } - } else { - waitingForUserInput = true; - hasSaveFile = false; - BlockIndexManager.sendScanPromptPacket(true); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: waiting for user input to start scan in world: {}", (Object)level.m_46472_().m_135782_()); - } - } else if (BlockIndexManager.isScanning() || !chunkScanQueue.isEmpty() && totalChunksToScan > 0) { - try { - ScanProgressPacket packet = new ScanProgressPacket(totalChunksToScan, chunksScanned, scanningComplete, lampsFound, dripstonesFound, glassBlocksFound); - PacketHandler.sendToPlayer(player2, packet); - ExplosionOverhaul.LOGGER.debug("Sent scan progress to rejoining OP player: {}/{} chunks", (Object)chunksScanned, (Object)totalChunksToScan); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to send scan progress to rejoining OP player: {}", (Object)e.getMessage()); - } - } - } else if (!serverScanDecisionMade && !userDeclinedScan) { - if (!serverScanPromptShown) { - serverScanPromptShown = true; - ExplosionOverhaul.LOGGER.info("BlockIndexManager: first OP joined server, waiting for scan decision from: {}", (Object)player2.m_7755_().getString()); - } else { - ExplosionOverhaul.LOGGER.info("BlockIndexManager: additional OP joined server, showing pending decision to: {}", (Object)player2.m_7755_().getString()); - } - pendingScanLevel = level; - if (saveFileExists) { - waitingForLoadDecision = true; - hasSaveFile = true; - try { - ScanLoadPromptPacket packet = new ScanLoadPromptPacket(true); - PacketHandler.sendToPlayer(player2, packet); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: showing load prompt for existing save file to OP: {}", (Object)player2.m_7755_().getString()); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to send load prompt: {}", (Object)e.getMessage()); - } - } else { - waitingForUserInput = true; - hasSaveFile = false; - try { - ScanPromptPacket packet = new ScanPromptPacket(true); - PacketHandler.sendToPlayer(player2, packet); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: showing scan prompt to OP: {}", (Object)player2.m_7755_().getString()); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to send scan prompt: {}", (Object)e.getMessage()); - } - } - } else if (totalChunksToScan > 0 && !scanningComplete) { - try { - ScanProgressPacket packet = new ScanProgressPacket(totalChunksToScan, chunksScanned, scanningComplete, lampsFound, dripstonesFound, glassBlocksFound); - PacketHandler.sendToPlayer(player2, packet); - ExplosionOverhaul.LOGGER.debug("Sent scan progress to joining OP player: {}/{} chunks", (Object)chunksScanned, (Object)totalChunksToScan); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to send scan progress to joining OP player: {}", (Object)e.getMessage()); - } - } - } - } - - @SubscribeEvent - public static void onServerTick(TickEvent.ServerTickEvent event) { - ScanTask task; - if (event.phase != TickEvent.Phase.END) { - return; - } - if (BlockIndexManager.isChunkScanningDisabled()) { - return; - } - if (userDeclinedScan) { - return; - } - if (!isSingleplayer && !serverScanDecisionMade) { - return; - } - int chunksToScan = BlockIndexManager.getChunksToScanPerTick(); - for (int processed = 0; processed < chunksToScan && (task = chunkScanQueue.poll()) != null; ++processed) { - MinecraftServer server = event.getServer(); - ServerLevel level = server.m_129880_(task.dim()); - if (level == null) continue; - try { - BlockIndexManager.scanChunk(level, task.chunkPos()); - long ck = BlockIndexManager.chunkKey(task.chunkPos()); - Set pending = BlockIndexManager.getOrCreatePendingSet(level); - pending.remove(ck); - continue; - } - catch (Exception ex) { - ExplosionOverhaul.LOGGER.warn("BlockIndexManager: error scanning chunk {} {}: {}", new Object[]{task.chunkPos().f_45578_, task.chunkPos().f_45579_, ex.toString()}); - } - } - } - - @SubscribeEvent - public static void onServerStarted(ServerStartedEvent event) { - currentServer = event.getServer(); - abortCurrentScan = false; - if (!ENABLED) { - return; - } - if (BlockIndexManager.isChunkScanningDisabled()) { - return; - } - if (INITIAL_SCAN_ENQUEUED) { - return; - } - MinecraftServer server = event.getServer(); - isSingleplayer = server.m_129792_(); - if (!isSingleplayer) { - userDeclinedScan = false; - } - serverScanPromptShown = false; - serverScanDecisionMade = false; - if (isSingleplayer) { - ExplosionOverhaul.LOGGER.info("BlockIndexManager: singleplayer detected, will scan on world entry"); - INITIAL_SCAN_ENQUEUED = true; - return; - } - ExplosionOverhaul.LOGGER.info("BlockIndexManager: multiplayer server detected, will wait for user decision before scanning"); - INITIAL_SCAN_ENQUEUED = true; - } - - private static void scanExistingChunksOnServer(MinecraftServer server) { - try { - int totalChunks; - chunksScanned = 0; - scanningComplete = false; - lampsFound = 0; - dripstonesFound = 0; - glassBlocksFound = 0; - chunkScanQueue.clear(); - pendingChunkKeys.clear(); - HyperScanner scanner = new HyperScanner(server); - totalChunksToScan = totalChunks = scanner.prepareTasks(); - INITIAL_SCAN_ENQUEUED = true; - BlockIndexManager.sendProgressUpdate(); - CompletableFuture.runAsync(() -> { - try { - scanner.run(); - chunksScanned = scanner.getProcessedChunks(); - lampsFound = scanner.getLampsFound(); - dripstonesFound = scanner.getDripstonesFound(); - glassBlocksFound = scanner.getGlassFound(); - scanningComplete = true; - server.execute(() -> { - BlockIndexManager.sendProgressUpdate(); - BlockIndexManager.saveIndexDataAfterScan(server); - ExplosionOverhaul.LOGGER.info("HyperScanner: background scan complete. Found {} lamps, {} dripstones, {} glass.", new Object[]{lampsFound, dripstonesFound, glassBlocksFound}); - }); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.error("HyperScanner: background scan failed", (Throwable)e); - } - }); - } - catch (Exception ex) { - ExplosionOverhaul.LOGGER.warn("BlockIndexManager: failed to start scan: {}", (Object)ex.toString()); - } - } - - @SubscribeEvent - public static void onServerStopped(ServerStoppedEvent event) { - if (!ENABLED) { - return; - } - abortCurrentScan = true; - if (!indexByDimension.isEmpty() && scanningComplete) { - try { - BlockIndexManager.saveIndexData(event.getServer()); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: saved data before server shutdown"); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("Failed to save data on server stop: {}", (Object)e.getMessage()); - } - } - userDeclinedScan = false; - serverScanPromptShown = false; - serverScanDecisionMade = false; - waitingForUserInput = false; - waitingForLoadDecision = false; - pendingScanLevel = null; - isRescanMode = false; - rescanRequestingPlayer = null; - hasSaveFile = false; - currentWorldId = null; - INITIAL_SCAN_ENQUEUED = false; - try { - ScanProgressPacket packet = new ScanProgressPacket(0, 0, true, 0, 0, 0); - PacketHandler.sendToAll(packet); - } - catch (Exception exception) { - // empty catch block - } - currentServer = null; - scanningComplete = false; - totalChunksToScan = 0; - chunksScanned = 0; - ExplosionOverhaul.LOGGER.info("BlockIndexManager: reset scan state and aborted background tasks on server stop"); - } - - @SubscribeEvent - public static void onPlayerLogout(PlayerEvent.PlayerLoggedOutEvent event) { - Player player; - if (!ENABLED) { - return; - } - if (isSingleplayer) { - abortCurrentScan = true; - waitingForUserInput = false; - waitingForLoadDecision = false; - pendingScanLevel = null; - userDeclinedScan = false; - hasSaveFile = false; - scanningComplete = false; - totalChunksToScan = 0; - chunksScanned = 0; - BlockIndexManager.clearAndSaveData(); - ExplosionOverhaul.LOGGER.info("BlockIndexManager: saved and cleared scan data on singleplayer logout"); - } - if ((player = event.getEntity()) instanceof ServerPlayer) { - ServerPlayer player2 = (ServerPlayer)player; - try { - ScanProgressPacket packet = new ScanProgressPacket(0, 0, true, 0, 0, 0); - PacketHandler.sendToPlayer(player2, packet); - } - catch (Exception exception) { - // empty catch block - } - } - } - - private static Path resolveRegionPath(ServerLevel lvl) { - try { - Path worldPath = lvl.m_7654_().m_129843_(LevelResource.f_78182_); - String dimPath = lvl.m_46472_().m_135782_().m_135815_(); - if ("overworld".equals(dimPath)) { - return worldPath.resolve("region"); - } - if ("the_nether".equals(dimPath)) { - return worldPath.resolve("DIM-1").resolve("region"); - } - if ("the_end".equals(dimPath)) { - return worldPath.resolve("DIM1").resolve("region"); - } - return worldPath.resolve("dimensions").resolve(lvl.m_46472_().m_135782_().m_135827_()).resolve(lvl.m_46472_().m_135782_().m_135815_()).resolve("region"); - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("HyperScanner: failed to resolve region path: {}", (Object)e.getMessage()); - return null; - } - } - - private static /* synthetic */ ServerPlayer lambda$loadExistingData$11(ServerPlayer serverPlayer) { - return serverPlayer; - } - - static { - indexByDimension = new ConcurrentHashMap, ConcurrentHashMap>>(); - chunkScanQueue = new ConcurrentLinkedQueue(); - pendingChunkKeys = new ConcurrentHashMap, Set>(); - ENABLED = true; - INITIAL_SCAN_ENQUEUED = false; - totalChunksToScan = 0; - chunksScanned = 0; - scanningComplete = false; - abortCurrentScan = false; - lampsFound = 0; - dripstonesFound = 0; - glassBlocksFound = 0; - lastScannedDimension = null; - waitingForUserInput = false; - pendingScanLevel = null; - currentScannedWorld = null; - isSingleplayer = false; - serverScanPromptShown = false; - serverScanDecisionMade = false; - isRescanMode = false; - rescanRequestingPlayer = null; - userDeclinedScan = false; - waitingForLoadDecision = false; - hasSaveFile = false; - currentWorldId = null; - DEFAULT_REINFORCED_GLASS_BLACKLIST = List.of("securitycraft:reinforced_white_stained_glass", "securitycraft:reinforced_orange_stained_glass", "securitycraft:reinforced_magenta_stained_glass", "securitycraft:reinforced_light_blue_stained_glass", "securitycraft:reinforced_yellow_stained_glass", "securitycraft:reinforced_lime_stained_glass", "securitycraft:reinforced_pink_stained_glass", "securitycraft:reinforced_gray_stained_glass", "securitycraft:reinforced_light_gray_stained_glass", "securitycraft:reinforced_cyan_stained_glass", "securitycraft:reinforced_purple_stained_glass", "securitycraft:reinforced_blue_stained_glass", "securitycraft:reinforced_brown_stained_glass", "securitycraft:reinforced_green_stained_glass", "securitycraft:reinforced_red_stained_glass", "securitycraft:reinforced_black_stained_glass", "securitycraft:reinforced_white_stained_glass_pane", "securitycraft:reinforced_orange_stained_glass_pane", "securitycraft:reinforced_magenta_stained_glass_pane", "securitycraft:reinforced_light_blue_stained_glass_pane", "securitycraft:reinforced_yellow_stained_glass_pane", "securitycraft:reinforced_lime_stained_glass_pane", "securitycraft:reinforced_pink_stained_glass_pane", "securitycraft:reinforced_gray_stained_glass_pane", "securitycraft:reinforced_light_gray_stained_glass_pane", "securitycraft:reinforced_cyan_stained_glass_pane", "securitycraft:reinforced_purple_stained_glass_pane", "securitycraft:reinforced_blue_stained_glass_pane", "securitycraft:reinforced_brown_stained_glass_pane", "securitycraft:reinforced_green_stained_glass_pane", "securitycraft:reinforced_red_stained_glass_pane", "securitycraft:reinforced_black_stained_glass_pane", "securitycraft:reinforced_glass", "securitycraft:reinforced_glass_pane", "create_tank_defenses:titanium_morning_reinforced_blast_glass", "mofus_better_end_:reinforced_glass", "crusty_chunks:reinforced_glass", "createnuclear:reinforced_glass", "mekanismgenerators:reactor_glass", "mekanism:structural_glass"); - MOD_CONFIG_DIRECTORY = Paths.get("config", "explosionoverhaul"); - GLASS_BLACKLIST_FILE = MOD_CONFIG_DIRECTORY.resolve("GlassBlacklist.json"); - GLASS_BLACKLIST = new CopyOnWriteArrayList(DEFAULT_REINFORCED_GLASS_BLACKLIST); - GLASS_BLACKLIST_LOOKUP = new AtomicReference>(new HashSet(DEFAULT_REINFORCED_GLASS_BLACKLIST)); - BlockIndexManager.loadGlassBlacklistFromJson(); - } - - private record ScanTask(ResourceKey dim, ChunkPos chunkPos) { - } - - public static enum BlockType { + public enum BlockType { LAMP, DRIPSTONE, - GLASS; - - } - - private static class HyperScanner { - private static final int SECTOR_BYTES = 4096; - private final MinecraftServer server; - private final ConcurrentLinkedQueue tasks = new ConcurrentLinkedQueue(); - private final AtomicInteger processedChunks = new AtomicInteger(); - private final LongAdder lamps = new LongAdder(); - private final LongAdder drips = new LongAdder(); - private final LongAdder glass = new LongAdder(); - private final int workerCount; - - HyperScanner(MinecraftServer server) { - this.server = server; - this.workerCount = this.resolveWorkerCount(); - } - - int prepareTasks() { - int total = 0; - for (ServerLevel level : this.server.m_129785_()) { - Path regionPath = BlockIndexManager.resolveRegionPath(level); - if (regionPath == null || !Files.exists(regionPath, new LinkOption[0])) { - ExplosionOverhaul.LOGGER.info("HyperScanner: region path not found for {}", (Object)level.m_46472_().m_135782_()); - continue; - } - try { - Stream regionFiles = Files.list(regionPath); - try { - for (Path regionFile : regionFiles.filter(p -> p.toString().endsWith(".mca")).toList()) { - RegionInfo info = this.parseRegion(regionFile); - if (info == null || info.chunkCount <= 0) continue; - this.tasks.add(new RegionTask(level, regionFile, info.regionX, info.regionZ)); - total += info.chunkCount; - } - } - finally { - if (regionFiles == null) continue; - regionFiles.close(); - } - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("HyperScanner: failed to enumerate region files in {}: {}", (Object)regionPath, (Object)e.getMessage()); - } - } - ExplosionOverhaul.LOGGER.info("HyperScanner: prepared {} region tasks, total chunks {}", (Object)this.tasks.size(), (Object)total); - return total; - } - - void run() { - if (this.tasks.isEmpty()) { - ExplosionOverhaul.LOGGER.info("HyperScanner: no tasks to run"); - return; - } - ExecutorService pool = Executors.newFixedThreadPool(this.workerCount, r -> { - Thread t = new Thread(r, "EO-HyperScanner"); - t.setDaemon(true); - return t; - }); - for (int i = 0; i < this.workerCount; ++i) { - pool.execute(this::workerLoop); - } - pool.shutdown(); - try { - while (!pool.isTerminated()) { - pool.awaitTermination(1L, TimeUnit.SECONDS); - } - } - catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - } - } - - int getProcessedChunks() { - return this.processedChunks.get(); - } - - int getLampsFound() { - return this.lamps.intValue(); - } - - int getDripstonesFound() { - return this.drips.intValue(); - } - - int getGlassFound() { - return this.glass.intValue(); - } - - private void workerLoop() { - RegionTask task; - while (!abortCurrentScan && (task = this.tasks.poll()) != null) { - this.scanRegion(task); - } - } - - private void scanRegion(RegionTask task) { - try (RandomAccessFile raf = new RandomAccessFile(task.file().toFile(), "r");){ - byte[] header = new byte[4096]; - int read = raf.read(header); - if (read < 4096) { - return; - } - for (int i = 0; i < 1024; ++i) { - if (abortCurrentScan) { - return; - } - int offsetIndex = i * 4; - int chunkOffset = (header[offsetIndex] & 0xFF) << 16 | (header[offsetIndex + 1] & 0xFF) << 8 | header[offsetIndex + 2] & 0xFF; - int sectorCount = header[offsetIndex + 3] & 0xFF; - if (chunkOffset == 0 || sectorCount == 0) continue; - int localX = i % 32; - int localZ = i / 32; - int chunkX = task.regionX() * 32 + localX; - int chunkZ = task.regionZ() * 32 + localZ; - try { - this.processChunk(raf, chunkOffset, sectorCount, new ChunkPos(chunkX, chunkZ), task.level()); - continue; - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("HyperScanner: failed to process chunk {} {} in {}: {}", new Object[]{chunkX, chunkZ, task.file().getFileName(), e.getMessage()}); - } - } - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("HyperScanner: failed to scan region {}: {}", (Object)task.file().getFileName(), (Object)e.getMessage()); - } - } - - private void processChunk(RandomAccessFile raf, int chunkOffsetSectors, int sectorCount, ChunkPos chunkPos, ServerLevel level) throws IOException { - InflaterInputStream in; - long filePos = (long)chunkOffsetSectors * 4096L; - raf.seek(filePos); - int length = raf.readInt(); - if (length <= 0 || length > sectorCount * 4096) { - return; - } - int compressionType = raf.readUnsignedByte(); - byte[] data = new byte[length - 1]; - raf.readFully(data); - ByteArrayInputStream base = new ByteArrayInputStream(data); - if (compressionType == 2) { - in = new InflaterInputStream(base); - } else if (compressionType == 1) { - in = new GZIPInputStream(base); - } else { - return; - } - CompoundTag root = NbtIo.m_128928_((DataInput)new DataInputStream(in)); - if (root == null) { - return; - } - CompoundTag levelTag = root.m_128425_("Level", 10) ? root.m_128469_("Level") : (root.m_128425_("level", 10) ? root.m_128469_("level") : root); - ListTag sections = levelTag.m_128437_("sections", 10); - HashSet found = new HashSet(); - for (int i = 0; i < sections.size(); ++i) { - CompoundTag section = sections.m_128728_(i); - this.processSection(section, chunkPos, level, found); - } - if (!found.isEmpty()) { - ConcurrentHashMap> dimIndex = BlockIndexManager.getOrCreateDimIndex(level); - dimIndex.put(BlockIndexManager.chunkKey(chunkPos), found); - } - if (abortCurrentScan) { - return; - } - int processed = this.processedChunks.incrementAndGet(); - this.maybeSendProgress(processed); - } - - private void processSection(CompoundTag section, ChunkPos chunkPos, ServerLevel level, Set out) { - if (!section.m_128425_("block_states", 10)) { - return; - } - CompoundTag blockStatesTag = section.m_128469_("block_states"); - if (blockStatesTag.m_128425_("palette", 9)) { - ListTag palette = blockStatesTag.m_128437_("palette", 10); - boolean hasInterestingBlock = false; - for (int i = 0; i < palette.size(); ++i) { - String name = palette.m_128728_(i).m_128461_("Name"); - if (!name.equals("minecraft:redstone_lamp") && !name.equals("minecraft:pointed_dripstone") && (!name.contains("glass") || BlockIndexManager.isGlassProtected(name))) continue; - hasInterestingBlock = true; - break; - } - if (!hasInterestingBlock) { - return; - } - } - try { - DataResult result = PalettedContainer.m_238371_((IdMap)Block.f_49791_, (Codec)BlockState.f_61039_, (PalettedContainer.Strategy)PalettedContainer.Strategy.f_188137_, (Object)Blocks.f_50016_.m_49966_()).parse((DynamicOps)NbtOps.f_128958_, (Object)blockStatesTag); - result.resultOrPartial(err -> {}).ifPresent(container -> { - byte sectionY = section.m_128445_("Y"); - int baseY = sectionY * 16; - if (baseY < level.m_141937_() || baseY >= level.m_151558_()) { - return; - } - IdentityHashMap stateTypeCache = new IdentityHashMap(); - for (int y = 0; y < 16; ++y) { - int worldY = baseY + y; - if (worldY < level.m_141937_() || worldY >= level.m_151558_()) continue; - for (int z = 0; z < 16; ++z) { - for (int x = 0; x < 16; ++x) { - BlockState state = (BlockState)container.m_63087_(x, y, z); - Byte type = (Byte)stateTypeCache.get(state); - if (type == null) { - type = state.m_60713_(Blocks.f_50261_) ? Byte.valueOf((byte)1) : (state.m_60713_(Blocks.f_152588_) ? Byte.valueOf((byte)2) : (BlockIndexManager.isGlassBlock(state) ? Byte.valueOf((byte)3) : Byte.valueOf((byte)0))); - stateTypeCache.put(state, type); - } - if (type == 0) continue; - int worldX = chunkPos.m_45604_() + x; - int worldZ = chunkPos.m_45605_() + z; - out.add(BlockPos.m_121882_((int)worldX, (int)worldY, (int)worldZ)); - if (type == 1) { - this.lamps.increment(); - continue; - } - if (type == 2) { - this.drips.increment(); - continue; - } - if (type != 3) continue; - this.glass.increment(); - } - } - } - }); - } - catch (Exception exception) { - // empty catch block - } - } - - private void maybeSendProgress(int processed) { - if (processed % 50 == 0 || processed == totalChunksToScan) { - int l = this.lamps.intValue(); - int d = this.drips.intValue(); - int g = this.glass.intValue(); - this.server.execute(() -> BlockIndexManager.sendMultiThreadProgressUpdate(processed, l, d, g)); - } - } - - private RegionInfo parseRegion(Path regionFile) { - int regionZ; - int regionX; - String fileName = regionFile.getFileName().toString(); - if (!fileName.startsWith("r.") || !fileName.endsWith(".mca")) { - return null; - } - String[] parts = fileName.substring(2, fileName.length() - 4).split("\\."); - if (parts.length != 2) { - return null; - } - try { - regionX = Integer.parseInt(parts[0]); - regionZ = Integer.parseInt(parts[1]); - } - catch (NumberFormatException nfe) { - return null; - } - int chunkCount = this.countChunksInRegion(regionFile); - return new RegionInfo(regionX, regionZ, chunkCount); - } - - /* - * Enabled aggressive block sorting - * Enabled unnecessary exception pruning - * Enabled aggressive exception aggregation - */ - private int countChunksInRegion(Path regionFile) { - int count = 0; - try (RandomAccessFile raf = new RandomAccessFile(regionFile.toFile(), "r");){ - byte[] header = new byte[4096]; - int read = raf.read(header); - if (read < 4096) { - int n = 0; - return n; - } - int i = 0; - while (i < 1024) { - int offset = i * 4; - int chunkOffset = (header[offset] & 0xFF) << 16 | (header[offset + 1] & 0xFF) << 8 | header[offset + 2] & 0xFF; - int sectorCount = header[offset + 3] & 0xFF; - if (chunkOffset > 0 && sectorCount > 0) { - ++count; - } - ++i; - } - return count; - } - catch (Exception e) { - ExplosionOverhaul.LOGGER.warn("HyperScanner: failed to read region header {}: {}", (Object)regionFile.getFileName(), (Object)e.getMessage()); - } - return count; - } - - private int resolveWorkerCount() { - int configured = (Integer)Config.COMMON.scan.maxScanThreads.get(); - int cores = Runtime.getRuntime().availableProcessors(); - if (configured <= 0) { - return Math.max(1, cores); - } - return Math.max(1, Math.min(configured, cores)); - } - } - - private record RegionInfo(int regionX, int regionZ, int chunkCount) { - } - - private record RegionTask(ServerLevel level, Path file, int regionX, int regionZ) { + GLASS } } diff --git a/src/main/java/com/vinlanx/explosionoverhaul/Config.java b/src/main/java/com/vinlanx/explosionoverhaul/Config.java index d0f3dad..3c2560c 100644 --- a/src/main/java/com/vinlanx/explosionoverhaul/Config.java +++ b/src/main/java/com/vinlanx/explosionoverhaul/Config.java @@ -25,7 +25,7 @@ public class Config { try { Boolean fileVal = Config.readFirstLaunchFromFile(); if (fileVal != null && fileVal.booleanValue()) { - Config.CLIENT.firstLaunchComplete.set((Object)true); + Config.CLIENT.firstLaunchComplete.set(true); return false; } } @@ -36,7 +36,7 @@ public class Config { } public static void markFirstLaunchComplete() { - Config.CLIENT.firstLaunchComplete.set((Object)true); + Config.CLIENT.firstLaunchComplete.set(true); CLIENT_SPEC.save(); } diff --git a/src/main/java/com/vinlanx/explosionoverhaul/client/AnimationSoundManager.java b/src/main/java/com/vinlanx/explosionoverhaul/client/AnimationSoundManager.java index 7046286..dde2d31 100644 --- a/src/main/java/com/vinlanx/explosionoverhaul/client/AnimationSoundManager.java +++ b/src/main/java/com/vinlanx/explosionoverhaul/client/AnimationSoundManager.java @@ -1,101 +1,18 @@ -/* - * Decompiled with CFR 0.152. - */ package com.vinlanx.explosionoverhaul.client; -import com.vinlanx.explosionoverhaul.ModSounds; -import java.util.ArrayList; -import java.util.List; -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.sounds.SimpleSoundInstance; -import net.minecraft.client.resources.sounds.SoundInstance; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.util.RandomSource; -import net.neoforged.neoforge.registries.DeferredHolder; - public class AnimationSoundManager { - private static final RandomSource RANDOM = RandomSource.m_216327_(); - private static final List> ANIMATION_SOUNDS = new ArrayList>(); - private static final List> FAR_POWER_2_SOUNDS = new ArrayList>(); - private static final List> FAR_POWER_3_SOUNDS = new ArrayList>(); - private static final List> MEDIUM_CAVE_POWER_4_SOUNDS = new ArrayList>(); - private static final List> SUPERFAR_POWER_4_SOUNDS = new ArrayList>(); - private static int lastAnimationSoundIndex = -1; - private static int lastFarPower2SoundIndex = -1; - private static int lastFarPower3SoundIndex = -1; - private static int lastMediumCavePower4SoundIndex = -1; - private static int lastSuperfar4SoundIndex = -1; - - private static int getNextRandomIndex(List list, int lastIndex) { - int nextIndex; - if (list.size() <= 1) { - return 0; - } - while ((nextIndex = RANDOM.m_188503_(list.size())) == lastIndex) { - } - return nextIndex; - } - public static void playRandomAnimationSound() { - if (ANIMATION_SOUNDS.isEmpty()) { - return; - } - lastAnimationSoundIndex = AnimationSoundManager.getNextRandomIndex(ANIMATION_SOUNDS, lastAnimationSoundIndex); - SoundEvent sound = (SoundEvent)ANIMATION_SOUNDS.get(lastAnimationSoundIndex).get(); - Minecraft.getInstance().m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119752_((SoundEvent)sound, (float)1.0f)); } public static void playRandomFarPower2Sound() { - if (FAR_POWER_2_SOUNDS.isEmpty()) { - return; - } - lastFarPower2SoundIndex = AnimationSoundManager.getNextRandomIndex(FAR_POWER_2_SOUNDS, lastFarPower2SoundIndex); - SoundEvent sound = (SoundEvent)FAR_POWER_2_SOUNDS.get(lastFarPower2SoundIndex).get(); - Minecraft.getInstance().m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119752_((SoundEvent)sound, (float)1.0f)); } public static void playRandomFarPower3Sound() { - if (FAR_POWER_3_SOUNDS.isEmpty()) { - return; - } - lastFarPower3SoundIndex = AnimationSoundManager.getNextRandomIndex(FAR_POWER_3_SOUNDS, lastFarPower3SoundIndex); - SoundEvent sound = (SoundEvent)FAR_POWER_3_SOUNDS.get(lastFarPower3SoundIndex).get(); - Minecraft.getInstance().m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119752_((SoundEvent)sound, (float)1.0f)); } public static void playRandomMediumCavePower4Sound() { - if (MEDIUM_CAVE_POWER_4_SOUNDS.isEmpty()) { - return; - } - lastMediumCavePower4SoundIndex = AnimationSoundManager.getNextRandomIndex(MEDIUM_CAVE_POWER_4_SOUNDS, lastMediumCavePower4SoundIndex); - SoundEvent sound = (SoundEvent)MEDIUM_CAVE_POWER_4_SOUNDS.get(lastMediumCavePower4SoundIndex).get(); - Minecraft.getInstance().m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119752_((SoundEvent)sound, (float)1.0f)); } public static void playRandomSuperfar4Sound() { - if (SUPERFAR_POWER_4_SOUNDS.isEmpty()) { - return; - } - lastSuperfar4SoundIndex = AnimationSoundManager.getNextRandomIndex(SUPERFAR_POWER_4_SOUNDS, lastSuperfar4SoundIndex); - SoundEvent sound = (SoundEvent)SUPERFAR_POWER_4_SOUNDS.get(lastSuperfar4SoundIndex).get(); - Minecraft.getInstance().m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119752_((SoundEvent)sound, (float)1.0f)); - } - - static { - ANIMATION_SOUNDS.add(ModSounds.EXPLODE_SUPERFAR_POWER_2_1); - ANIMATION_SOUNDS.add(ModSounds.EXPLODE_SUPERFAR_POWER_2_2); - ANIMATION_SOUNDS.add(ModSounds.EXPLODE_SUPERFAR_POWER_3_1); - FAR_POWER_2_SOUNDS.add(ModSounds.EXPLODE_FAR_POWER_2_1); - FAR_POWER_2_SOUNDS.add(ModSounds.EXPLODE_FAR_POWER_2_2); - FAR_POWER_2_SOUNDS.add(ModSounds.EXPLODE_FAR_POWER_2_3); - FAR_POWER_3_SOUNDS.add(ModSounds.EXPLODE_FAR_POWER_3_1); - FAR_POWER_3_SOUNDS.add(ModSounds.EXPLODE_FAR_POWER_3_2); - FAR_POWER_3_SOUNDS.add(ModSounds.EXPLODE_FAR_POWER_3_3); - MEDIUM_CAVE_POWER_4_SOUNDS.add(ModSounds.EXPLODE_MEDIUM_CAVE_POWER_4_1); - MEDIUM_CAVE_POWER_4_SOUNDS.add(ModSounds.EXPLODE_MEDIUM_CAVE_POWER_4_2); - MEDIUM_CAVE_POWER_4_SOUNDS.add(ModSounds.EXPLODE_MEDIUM_CAVE_POWER_4_3); - SUPERFAR_POWER_4_SOUNDS.add(ModSounds.EXPLODE_SUPERFAR_POWER_4_1); - SUPERFAR_POWER_4_SOUNDS.add(ModSounds.EXPLODE_SUPERFAR_POWER_4_2); - SUPERFAR_POWER_4_SOUNDS.add(ModSounds.EXPLODE_SUPERFAR_POWER_4_3); } } diff --git a/src/main/java/com/vinlanx/explosionoverhaul/client/FirstTimeSetupHandler.java b/src/main/java/com/vinlanx/explosionoverhaul/client/FirstTimeSetupHandler.java index 51dfe21..6a3d26b 100644 --- a/src/main/java/com/vinlanx/explosionoverhaul/client/FirstTimeSetupHandler.java +++ b/src/main/java/com/vinlanx/explosionoverhaul/client/FirstTimeSetupHandler.java @@ -22,25 +22,6 @@ public class FirstTimeSetupHandler { @SubscribeEvent public static void onClientTick(TickEvent.ClientTickEvent event) { - if (event.phase != TickEvent.Phase.END) { - return; - } - Minecraft mc = Minecraft.getInstance(); - if (!hasChecked && mc.screen instanceof TitleScreen) { - hasChecked = true; - ExplosionOverhaul.LOGGER.info("Detected TitleScreen on client, hasChecked=true"); - if (Config.isFirstLaunch()) { - pendingShowIntro = true; - } - } - if (!pendingShowIntro) { - return; - } - if (mc.screen instanceof TitleScreen) { - pendingShowIntro = false; - ExplosionOverhaul.LOGGER.info("Showing IntroSplashScreen (first launch)"); - mc.m_91152_((Screen)new IntroSplashScreen()); - } } static { diff --git a/src/main/java/com/vinlanx/explosionoverhaul/client/SmokeParticle.java b/src/main/java/com/vinlanx/explosionoverhaul/client/SmokeParticle.java index dc20d4f..06ac5a9 100644 --- a/src/main/java/com/vinlanx/explosionoverhaul/client/SmokeParticle.java +++ b/src/main/java/com/vinlanx/explosionoverhaul/client/SmokeParticle.java @@ -1,95 +1,40 @@ -/* - * Decompiled with CFR 0.152. - */ package com.vinlanx.explosionoverhaul.client; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.VertexConsumer; import com.vinlanx.explosionoverhaul.SmokeParticleOptions; -import com.vinlanx.explosionoverhaul.client.ExplosionWindController; -import net.minecraft.client.Camera; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.particle.Particle; import net.minecraft.client.particle.ParticleProvider; import net.minecraft.client.particle.ParticleRenderType; import net.minecraft.client.particle.SpriteSet; import net.minecraft.client.particle.TextureSheetParticle; -import net.minecraft.world.phys.Vec3; -public class SmokeParticle -extends TextureSheetParticle { - private final float initialAlpha; - private final boolean isHeavy; - private final float windSpeed; - private final float heightPercent; - - protected SmokeParticle(ClientLevel pLevel, double pX, double pY, double pZ, double pXSpeed, double pYSpeed, double pZSpeed, SmokeParticleOptions options, SpriteSet spriteSet) { - super(pLevel, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed); - this.f_172258_ = 0.96f; - this.f_107226_ = 0.0f; - this.f_107225_ = options.getLifetime(); - this.f_107663_ = options.getScale(); - this.f_107227_ = options.getRed(); - this.f_107228_ = options.getGreen(); - this.f_107229_ = options.getBlue(); - this.f_107230_ = options.getAlpha(); - this.initialAlpha = options.getAlpha(); - this.isHeavy = options.isHeavy(); - this.windSpeed = options.getWindSpeed(); - this.heightPercent = options.getHeightPercent(); - this.m_108337_(spriteSet.m_213979_(this.f_107223_)); +public class SmokeParticle extends TextureSheetParticle { + protected SmokeParticle(ClientLevel level, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed, SmokeParticleOptions options, SpriteSet sprites) { + super(level, x, y, z, xSpeed, ySpeed, zSpeed); + this.lifetime = 1; + this.pickSprite(sprites); } - public void m_5744_(VertexConsumer pBuffer, Camera pRenderInfo, float pPartialTicks) { - RenderSystem.depthMask((this.f_107230_ > 0.3f ? 1 : 0) != 0); - super.m_5744_(pBuffer, pRenderInfo, pPartialTicks); - RenderSystem.depthMask((boolean)true); - } - - public void m_5989_() { - Vec3 direction; - this.f_107209_ = this.f_107212_; - this.f_107210_ = this.f_107213_; - this.f_107211_ = this.f_107214_; - if (this.f_107224_++ >= this.f_107225_) { - this.m_107274_(); - return; - } - if (this.isHeavy) { - this.f_107216_ = -0.04; - } - this.m_6257_(this.f_107215_, this.f_107216_, this.f_107217_); - this.f_107215_ *= (double)this.f_172258_; - this.f_107216_ *= (double)this.f_172258_; - this.f_107217_ *= (double)this.f_172258_; - if (this.windSpeed > 0.0f && (direction = ExplosionWindController.getWindDirection()) != Vec3.f_82478_) { - double targetX = direction.f_82479_ * (double)this.windSpeed; - double targetZ = direction.f_82481_ * (double)this.windSpeed; - this.f_107215_ += (targetX - this.f_107215_) * 0.12; - this.f_107217_ += (targetZ - this.f_107217_) * 0.12; - } - float lifeProgress = (float)this.f_107224_ / (float)this.f_107225_; - this.f_107230_ = this.initialAlpha * (1.0f - lifeProgress); + @Override + public ParticleRenderType getRenderType() { + return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; } + @Override public boolean shouldCull() { return false; } - public ParticleRenderType m_7556_() { - return ParticleRenderType.f_107431_; - } - - public static class Provider - implements ParticleProvider { + public static class Provider implements ParticleProvider { private final SpriteSet sprites; - public Provider(SpriteSet pSprites) { - this.sprites = pSprites; + public Provider(SpriteSet sprites) { + this.sprites = sprites; } - public Particle createParticle(SmokeParticleOptions options, ClientLevel pLevel, double pX, double pY, double pZ, double pXSpeed, double pYSpeed, double pZSpeed) { - return new SmokeParticle(pLevel, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed, options, this.sprites); + @Override + public Particle createParticle(SmokeParticleOptions options, ClientLevel level, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + return new SmokeParticle(level, x, y, z, xSpeed, ySpeed, zSpeed, options, this.sprites); } } }