/* * Copyright (C) 2022 NotEnoughUpdates contributors * * This file is part of NotEnoughUpdates. * * NotEnoughUpdates is free software: you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 3 of the License, or (at your option) any later version. * * NotEnoughUpdates is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with NotEnoughUpdates. If not, see . */ package io.github.moulberry.notenoughupdates.miscfeatures.customblockzones; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.init.Blocks; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.BlockPos; import net.minecraft.util.EnumFacing; import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; import net.minecraft.util.Vec3; import net.minecraft.world.ChunkCoordIntPair; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import static io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes.isMithril; import static io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes.isTitanium; @NEUAutoSubscribe public class DwarvenMinesTextures implements IslandZoneSubdivider { private static class IgnoreColumn { boolean always; int minY; int maxY; public IgnoreColumn(boolean always, int minY, int maxY) { this.always = always; this.minY = minY; this.maxY = maxY; } } private Set ignoredChunks = null; private final Map> loadedChunkData = new HashMap<>(); private boolean error = false; private IBlockState getBlock(BlockPos pos) { return Minecraft.getMinecraft().theWorld.getBlockState(pos); } private boolean isDoubleSlab(IBlockState state) { return state.getBlock() == Blocks.double_stone_slab; } private Reader getUTF8Resource(ResourceLocation location) throws IOException { return new BufferedReader(new InputStreamReader(Minecraft .getMinecraft() .getResourceManager() .getResource(location) .getInputStream(), StandardCharsets.UTF_8)); } private void loadIgnoredChunks() { ignoredChunks = new HashSet<>(); try (Reader reader = getUTF8Resource(new ResourceLocation("notenoughupdates:dwarven_data/all.json"))) { JsonObject json = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, JsonObject.class); for (Map.Entry entry : json.entrySet()) { String coord = entry.getKey(); String[] split = coord.split("_"); int left = Integer.parseInt(split[0]); int right = Integer.parseInt(split[1]); ignoredChunks.add(new ChunkCoordIntPair(left, right)); } } catch (IOException e) { ignoredChunks = null; error = true; System.out.println("NEU failed to load dwarven mines ignore chunks: "); e.printStackTrace(); } } private Set getIgnoredChunks() { if (ignoredChunks == null) synchronized (this) { if (ignoredChunks != null) return ignoredChunks; loadIgnoredChunks(); } return ignoredChunks; } private IgnoreColumn parseIgnoreColumn(JsonElement element) { if (element.isJsonPrimitive()) { JsonPrimitive prim = element.getAsJsonPrimitive(); if (prim.isBoolean()) { return new IgnoreColumn(true, 0, 0); } else if (prim.isNumber()) { int y = prim.getAsInt(); return new IgnoreColumn(false, y, y); } } if (element.isJsonArray()) { JsonArray arr = element.getAsJsonArray(); if (arr.size() == 2) { int min = arr.get(0).getAsInt(); int max = arr.get(1).getAsInt(); return new IgnoreColumn(false, min, max); } } return null; } private Map loadChunkData(ChunkCoordIntPair pair) { Map map = new HashMap<>(); try { ResourceLocation loc = new ResourceLocation("notenoughupdates:dwarven_data/" + pair.chunkXPos + "_" + pair.chunkZPos + ".json"); try (Reader reader = getUTF8Resource(loc)) { JsonObject json = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, JsonObject.class); for (Map.Entry entry : json.entrySet()) { String coord = entry.getKey(); String[] split = coord.split(":"); int left = Integer.parseInt(split[0]); int right = Integer.parseInt(split[1]); IgnoreColumn ignore = parseIgnoreColumn(entry.getValue()); if (ignore != null) { ChunkCoordIntPair offset = new ChunkCoordIntPair(left, right); map.put(offset, ignore); } } } } catch (Exception e) { } return map; } private Map getChunkData(ChunkCoordIntPair chunkCoordinates) { synchronized (this) { return loadedChunkData.computeIfAbsent(chunkCoordinates, this::loadChunkData); } } // Tunnels coords // 130 -50 185 // -130 180 480 @Override public SpecialBlockZone getSpecialZoneForBlock(String location, BlockPos pos) { AxisAlignedBB axisAlignedBB = new AxisAlignedBB(130, -50, 185, -130, 180, 480); if (axisAlignedBB.isVecInside(new Vec3(pos))) return SpecialBlockZone.GLACITE_TUNNELS; if (error) return null; IBlockState block = getBlock(pos); boolean isTitanium = isTitanium(block); boolean isMithril = isMithril(block); if (isTitanium) { for (EnumFacing direction : EnumFacing.values()) if (isDoubleSlab(getBlock(pos.offset(direction)))) return SpecialBlockZone.DWARVEN_MINES_NON_MITHRIL; } if (!isMithril && !isTitanium) return SpecialBlockZone.DWARVEN_MINES_NON_MITHRIL; Set ignoredChunks = getIgnoredChunks(); if (ignoredChunks == null) return null; ChunkCoordIntPair pair = new ChunkCoordIntPair( MathHelper.floor_float(pos.getX() / 16f), MathHelper.floor_float(pos.getZ() / 16f) ); if (ignoredChunks.contains(pair)) { return SpecialBlockZone.DWARVEN_MINES_NON_MITHRIL; } if (isTitanium) { return SpecialBlockZone.DWARVEN_MINES_MITHRIL; } Map chunkData = getChunkData(pair); if (chunkData == null || error) return null; int modX = pos.getX() % 16; int modZ = pos.getZ() % 16; if (modX < 0) modX += 16; if (modZ < 0) modZ += 16; ChunkCoordIntPair subChunkCoordinates = new ChunkCoordIntPair(modX, modZ); IgnoreColumn ignore = chunkData.get(subChunkCoordinates); if (ignore != null) { if (ignore.always) { return SpecialBlockZone.DWARVEN_MINES_NON_MITHRIL; } int y = pos.getY(); if (ignore.minY <= y && y <= ignore.maxY) { return SpecialBlockZone.DWARVEN_MINES_NON_MITHRIL; } } return SpecialBlockZone.DWARVEN_MINES_MITHRIL; } }