Merge pull request #2513 from MellowArpeggiation/master

fix crash in Highlands mod due to it using a deprecated biome hook
This commit is contained in:
HbmMods 2025-10-31 09:07:59 +01:00 committed by GitHub
commit a3fbb711f0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 192 additions and 143 deletions

View File

@ -4,11 +4,17 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.hbm.blocks.ModBlocks; import com.hbm.blocks.ModBlocks;
import com.hbm.inventory.material.NTMMaterial;
import com.hbm.inventory.material.Mats.MaterialStack; import com.hbm.inventory.material.Mats.MaterialStack;
import com.hbm.items.machine.ItemScraps; import com.hbm.items.machine.ItemScraps;
import com.hbm.lib.Library; import com.hbm.lib.Library;
import com.hbm.lib.RefStrings; import com.hbm.lib.RefStrings;
import com.hbm.tileentity.machine.TileEntityFoundryChannel; import com.hbm.tileentity.machine.TileEntityFoundryChannel;
import com.hbm.uninos.GenNode;
import com.hbm.uninos.INetworkProvider;
import com.hbm.uninos.networkproviders.FoundryNetwork;
import com.hbm.util.fauxpointtwelve.BlockPos;
import com.hbm.util.fauxpointtwelve.DirPos;
import api.hbm.block.ICrucibleAcceptor; import api.hbm.block.ICrucibleAcceptor;
import cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.client.registry.RenderingRegistry;
@ -176,7 +182,6 @@ public class FoundryChannel extends BlockContainer implements ICrucibleAcceptor
} }
cast.amount = 0; cast.amount = 0;
cast.type = null; cast.type = null;
cast.propagateMaterial(null);
cast.markDirty(); cast.markDirty();
world.markBlockForUpdate(x, y, z); world.markBlockForUpdate(x, y, z);
} }
@ -199,4 +204,21 @@ public class FoundryChannel extends BlockContainer implements ICrucibleAcceptor
super.breakBlock(world, x, y, z, b, i); super.breakBlock(world, x, y, z, b, i);
} }
public static class FoundryNode extends GenNode<FoundryNetwork> {
public NTMMaterial type;
public FoundryNode(INetworkProvider<FoundryNetwork> provider, BlockPos... positions) {
super(provider, positions);
}
@Override
public FoundryNode setConnections(DirPos... connections) {
super.setConnections(connections);
return this;
}
}
} }

View File

