Skip to content

Commit 048bf63

Browse files
committed
尝试优化IE的多方块结构的部分查询性能
1 parent a27e9f0 commit 048bf63

6 files changed

Lines changed: 346 additions & 0 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package github.kasuminova.novaeng.mixin.ic2;
2+
3+
import ic2.api.energy.EnergyNet;
4+
import ic2.api.energy.tile.IEnergyTile;
5+
import ic2.core.energy.grid.Tile;
6+
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
7+
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
8+
import net.minecraft.util.math.BlockPos;
9+
import org.spongepowered.asm.mixin.Final;
10+
import org.spongepowered.asm.mixin.Mixin;
11+
import org.spongepowered.asm.mixin.Overwrite;
12+
import org.spongepowered.asm.mixin.Shadow;
13+
import org.spongepowered.asm.mixin.Unique;
14+
15+
import java.util.List;
16+
17+
@Mixin(value = Tile.class, remap = false)
18+
public class MixinTile {
19+
20+
@Shadow
21+
@Final
22+
List<IEnergyTile> subTiles;
23+
@Unique
24+
private static final IEnergyTile N_E = new IEnergyTile() {};
25+
@Unique
26+
private final Long2ObjectMap<IEnergyTile> n_cache = new Long2ObjectOpenHashMap<>();
27+
28+
{
29+
n_cache.defaultReturnValue(N_E);
30+
}
31+
32+
/**
33+
* @author circulation
34+
* @reason 一个索引式优化尝试?
35+
*/
36+
@Overwrite
37+
IEnergyTile getSubTileAt(BlockPos pos) {
38+
if (subTiles.size() < 8) {
39+
return n_g(pos);
40+
}
41+
var t = n_cache.get(pos.toLong());
42+
if (t == null) {
43+
return null;
44+
}
45+
if (t == n_cache.defaultReturnValue()) {
46+
n_cache.put(pos.toLong(), t = n_g(pos));
47+
}
48+
return t;
49+
}
50+
51+
@Unique
52+
private IEnergyTile n_g(BlockPos pos) {
53+
for(IEnergyTile subTile : this.subTiles) {
54+
if (EnergyNet.instance.getPos(subTile).equals(pos)) {
55+
return subTile;
56+
}
57+
}
58+
59+
return null;
60+
}
61+
62+
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package github.kasuminova.novaeng.mixin.immersiveengineering;
2+
3+
import blusunrize.immersiveengineering.api.DimensionChunkCoords;
4+
import blusunrize.immersiveengineering.api.tool.ExcavatorHandler;
5+
import net.minecraft.world.World;
6+
import org.spongepowered.asm.mixin.Mixin;
7+
import org.spongepowered.asm.mixin.Overwrite;
8+
import org.spongepowered.asm.mixin.Shadow;
9+
import org.spongepowered.asm.mixin.Unique;
10+
11+
import java.util.HashMap;
12+
import java.util.HashSet;
13+
import java.util.LinkedHashMap;
14+
import java.util.Map;
15+
import java.util.Random;
16+
import java.util.Set;
17+
18+
@Mixin(value = ExcavatorHandler.class, remap = false)
19+
public class MixinExcavatorHandler {
20+
21+
@Shadow
22+
public static HashMap<DimensionChunkCoords, ExcavatorHandler.MineralWorldInfo> mineralCache;
23+
24+
@Shadow
25+
public static LinkedHashMap<ExcavatorHandler.MineralMix, Integer> mineralList;
26+
27+
@Shadow
28+
public static double mineralChance;
29+
30+
/**
31+
* @author Circulation
32+
* @reason 让没有任何矿脉的维度生成主世界的矿脉
33+
*/
34+
@Overwrite
35+
public static ExcavatorHandler.MineralWorldInfo getMineralWorldInfo(final World world,
36+
final DimensionChunkCoords chunkCoords,
37+
final boolean guaranteed) {
38+
if (world.isRemote) {
39+
return null;
40+
}
41+
42+
ExcavatorHandler.MineralWorldInfo worldInfo = mineralCache.get(chunkCoords);
43+
if (worldInfo == null) {
44+
ExcavatorHandler.MineralMix mix = null;
45+
Random random = world.getChunk(chunkCoords.x, chunkCoords.z).getRandomWithSeed(940610L);
46+
boolean empty = !guaranteed && random.nextDouble() > mineralChance;
47+
48+
if (!empty) {
49+
int mineralDimension = chunkCoords.dimension;
50+
if (mineralDimension != 0 && novaeng_core$getDimensionTotalWeight(mineralDimension) <= 0) {
51+
mineralDimension = 0;
52+
}
53+
54+
Set<Map.Entry<ExcavatorHandler.MineralMix, Integer>> selection =
55+
novaeng_core$selectMinerals(chunkCoords, mineralDimension);
56+
int totalWeight = novaeng_core$getTotalWeight(selection);
57+
58+
if (totalWeight > 0) {
59+
int weight = Math.abs(random.nextInt() % totalWeight);
60+
61+
for (Map.Entry<ExcavatorHandler.MineralMix, Integer> entry : selection) {
62+
weight -= entry.getValue();
63+
if (weight < 0) {
64+
mix = entry.getKey();
65+
break;
66+
}
67+
}
68+
}
69+
}
70+
71+
worldInfo = new ExcavatorHandler.MineralWorldInfo();
72+
worldInfo.mineral = mix;
73+
mineralCache.put(chunkCoords, worldInfo);
74+
}
75+
76+
return worldInfo;
77+
}
78+
79+
@Unique
80+
private static int novaeng_core$getDimensionTotalWeight(final int mineralDimension) {
81+
int totalWeight = 0;
82+
for (Map.Entry<ExcavatorHandler.MineralMix, Integer> entry : mineralList.entrySet()) {
83+
ExcavatorHandler.MineralMix mineral = entry.getKey();
84+
if (mineral.isValid() && mineral.validDimension(mineralDimension)) {
85+
totalWeight += entry.getValue();
86+
}
87+
}
88+
return totalWeight;
89+
}
90+
91+
@Unique
92+
private static Set<ExcavatorHandler.MineralMix> novaeng_core$getSurroundingMinerals(
93+
final DimensionChunkCoords chunkCoords) {
94+
Set<ExcavatorHandler.MineralMix> surrounding = new HashSet<>();
95+
for (int xx = -2; xx <= 2; ++xx) {
96+
for (int zz = -2; zz <= 2; ++zz) {
97+
if (xx == 0 && zz == 0) {
98+
continue;
99+
}
100+
101+
DimensionChunkCoords offset = chunkCoords.withOffset(xx, zz);
102+
ExcavatorHandler.MineralWorldInfo worldInfo = mineralCache.get(offset);
103+
if (worldInfo != null && worldInfo.mineral != null) {
104+
surrounding.add(worldInfo.mineral);
105+
}
106+
}
107+
}
108+
return surrounding;
109+
}
110+
111+
@Unique
112+
private static Set<Map.Entry<ExcavatorHandler.MineralMix, Integer>> novaeng_core$selectMinerals(
113+
final DimensionChunkCoords chunkCoords,
114+
final int mineralDimension) {
115+
Set<ExcavatorHandler.MineralMix> surrounding = novaeng_core$getSurroundingMinerals(chunkCoords);
116+
Set<Map.Entry<ExcavatorHandler.MineralMix, Integer>> validMinerals = new HashSet<>();
117+
118+
for (Map.Entry<ExcavatorHandler.MineralMix, Integer> entry : mineralList.entrySet()) {
119+
ExcavatorHandler.MineralMix mineral = entry.getKey();
120+
if (mineral.isValid() && mineral.validDimension(mineralDimension) && !surrounding.contains(mineral)) {
121+
validMinerals.add(entry);
122+
}
123+
}
124+
125+
return validMinerals;
126+
}
127+
128+
@Unique
129+
private static int novaeng_core$getTotalWeight(
130+
final Set<Map.Entry<ExcavatorHandler.MineralMix, Integer>> minerals) {
131+
int totalWeight = 0;
132+
for (Map.Entry<ExcavatorHandler.MineralMix, Integer> entry : minerals) {
133+
totalWeight += entry.getValue();
134+
}
135+
return totalWeight;
136+
}
137+
138+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package github.kasuminova.novaeng.mixin.immersiveengineering;
2+
3+
import blusunrize.immersiveengineering.api.crafting.IMultiblockRecipe;
4+
import blusunrize.immersiveengineering.common.blocks.metal.TileEntityMultiblockMetal;
5+
import org.spongepowered.asm.mixin.Mixin;
6+
import org.spongepowered.asm.mixin.Overwrite;
7+
import org.spongepowered.asm.mixin.Shadow;
8+
import org.spongepowered.asm.mixin.Unique;
9+
10+
@Mixin(value = TileEntityMultiblockMetal.class, remap = false)
11+
public abstract class MixinTileEntityMultiblockMetal<T extends TileEntityMultiblockMetal<T, R>, R extends IMultiblockRecipe> extends MixinTileEntityMultiblockPart<T> {
12+
13+
@Unique
14+
private int n_cache;
15+
16+
@Shadow
17+
public abstract int[] getEnergyPos();
18+
19+
/**
20+
* @author circulation
21+
* @reason 重写方法在field_174879_c不变化的情况下直接返回true
22+
*/
23+
@Overwrite
24+
public boolean isEnergyPos() {
25+
if (n_cache == field_174879_c) {
26+
return true;
27+
}
28+
for (int i : this.getEnergyPos()) {
29+
if (this.field_174879_c == i) {
30+
n_cache = field_174879_c;
31+
return true;
32+
}
33+
}
34+
35+
return false;
36+
}
37+
38+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package github.kasuminova.novaeng.mixin.immersiveengineering;
2+
3+
import blusunrize.immersiveengineering.common.blocks.TileEntityIEBase;
4+
import blusunrize.immersiveengineering.common.blocks.TileEntityMultiblockPart;
5+
import blusunrize.immersiveengineering.common.util.Utils;
6+
import net.minecraft.tileentity.TileEntity;
7+
import net.minecraft.util.math.BlockPos;
8+
import org.spongepowered.asm.mixin.Mixin;
9+
import org.spongepowered.asm.mixin.Overwrite;
10+
import org.spongepowered.asm.mixin.Shadow;
11+
import org.spongepowered.asm.mixin.Unique;
12+
13+
import javax.annotation.Nullable;
14+
15+
@Mixin(value = TileEntityMultiblockPart.class, remap = false)
16+
public abstract class MixinTileEntityMultiblockPart<T extends TileEntityMultiblockPart<T>> extends TileEntityIEBase {
17+
18+
@Shadow
19+
public int[] offset;
20+
@Shadow
21+
public int field_174879_c;
22+
@Unique
23+
private T n_te;
24+
@Unique
25+
private long n_cachePos;
26+
27+
/**
28+
* @author circulation
29+
* @reason 重写方法缓存上一次捕获到的结果
30+
*/
31+
@SuppressWarnings({"unchecked", "DataFlowIssue"})
32+
@Nullable
33+
@Overwrite
34+
public T master() {
35+
if (this.offset[0] == 0 && this.offset[1] == 0 && this.offset[2] == 0) {
36+
return (T) (Object) this;
37+
} else {
38+
BlockPos masterPos = this.getPos().add(-this.offset[0], -this.offset[1], -this.offset[2]);
39+
if (masterPos.toLong() == n_cachePos) {
40+
if (n_te != null && !n_te.isInvalid()) {
41+
return n_te;
42+
} else {
43+
n_te = null;
44+
n_cachePos = 0;
45+
}
46+
}
47+
TileEntity te = Utils.getExistingTileEntity(this.world, masterPos);
48+
if (this.getClass().isInstance(te)) {
49+
n_cachePos = masterPos.toLong();
50+
return n_te = (T) te;
51+
}
52+
return null;
53+
}
54+
}
55+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package github.kasuminova.novaeng.mixin.immersiveengineering;
2+
3+
import blusunrize.immersiveengineering.api.crafting.IMultiblockRecipe;
4+
import blusunrize.immersiveengineering.common.util.Utils;
5+
import flaxbeard.immersivepetroleum.common.blocks.metal.TileEntityPumpjack;
6+
import net.minecraft.tileentity.TileEntity;
7+
import net.minecraft.util.math.BlockPos;
8+
import org.spongepowered.asm.mixin.Mixin;
9+
import org.spongepowered.asm.mixin.Overwrite;
10+
import org.spongepowered.asm.mixin.Unique;
11+
12+
import javax.annotation.Nullable;
13+
14+
@Mixin(value = TileEntityPumpjack.class, remap = false)
15+
public abstract class MixinTileEntityPumpjack extends MixinTileEntityMultiblockMetal<TileEntityPumpjack, IMultiblockRecipe> {
16+
17+
@Unique
18+
private TileEntityPumpjack n_te;
19+
@Unique
20+
private long n_cachePos;
21+
22+
/**
23+
* @author circulation
24+
* @reason 重写方法缓存上一次捕获到的结果
25+
*/
26+
@Nullable
27+
@Overwrite
28+
public TileEntityPumpjack master() {
29+
if (this.offset[0] == 0 && this.offset[1] == 0 && this.offset[2] == 0) {
30+
return (TileEntityPumpjack) (Object) this;
31+
} else {
32+
BlockPos masterPos = this.getPos().add(-this.offset[0], -this.offset[1], -this.offset[2]);
33+
if (masterPos.toLong() == n_cachePos) {
34+
if (n_te != null && !n_te.isInvalid()) {
35+
return n_te;
36+
} else {
37+
n_te = null;
38+
n_cachePos = 0;
39+
}
40+
}
41+
TileEntity te = Utils.getExistingTileEntity(this.world, masterPos);
42+
if (te instanceof TileEntityPumpjack p) {
43+
n_cachePos = masterPos.toLong();
44+
return n_te = p;
45+
}
46+
return null;
47+
}
48+
}
49+
}

src/main/resources/mixins.novaeng_core.mod.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,13 @@
7373
"ic2.AccessorTileEntityInventory",
7474
"ic2.MixinBasicMachineRecipeManager",
7575
"ic2.MixinNetworkManager",
76+
"ic2.MixinTile",
7677
"ic2.MixinTileEntityBlock",
7778
"ic2.MixinTileEntityMatter",
7879
"ic2.MixinTileEntityReplicator",
80+
"immersiveengineering.MixinTileEntityMultiblockMetal",
81+
"immersiveengineering.MixinTileEntityMultiblockPart",
82+
"immersiveengineering.MixinTileEntityPumpjack",
7983
"libvulpes.MixinTileFluidHatch",
8084
"lootoverhaul.MixinConfigIdFileGenerator",
8185
"mets.MixinEntityTachyonBullet",

0 commit comments

Comments
 (0)