Skip to content

Commit 6b1aaa7

Browse files
committed
Finally fixed TF saplings
The previous fix may dupe saplings on grow, probably caused by code in ForgeHooks.
1 parent 34b00e7 commit 6b1aaa7

File tree

2 files changed

+91
-32
lines changed

2 files changed

+91
-32
lines changed
Lines changed: 68 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
package io.wdsj.hybridfix.mixin.late.the_twilight_forest.sapling;
22

3+
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
4+
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
5+
import com.llamalad7.mixinextras.sugar.Share;
6+
import com.llamalad7.mixinextras.sugar.ref.LocalBooleanRef;
37
import io.wdsj.hybridfix.duck.bridge.IWorldGetter;
48
import io.wdsj.hybridfix.util.hybrid.HybridReflectionUtils;
59
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
610
import net.minecraft.block.state.IBlockState;
711
import net.minecraft.util.math.BlockPos;
812
import net.minecraft.world.World;
13+
import net.minecraft.world.gen.feature.WorldGenerator;
914
import net.minecraftforge.common.util.BlockSnapshot;
1015
import org.bukkit.Bukkit;
1116
import org.bukkit.Location;
@@ -22,56 +27,40 @@
2227
import java.util.List;
2328
import java.util.Random;
2429

25-
@Mixin(value = BlockTFSapling.class, remap = false)
30+
@Mixin(value = BlockTFSapling.class)
2631
public abstract class BlockTFSaplingMixin {
27-
@Unique private boolean hybridFix$isBoneMeal = true;
32+
@Unique
33+
private boolean hybridFix$isBoneMeal = true;
2834
@Inject(
2935
method = "updateTick",
3036
at = @At(
31-
value = "INVOKE",
32-
target = "Ltwilightforest/block/BlockTFSapling;grow(Lnet/minecraft/world/World;Ljava/util/Random;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/state/IBlockState;)V"
33-
),
34-
remap = true
37+
value = "INVOKE",
38+
target = "Ltwilightforest/block/BlockTFSapling;grow(Lnet/minecraft/world/World;Ljava/util/Random;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/state/IBlockState;)V"
39+
)
3540
)
36-
public void beforeTickGrow(World worldIn, BlockPos pos, IBlockState state, Random rand, CallbackInfo ci) {
41+
private void beforeNaturalGrow(World worldIn, BlockPos pos, IBlockState state, Random rand, CallbackInfo ci) {
3742
hybridFix$isBoneMeal = false;
3843
}
3944

4045
@Inject(
41-
method = "grow",
42-
at = @At(
43-
value = "HEAD"
44-
),
45-
remap = true
46-
)
47-
public void onGrowHead(World worldIn, Random rand, BlockPos pos, IBlockState state, CallbackInfo ci) {
48-
HybridReflectionUtils.setCaptureTreeGeneration(worldIn, true);
49-
}
50-
51-
@Inject(
52-
method = "grow",
46+
method = "updateTick",
5347
at = @At(
54-
value = "RETURN"
55-
),
56-
remap = true
48+
value = "INVOKE",
49+
target = "Ltwilightforest/block/BlockTFSapling;grow(Lnet/minecraft/world/World;Ljava/util/Random;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/state/IBlockState;)V",
50+
shift = At.Shift.AFTER
51+
)
5752
)
58-
// Afterglow >_<
59-
public void afterGrow(World worldIn, Random rand, BlockPos pos, IBlockState state, CallbackInfo ci) {
53+
private void afterNaturalGrow(World worldIn, BlockPos pos, IBlockState state, Random rand, CallbackInfo ci) {
6054
HybridReflectionUtils.setCaptureTreeGeneration(worldIn, false);
55+
hybridFix$isBoneMeal = true;
6156
if (!worldIn.capturedBlockSnapshots.isEmpty()) {
6257
Location location = new Location(((IWorldGetter)worldIn).getWorld(), pos.getX(), pos.getY(), pos.getZ());
6358
List<BlockState> blockstates = new ObjectArrayList<>(worldIn.capturedBlockSnapshots.size());
6459
for (BlockSnapshot snapshot : worldIn.capturedBlockSnapshots) {
6560
blockstates.add(HybridReflectionUtils.newBlockStateFromBlockSnapshot(snapshot));
6661
}
6762
worldIn.capturedBlockSnapshots.clear();
68-
StructureGrowEvent event;
69-
if (!hybridFix$isBoneMeal) {
70-
event = new StructureGrowEvent(location, TreeType.TREE, false, null, blockstates);
71-
hybridFix$isBoneMeal = true;
72-
} else {
73-
event = new StructureGrowEvent(location, TreeType.TREE, true, null, blockstates);
74-
}
63+
StructureGrowEvent event = new StructureGrowEvent(location, TreeType.TREE, false, null, blockstates);
7564
Bukkit.getPluginManager().callEvent(event);
7665
if (!event.isCancelled()) {
7766
for (BlockState blockstate : blockstates) {
@@ -80,4 +69,52 @@ public void afterGrow(World worldIn, Random rand, BlockPos pos, IBlockState stat
8069
}
8170
}
8271
}
72+
73+
@WrapOperation(
74+
method = "grow",
75+
at = @At(
76+
value = "INVOKE",
77+
target = "Lnet/minecraft/world/gen/feature/WorldGenerator;generate(Lnet/minecraft/world/World;Ljava/util/Random;Lnet/minecraft/util/math/BlockPos;)Z"
78+
)
79+
)
80+
public boolean onGenerate(WorldGenerator instance, World world, Random random, BlockPos blockPos, Operation<Boolean> original, @Share("canGen") LocalBooleanRef canGen) {
81+
HybridReflectionUtils.setCaptureTreeGeneration(world, true);
82+
boolean result = original.call(instance, world, random, blockPos);
83+
canGen.set(result);
84+
return result;
85+
}
86+
87+
@Inject(
88+
method = "grow",
89+
at = @At(
90+
value = "HEAD"
91+
)
92+
)
93+
public void setTypeOnGrow(World world, Random rand, BlockPos pos, IBlockState state, CallbackInfo ci) {
94+
if (hybridFix$isBoneMeal) {
95+
world.captureBlockSnapshots = false; // Check ForgeHooks, hybrids are disgusting
96+
world.capturedBlockSnapshots.clear();
97+
HybridReflectionUtils.setTreeType(TreeType.TREE);
98+
}
99+
}
100+
101+
@Inject(
102+
method = "grow",
103+
at = @At(
104+
value = "RETURN"
105+
)
106+
)
107+
// Afterglow >_<
108+
public void afterGrow(World world, Random rand, BlockPos pos, IBlockState state, CallbackInfo ci, @Share("canGen") LocalBooleanRef canGen) {
109+
if (!canGen.get()) {
110+
HybridReflectionUtils.setTreeType(null);
111+
HybridReflectionUtils.setCaptureTreeGeneration(world, false);
112+
List<BlockSnapshot> pending = new ObjectArrayList<>();
113+
pending.addAll(world.capturedBlockSnapshots);
114+
for (BlockSnapshot snapshot : pending) {
115+
snapshot.restore(true);
116+
}
117+
world.capturedBlockSnapshots.clear();
118+
}
119+
}
83120
}

src/main/java/io/wdsj/hybridfix/util/hybrid/HybridReflectionUtils.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package io.wdsj.hybridfix.util.hybrid;
22

33
import io.wdsj.hybridfix.HybridFix;
4+
import net.minecraft.block.BlockSapling;
45
import net.minecraft.world.World;
56
import net.minecraftforge.common.util.BlockSnapshot;
7+
import org.bukkit.TreeType;
68
import org.bukkit.craftbukkit.v1_12_R1.block.CraftBlockState;
79

810
import java.lang.invoke.MethodHandle;
@@ -12,11 +14,21 @@
1214

1315
public class HybridReflectionUtils {
1416
private static final Field FIELD_WORLD_CAPTURE_TREE_GENERATION = getField(World.class, "captureTreeGeneration");
17+
private static final Field FIELD_BLOCK_SAPLING_TREE_TYPE = getField(BlockSapling.class, "treeType");
1518
private static final MethodHandle CONSTRUCTOR_CRAFT_BLOCK_STATE = getConstructorHandle(CraftBlockState.class, BlockSnapshot.class);
1619

1720
public static void setCaptureTreeGeneration(World world, boolean value) {
1821
setBooleanField(FIELD_WORLD_CAPTURE_TREE_GENERATION, world, value);
1922
}
23+
24+
public static TreeType getTreeType() { // Currently unused
25+
return (TreeType) getFieldValue(FIELD_BLOCK_SAPLING_TREE_TYPE, null);
26+
}
27+
28+
public static void setTreeType(TreeType treeType) {
29+
setField(FIELD_BLOCK_SAPLING_TREE_TYPE, null, treeType);
30+
}
31+
2032
public static CraftBlockState newBlockStateFromBlockSnapshot(BlockSnapshot snapshot) {
2133
assert CONSTRUCTOR_CRAFT_BLOCK_STATE != null;
2234
try {
@@ -44,7 +56,17 @@ private static Field getField(Class<?> clazz, String fieldName) {
4456
return null;
4557
}
4658
}
47-
private static void setField(Field field, Object instance, Object... value) {
59+
60+
private static Object getFieldValue(Field field, Object instance) {
61+
try {
62+
return field.get(instance);
63+
} catch (Exception e) {
64+
HybridFix.LOGGER.warn("Error occurred while getting field {}", field.getName(), e);
65+
return null;
66+
}
67+
}
68+
69+
private static void setField(Field field, Object instance, Object value) {
4870
try {
4971
field.set(instance, value);
5072
} catch (Exception e) {

0 commit comments

Comments
 (0)