@ -21,6 +21,7 @@ import com.hbm.util.WeightedRandomGeneric;
import com.hbm.world.dungeon.*; import com.hbm.world.dungeon.*;
import com.hbm.world.feature.*; import com.hbm.world.feature.*;
import com.hbm.world.feature.BedrockOre.BedrockOreDefinition; import com.hbm.world.feature.BedrockOre.BedrockOreDefinition;
import com.hbm.world.gen.MapGenChainloader;
import com.hbm.world.generator.CellularDungeonFactory; import com.hbm.world.generator.CellularDungeonFactory;
import com.hbm.world.generator.DungeonToolbox; import com.hbm.world.generator.DungeonToolbox;
import cpw.mods.fml.common.IWorldGenerator; import cpw.mods.fml.common.IWorldGenerator;
@ -40,6 +41,11 @@ public class HbmWorldGen implements IWorldGenerator {
@Override @Override
public void generate(Random rand, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { public void generate(Random rand, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) {
// quick fix for bad generators
if(world.provider.dimensionId == 0) {
MapGenChainloader.repairBadGeneration(world, chunkX, chunkZ);
}
switch (world.provider.dimensionId) { switch (world.provider.dimensionId) {
case -1: case -1:
generateNether(world, rand, chunkX * 16, chunkZ * 16); break; generateNether(world, rand, chunkX * 16, chunkZ * 16); break;

View File

@ -5,10 +5,14 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import com.hbm.blocks.ModBlocks; import com.hbm.blocks.ModBlocks;
import com.hbm.blocks.machine.FoundryChannel.FoundryNode;
import com.hbm.inventory.material.MaterialShapes; import com.hbm.inventory.material.MaterialShapes;
import com.hbm.inventory.material.Mats;
import com.hbm.inventory.material.Mats.MaterialStack; import com.hbm.inventory.material.Mats.MaterialStack;
import com.hbm.inventory.material.NTMMaterial; import com.hbm.lib.Library;
import com.hbm.uninos.UniNodespace;
import com.hbm.uninos.networkproviders.FoundryNetworkProvider;
import com.hbm.util.fauxpointtwelve.BlockPos;
import com.hbm.util.fauxpointtwelve.DirPos;
import api.hbm.block.ICrucibleAcceptor; import api.hbm.block.ICrucibleAcceptor;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -22,22 +26,16 @@ public class TileEntityFoundryChannel extends TileEntityFoundryBase {
public int nextUpdate; public int nextUpdate;
public int lastFlow = 0; public int lastFlow = 0;
protected NTMMaterial neighborType; protected FoundryNode node;
protected boolean hasCheckedNeighbors;
protected int unpropagateTime;
@Override @Override
public void updateEntity() { public void updateEntity() {
if(!worldObj.isRemote) { if(!worldObj.isRemote) {
initNode();
// Initialise before allowing pours, so newly added channels will avoid causing clog feeds if(this.node.type != null && this.amount == 0) {
if(!hasCheckedNeighbors) { this.node.type = null;
List<TileEntityFoundryChannel> visited = new ArrayList<TileEntityFoundryChannel>();
visited.add(this);
neighborType = checkNeighbors(visited);
hasCheckedNeighbors = true;
} }
if(this.type == null && this.amount != 0) { if(this.type == null && this.amount != 0) {
@ -71,7 +69,7 @@ public class TileEntityFoundryChannel extends TileEntityFoundryBase {
this.type = null; this.type = null;
this.amount = 0; this.amount = 0;
propagateMaterial(null); this.node.type = null;
} else { } else {
this.amount = left.amount; this.amount = left.amount;
} }
@ -91,6 +89,8 @@ public class TileEntityFoundryChannel extends TileEntityFoundryBase {
if(acc.type == null || acc.type == this.type || acc.amount == 0) { if(acc.type == null || acc.type == this.type || acc.amount == 0) {
acc.type = this.type; acc.type = this.type;
acc.initNode();
acc.node.type = this.type;
acc.lastFlow = dir.getOpposite().ordinal(); acc.lastFlow = dir.getOpposite().ordinal();
@ -117,24 +117,28 @@ public class TileEntityFoundryChannel extends TileEntityFoundryBase {
} }
} }
if(neighborType != null && amount == 0) unpropagateTime++;
// every 5 seconds do a unprop test, will only occur once per contiguous channel per 5 seconds due to the timer getting updated in all channels from the prop
if(unpropagateTime > 100) {
propagateMaterial(null);
}
if(this.amount == 0) { if(this.amount == 0) {
this.lastFlow = 0; this.lastFlow = 0;
this.nextUpdate = 5; this.nextUpdate = 5;
} else {
unpropagateTime = 0;
} }
} }
super.updateEntity(); super.updateEntity();
} }
protected void initNode() {
if(this.node == null || this.node.expired) {
this.node = (FoundryNode) UniNodespace.getNode(worldObj, xCoord, yCoord, zCoord, FoundryNetworkProvider.THE_PROVIDER);
if(this.node == null || this.node.expired) {
this.node = this.createNode();
this.node.type = this.type;
UniNodespace.createNode(worldObj, this.node);
}
}
}
@Override @Override
public int getCapacity() { public int getCapacity() {
return MaterialShapes.INGOT.q(2); return MaterialShapes.INGOT.q(2);
@ -144,95 +148,58 @@ public class TileEntityFoundryChannel extends TileEntityFoundryBase {
public void readFromNBT(NBTTagCompound nbt) { public void readFromNBT(NBTTagCompound nbt) {
super.readFromNBT(nbt); super.readFromNBT(nbt);
this.lastFlow = nbt.getByte("flow"); this.lastFlow = nbt.getByte("flow");
this.neighborType = Mats.matById.get(nbt.getInteger("nType"));
this.hasCheckedNeighbors = nbt.getBoolean("init");
} }
@Override @Override
public void writeToNBT(NBTTagCompound nbt) { public void writeToNBT(NBTTagCompound nbt) {
super.writeToNBT(nbt); super.writeToNBT(nbt);
nbt.setByte("flow", (byte) this.lastFlow); nbt.setByte("flow", (byte) this.lastFlow);
nbt.setInteger("nType", this.neighborType != null ? this.neighborType.id : -1);
nbt.setBoolean("init", hasCheckedNeighbors);
} }
/** @Override
* Channels accept pouring as normal, except when neighbor channels already have material. public void invalidate() {
* This prevents a contiguous channel from having multiple different types of material in it, causing clogs. super.invalidate();
* If you connect two channels that have different materials already in them, god help you (nah jokes it'll just be clogged until you fix manually)
*/ if(!worldObj.isRemote) {
if(this.node != null) {
UniNodespace.destroyNode(worldObj, xCoord, yCoord, zCoord, FoundryNetworkProvider.THE_PROVIDER);
}
}
}
public FoundryNode createNode() {
TileEntity tile = (TileEntity) this;
return new FoundryNode(FoundryNetworkProvider.THE_PROVIDER, new BlockPos(tile.xCoord, tile.yCoord, tile.zCoord)).setConnections(
new DirPos(tile.xCoord + 1, tile.yCoord, tile.zCoord, Library.POS_X),
new DirPos(tile.xCoord - 1, tile.yCoord, tile.zCoord, Library.NEG_X),
new DirPos(tile.xCoord, tile.yCoord, tile.zCoord + 1, Library.POS_Z),
new DirPos(tile.xCoord, tile.yCoord, tile.zCoord - 1, Library.NEG_Z)
);
}
@Override @Override
public boolean canAcceptPartialPour(World world, int x, int y, int z, double dX, double dY, double dZ, ForgeDirection side, MaterialStack stack) { public boolean canAcceptPartialPour(World world, int x, int y, int z, double dX, double dY, double dZ, ForgeDirection side, MaterialStack stack) {
if(!hasCheckedNeighbors || (neighborType != null && neighborType != stack.material)) return false; if(this.node == null) return false;
for(Object o : this.node.net.links) {
FoundryNode node = (FoundryNode) o;
if(node.type != null && node.type != stack.material) {
return false;
}
}
return super.canAcceptPartialPour(world, x, y, z, dX, dY, dZ, side, stack); return super.canAcceptPartialPour(world, x, y, z, dX, dY, dZ, side, stack);
} }
/** Upon pouring, propagate the current material type along contiguous channels */ @Override
public MaterialStack flow(World world, int x, int y, int z, ForgeDirection side, MaterialStack stack) {
if(this.node != null) this.node.type = stack.material;
return super.flow(world, x, y, z, side, stack);
}
@Override @Override
public MaterialStack pour(World world, int x, int y, int z, double dX, double dY, double dZ, ForgeDirection side, MaterialStack stack) { public MaterialStack pour(World world, int x, int y, int z, double dX, double dY, double dZ, ForgeDirection side, MaterialStack stack) {
propagateMaterial(stack.material); if(this.node != null) this.node.type = stack.material;
return super.pour(world, x, y, z, dX, dY, dZ, side, stack); return super.pour(world, x, y, z, dX, dY, dZ, side, stack);
} }
public void propagateMaterial(NTMMaterial propType) {
if(propType != null && neighborType != null) return; // optimise away any pours that change nothing
List<TileEntityFoundryChannel> visited = new ArrayList<TileEntityFoundryChannel>();
visited.add(this);
boolean hasMaterial = propagateMaterial(propType, visited, false);
// since we are now fully clear, it's safe to unassign the contiguous channel type
if(propType == null && !hasMaterial) {
for(TileEntityFoundryChannel acc : visited) {
acc.neighborType = null;
}
}
}
protected boolean propagateMaterial(NTMMaterial propType, List<TileEntityFoundryChannel> visited, boolean hasMaterial) {
// if emptying, don't mark the channel as ready for a new material until it is entirely clear
if(propType != null) {
neighborType = propType;
} else {
// and when empty testing, update the last unpropagate time
unpropagateTime = 0;
}
for(ForgeDirection dir : new ForgeDirection[] { ForgeDirection.NORTH, ForgeDirection.SOUTH, ForgeDirection.WEST, ForgeDirection.EAST }) {
TileEntity b = worldObj.getTileEntity(xCoord + dir.offsetX, yCoord, zCoord + dir.offsetZ);
if(b instanceof TileEntityFoundryChannel && !visited.contains(b)) {
TileEntityFoundryChannel acc = (TileEntityFoundryChannel) b;
visited.add(acc);
if(acc.amount > 0) hasMaterial = true;
hasMaterial = acc.propagateMaterial(propType, visited, hasMaterial);
}
}
return hasMaterial;
}
protected NTMMaterial checkNeighbors(List<TileEntityFoundryChannel> visited) {
if(neighborType != null) return neighborType;
for(ForgeDirection dir : new ForgeDirection[] { ForgeDirection.NORTH, ForgeDirection.SOUTH, ForgeDirection.WEST, ForgeDirection.EAST }) {
TileEntity b = worldObj.getTileEntity(xCoord + dir.offsetX, yCoord, zCoord + dir.offsetZ);
if(b instanceof TileEntityFoundryChannel && !visited.contains(b)) {
TileEntityFoundryChannel acc = (TileEntityFoundryChannel) b;
visited.add(acc);
NTMMaterial neighborMaterial = acc.checkNeighbors(visited);
// immediately propagate backwards if a material is found
if(neighborMaterial != null) return neighborMaterial;
}
}
return null;
}
} }

View File

@ -114,7 +114,7 @@ public class TileEntityMachineArcFurnaceLarge extends TileEntityMachineBase impl
for(DirPos pos : getConPos()) this.trySubscribe(worldObj, pos.getX(), pos.getY(), pos.getZ(), pos.getDir()); for(DirPos pos : getConPos()) this.trySubscribe(worldObj, pos.getX(), pos.getY(), pos.getZ(), pos.getDir());
if(lid == 1) loadIngredients(); if(lid > 0) loadIngredients();
if(power > 0) { if(power > 0) {

View File

@ -0,0 +1,10 @@
package com.hbm.uninos.networkproviders;
import com.hbm.uninos.NodeNet;
public class FoundryNetwork extends NodeNet {
@Override
public void update() { }
}

View File

@ -0,0 +1,14 @@
package com.hbm.uninos.networkproviders;
import com.hbm.uninos.INetworkProvider;
public class FoundryNetworkProvider implements INetworkProvider<FoundryNetwork> {
public static FoundryNetworkProvider THE_PROVIDER = new FoundryNetworkProvider();
@Override
public FoundryNetwork provideNetwork() {
return new FoundryNetwork();
}
}

View File

@ -1,11 +1,13 @@
package com.hbm.world.gen; package com.hbm.world.gen;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import cpw.mods.fml.common.eventhandler.EventPriority; import cpw.mods.fml.common.eventhandler.EventPriority;
import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.MapGenBase; import net.minecraft.world.gen.MapGenBase;
@ -32,6 +34,9 @@ public class MapGenChainloader extends MapGenBase {
// Hack to provide the current generating chunk's block metas to the generation function // Hack to provide the current generating chunk's block metas to the generation function
private static byte[] blockMetas; private static byte[] blockMetas;
// Double hack to check we actually get the damn metas, if not we will have to do a quick bit of post gen!
private static HashMap<ChunkCoordIntPair, byte[]> blockMetaMap = new HashMap<>();
// Executes our chainloaded parent, and all our child generators // Executes our chainloaded parent, and all our child generators
@Override @Override
public void func_151539_a(IChunkProvider chunk, World world, int chunkX, int chunkZ, Block[] blocks) { public void func_151539_a(IChunkProvider chunk, World world, int chunkX, int chunkZ, Block[] blocks) {
@ -62,6 +67,24 @@ public class MapGenChainloader extends MapGenBase {
netherGenerators.add(generator); netherGenerators.add(generator);
} }
public static void repairBadGeneration(World world, int chunkX, int chunkZ) {
ChunkCoordIntPair coords = new ChunkCoordIntPair(chunkX, chunkZ);
if(MapGenChainloader.blockMetaMap.containsKey(coords)) {
byte[] metas = MapGenChainloader.blockMetaMap.get(coords);
for(int i = 0; i < metas.length; i++) {
if(metas[i] == 0) continue;
int y = i % 256;
int xz = (i - y) / 256;
int z = xz % 16;
int x = (xz - z) / 16;
world.setBlockMetadataWithNotify(chunkX * 16 + x, y, chunkZ * 16 + z, metas[i], 3);
}
MapGenChainloader.blockMetaMap.remove(coords);
}
}
public static class MapGenEventHandler { public static class MapGenEventHandler {
// Register as late as possible to pick up any modded cave generators // Register as late as possible to pick up any modded cave generators
@ -84,7 +107,14 @@ public class MapGenChainloader extends MapGenBase {
@SubscribeEvent @SubscribeEvent
public void storeLatestBlockMeta(ReplaceBiomeBlocks event) { public void storeLatestBlockMeta(ReplaceBiomeBlocks event) {
blockMetas = event.metaArray; if(event.metaArray.length == 256) {
// a mod is using a deprecated forge hook! fuck!
// we will store our own meta array and apply metas _after_ chunk gen has finished
blockMetas = new byte[65536];
blockMetaMap.put(new ChunkCoordIntPair(event.chunkX, event.chunkZ), blockMetas);
} else {
blockMetas = event.metaArray;
}
} }
} }

View File

@ -53,7 +53,7 @@ public class MapGenBubble extends MapGenBase {
double radiusSqr = (radius * radius) / 2; // original OilBubble implementation divided the square by 2 for some reason double radiusSqr = (radius * radius) / 2; // original OilBubble implementation divided the square by 2 for some reason
int yMin = Math.max(1, MathHelper.floor_double(yCoord - radius)); int yMin = Math.max(1, MathHelper.floor_double(yCoord - radius));
int yMax = MathHelper.ceiling_double_int(yCoord + radius); int yMax = Math.min(127, MathHelper.ceiling_double_int(yCoord + radius));
for(int bx = 15; bx >= 0; bx--) // bx, bz is the coordinate of the block we're modifying, relative to the generating chunk origin for(int bx = 15; bx >= 0; bx--) // bx, bz is the coordinate of the block we're modifying, relative to the generating chunk origin
for(int bz = 15; bz >= 0; bz--) for(int bz = 15; bz >= 0; bz--)