Author SHA1 Message Date
layue13andClaude Sonnet 5.5 34f98ad930 perf: hyper node creator rewrites the node only when it no longer holds the wanted aspects
Build / build (push) Skipped
Build / publish (push) Skipped
Build / publish (pull_request) Skipped
Build / build (pull_request) Successful in 43s
Closes TDLM/thaumicadditions#16

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-07 14:19:39 +08:00
layue13 a0e3d1751f Merge pull request 'perf: creative node registers once, no server stack walk' (#29) from perf/creative-node-registry into main
Build / build (push) Successful in 51s
Build / publish (push) Successful in 45s
2026-11-07 06:18:49 +00:00
2 changed files with 99 additions and 14 deletions

No files matched your search

@@ -35,25 +35,17 @@ public class TileHyperNodeCreator extends TileThaumcraft implements IInventory,
}
}
TileNode var5 = this.worldObj.getTileEntity(this.xCoord, this.yCoord + 1, this.zCoord) != null && this.worldObj.getTileEntity(this.xCoord, this.yCoord + 1, this.zCoord) instanceof TileNode?(TileNode)this.worldObj.getTileEntity(this.xCoord, this.yCoord + 1, this.zCoord):null;
net.minecraft.tileentity.TileEntity above = this.worldObj.getTileEntity(this.xCoord, this.yCoord + 1, this.zCoord);
TileNode var5 = above instanceof TileNode?(TileNode)above:null;
this.node = var5 != null;
if(this.node) {
AspectList list = new AspectList();
int corner;
for(corner = 0; corner < Aspect.getPrimalAspects().size(); ++corner) {
list.add((Aspect)Aspect.getPrimalAspects().get(corner), totalItems);
// the node is only rewritten when it no longer holds the wanted amounts (drained, or the stock changed)
if(!holdsExactly(var5.getAspects(), totalItems, this.primalsOnly)) {
var5.setAspects(wantedAspects(totalItems, this.primalsOnly));
}
if(!this.primalsOnly) {
for(corner = 0; corner < Aspect.getCompoundAspects().size(); ++corner) {
list.add((Aspect)Aspect.getCompoundAspects().get(corner), totalItems);
}
}
var5.setAspects(list);
if(this.worldObj.rand.nextBoolean()) {
corner = this.worldObj.rand.nextInt(8);
int corner = this.worldObj.rand.nextInt(8);
if(corner == 0) {
Thaumcraft.proxy.nodeBolt(this.worldObj, (float)this.xCoord, (float)this.yCoord + 2.0F, (float)this.zCoord, (float)this.xCoord + 0.5F, (float)this.yCoord + 1.5F, (float)this.zCoord + 0.5F);
}
@@ -90,6 +82,52 @@ public class TileHyperNodeCreator extends TileThaumcraft implements IInventory,
}
/** The aspect list a node above gets: every primal (and unless primalsOnly every compound) at {@code total}. */
public static AspectList wantedAspects(int total, boolean primalsOnly) {
AspectList list = new AspectList();
int i;
for(i = 0; i < Aspect.getPrimalAspects().size(); ++i) {
list.add((Aspect)Aspect.getPrimalAspects().get(i), total);
}
if(!primalsOnly) {
for(i = 0; i < Aspect.getCompoundAspects().size(); ++i) {
list.add((Aspect)Aspect.getCompoundAspects().get(i), total);
}
}
return list;
}
/** Whether {@code current} already equals {@link #wantedAspects(int, boolean)} without building it. */
public static boolean holdsExactly(AspectList current, int total, boolean primalsOnly) {
if(current == null) {
return false;
}
int expected = Aspect.getPrimalAspects().size() + (primalsOnly?0:Aspect.getCompoundAspects().size());
return current.size() == expected && allAmounts(current, total, primalsOnly);
}
private static boolean allAmounts(AspectList current, int total, boolean primalsOnly) {
for(int i = 0; i < Aspect.getPrimalAspects().size(); ++i) {
if(current.getAmount((Aspect)Aspect.getPrimalAspects().get(i)) != total) {
return false;
}
}
if(!primalsOnly) {
for(int i = 0; i < Aspect.getCompoundAspects().size(); ++i) {
if(current.getAmount((Aspect)Aspect.getCompoundAspects().get(i)) != total) {
return false;
}
}
}
return true;
}
public static boolean areItemStacksEqual(ItemStack s1, ItemStack s2) {
return s1 == null && s2 == null?true:s1 != null && s2 != null && s1.getItem() == s2.getItem() && s1.getItemDamage() == s2.getItemDamage();
}
@@ -0,0 +1,47 @@
package com.pengu.thaumcraft.additions.tileentity;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
/** TDLM/thaumicadditions#16: the node is only rewritten when it no longer holds what the creator wants. */
public class HyperNodeCreatorAspectsTest {
@Test
public void aFreshlyBuiltListIsRecognisedAsCurrent() {
for (boolean primalsOnly : new boolean[] { false, true }) {
for (int total : new int[] { 0, 1, 64, 5000 }) {
AspectList list = TileHyperNodeCreator.wantedAspects(total, primalsOnly);
assertTrue("total " + total + " primalsOnly " + primalsOnly,
TileHyperNodeCreator.holdsExactly(list, total, primalsOnly));
}
}
}
@Test
public void wantedListHasTheSameShapeAsBefore() {
AspectList all = TileHyperNodeCreator.wantedAspects(7, false);
assertEquals(Aspect.getPrimalAspects().size() + Aspect.getCompoundAspects().size(), all.size());
assertEquals(7, all.getAmount(Aspect.getPrimalAspects().get(0)));
assertEquals(Aspect.getPrimalAspects().size(), TileHyperNodeCreator.wantedAspects(7, true).size());
}
@Test
public void aDrainedOrChangedNodeIsRewritten() {
AspectList list = TileHyperNodeCreator.wantedAspects(10, false);
list.reduce(Aspect.getPrimalAspects().get(0), 3);
assertFalse(TileHyperNodeCreator.holdsExactly(list, 10, false));
assertFalse(TileHyperNodeCreator.holdsExactly(TileHyperNodeCreator.wantedAspects(10, false), 11, false));
assertFalse(TileHyperNodeCreator.holdsExactly(TileHyperNodeCreator.wantedAspects(10, true), 10, false));
assertFalse(TileHyperNodeCreator.holdsExactly(null, 10, false));
}
@Test
public void primalsOnlyDoesNotMatchAnUnrelatedFullList() {
assertFalse(TileHyperNodeCreator.holdsExactly(TileHyperNodeCreator.wantedAspects(10, false), 10, true));
}
}