Skip to content

Commit aeeaf9b

Browse files
committed
Added proper init to tile entities.
Added absolute world time counting. Added framework for tile entities extendable with features.
1 parent 7647e86 commit aeeaf9b

11 files changed

+405
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package sunsetsatellite.catalyst.core.mixin;
2+
3+
import net.minecraft.core.block.Block;
4+
import net.minecraft.core.block.entity.TileEntity;
5+
import net.minecraft.core.world.chunk.Chunk;
6+
import org.spongepowered.asm.mixin.Mixin;
7+
import org.spongepowered.asm.mixin.Shadow;
8+
import org.spongepowered.asm.mixin.injection.At;
9+
import org.spongepowered.asm.mixin.injection.Inject;
10+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
11+
import sunsetsatellite.catalyst.core.util.mixin.interfaces.ITileEntityInit;
12+
13+
@Mixin(value = Chunk.class,remap = false)
14+
public abstract class ChunkMixin {
15+
16+
@Shadow
17+
public abstract int getBlockID(int x, int y, int z);
18+
19+
@Inject(method = "setTileEntity",at = @At(value = "INVOKE", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", shift = At.Shift.AFTER))
20+
public void setTileEntity(int x, int y, int z, TileEntity tileEntity, CallbackInfo ci){
21+
if(!((ITileEntityInit) tileEntity).isInitialized()){
22+
((ITileEntityInit) tileEntity).setInitialized();
23+
((ITileEntityInit) tileEntity).init(Block.getBlock(getBlockID(x,y,z)));
24+
}
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package sunsetsatellite.catalyst.core.mixin;
2+
3+
import com.mojang.nbt.CompoundTag;
4+
import net.minecraft.core.world.save.LevelData;
5+
import org.spongepowered.asm.mixin.Mixin;
6+
import org.spongepowered.asm.mixin.Unique;
7+
import org.spongepowered.asm.mixin.injection.At;
8+
import org.spongepowered.asm.mixin.injection.Inject;
9+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
10+
import sunsetsatellite.catalyst.core.util.mixin.interfaces.IAbsoluteWorldTime;
11+
12+
@Mixin(value = LevelData.class,remap = false)
13+
public class LevelDataMixin implements IAbsoluteWorldTime {
14+
15+
@Unique
16+
private long absoluteWorldTime;
17+
18+
@Override
19+
public long getAbsoluteWorldTime() {
20+
return absoluteWorldTime;
21+
}
22+
23+
@Override
24+
public void setAbsoluteWorldTime(long value) {
25+
absoluteWorldTime = value;
26+
}
27+
28+
@Inject(method = "<init>(Lnet/minecraft/core/world/save/LevelData;)V",at = @At("TAIL"))
29+
public void init(LevelData levelData, CallbackInfo ci){
30+
absoluteWorldTime = ((IAbsoluteWorldTime) levelData).getAbsoluteWorldTime();
31+
}
32+
33+
@Inject(method = "readFromCompoundTag", at = @At("HEAD"))
34+
public void read(CompoundTag tag, CallbackInfo ci){
35+
absoluteWorldTime = tag.getLong("AbsoluteTime");
36+
}
37+
38+
@Inject(method = "updateTagCompound", at = @At("HEAD"))
39+
public void write(CompoundTag levelTag, CompoundTag playerTag, CallbackInfo ci){
40+
levelTag.putLong("AbsoluteTime", absoluteWorldTime);
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package sunsetsatellite.catalyst.core.mixin;
2+
3+
import net.minecraft.core.block.Block;
4+
import net.minecraft.core.block.entity.TileEntity;
5+
import org.spongepowered.asm.mixin.Mixin;
6+
import org.spongepowered.asm.mixin.Unique;
7+
import sunsetsatellite.catalyst.core.util.mixin.interfaces.ITileEntityInit;
8+
9+
@Mixin(value = TileEntity.class,remap = false)
10+
public class TileEntityMixin implements ITileEntityInit {
11+
12+
@Unique
13+
protected boolean initialized = false;
14+
15+
@Override
16+
public void init(Block block) {
17+
}
18+
19+
@Override
20+
public boolean isInitialized() {
21+
return initialized;
22+
}
23+
24+
@Override
25+
public void setInitialized() {
26+
initialized = true;
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package sunsetsatellite.catalyst.core.mixin;
2+
3+
import net.minecraft.client.world.WorldClient;
4+
import net.minecraft.core.world.World;
5+
import org.spongepowered.asm.mixin.Mixin;
6+
import org.spongepowered.asm.mixin.injection.At;
7+
import org.spongepowered.asm.mixin.injection.Inject;
8+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
9+
import sunsetsatellite.catalyst.core.util.mixin.interfaces.IAbsoluteWorldTime;
10+
11+
@Mixin(value = WorldClient.class,remap = false)
12+
public class WorldClientMixin extends World {
13+
14+
@Inject(method = "tick", at = @At("HEAD"))
15+
public void tick(CallbackInfo ci){
16+
((IAbsoluteWorldTime) this.levelData).setAbsoluteWorldTime(((IAbsoluteWorldTime) this.levelData).getAbsoluteWorldTime() + 1L);
17+
}
18+
}

src/main/java/sunsetsatellite/catalyst/core/mixin/WorldMixin.java

+20-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import net.minecraft.core.block.entity.TileEntity;
44
import net.minecraft.core.world.World;
5+
import net.minecraft.core.world.save.LevelData;
56
import net.minecraft.core.world.save.LevelStorage;
67
import org.spongepowered.asm.mixin.Final;
78
import org.spongepowered.asm.mixin.Mixin;
@@ -14,11 +15,12 @@
1415
import sunsetsatellite.catalyst.Catalyst;
1516
import sunsetsatellite.catalyst.core.util.BlockChangeInfo;
1617
import sunsetsatellite.catalyst.core.util.Vec3i;
18+
import sunsetsatellite.catalyst.core.util.mixin.interfaces.IAbsoluteWorldTime;
1719
import sunsetsatellite.catalyst.core.util.mixin.interfaces.ISaveHandlerWorld;
1820
import sunsetsatellite.catalyst.core.util.network.NetworkManager;
1921

2022
@Mixin(value = World.class,remap = false)
21-
public abstract class WorldMixin {
23+
public abstract class WorldMixin implements IAbsoluteWorldTime {
2224

2325
@Shadow
2426
@Final
@@ -30,6 +32,8 @@ public abstract class WorldMixin {
3032

3133
@Shadow public abstract TileEntity getBlockTileEntity(int x, int y, int z);
3234

35+
@Shadow
36+
protected LevelData levelData;
3337
@Unique
3438
private final World thisAs = (World)((Object)this);
3539

@@ -86,4 +90,19 @@ public void setBlockAndMetadata(int x, int y, int z, int id, int meta, CallbackI
8690
Catalyst.TILE_ENTITY_BLOCK_CHANGED_SIGNAL.emit(new BlockChangeInfo(thisAs,new Vec3i(x,y,z),id,getBlockMetadata(x,y,z)));
8791
}
8892
}
93+
94+
@Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/debug/Debug;change(Ljava/lang/String;)V", ordinal = 5, shift = At.Shift.AFTER))
95+
public void tick(CallbackInfo ci){
96+
((IAbsoluteWorldTime) this.levelData).setAbsoluteWorldTime(((IAbsoluteWorldTime) this.levelData).getAbsoluteWorldTime() + 1L);
97+
}
98+
99+
@Override
100+
public long getAbsoluteWorldTime() {
101+
return ((IAbsoluteWorldTime) levelData).getAbsoluteWorldTime();
102+
}
103+
104+
@Override
105+
public void setAbsoluteWorldTime(long value) {
106+
((IAbsoluteWorldTime) levelData).setAbsoluteWorldTime(value);
107+
}
89108
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package sunsetsatellite.catalyst.core.util;
2+
3+
import net.minecraft.core.world.World;
4+
import sunsetsatellite.catalyst.core.util.mixin.interfaces.IAbsoluteWorldTime;
5+
6+
import java.util.Arrays;
7+
8+
public class AveragingCounter {
9+
10+
private final long defaultValue;
11+
private final long[] values;
12+
private long lastUpdatedWorldTime = 0;
13+
private int currentIndex = 0;
14+
private boolean dirty = true;
15+
private double lastAverage = 0;
16+
17+
public AveragingCounter() {
18+
this(0, 20);
19+
}
20+
21+
public AveragingCounter(long defaultValue, int length) {
22+
this.defaultValue = defaultValue;
23+
this.values = new long[length];
24+
Arrays.fill(values, defaultValue);
25+
}
26+
27+
private void update(World world) {
28+
if (world == null) return;
29+
long currentWorldTime = ((IAbsoluteWorldTime) world).getAbsoluteWorldTime();
30+
if (currentWorldTime != lastUpdatedWorldTime) {
31+
long dif = currentWorldTime - lastUpdatedWorldTime;
32+
if (dif >= values.length || dif < 0) {
33+
Arrays.fill(values, defaultValue);
34+
currentIndex = 0;
35+
} else {
36+
currentIndex += (int) dif;
37+
if (currentIndex > values.length - 1)
38+
currentIndex -= values.length;
39+
int index;
40+
for (int i = 0, n = values.length; i < dif; i++) {
41+
index = i + currentIndex;
42+
if (index >= n)
43+
index -= n;
44+
values[index] = defaultValue;
45+
}
46+
}
47+
this.lastUpdatedWorldTime = currentWorldTime;
48+
dirty = true;
49+
}
50+
}
51+
52+
public long getLast(World world) {
53+
update(world);
54+
return values[currentIndex];
55+
}
56+
57+
public double getAverage(World world) {
58+
update(world);
59+
if (!dirty)
60+
return lastAverage;
61+
dirty = false;
62+
return lastAverage = Arrays.stream(values).sum() / (double) (values.length);
63+
}
64+
65+
public void increment(World world, long value) {
66+
update(world);
67+
values[currentIndex] += value;
68+
}
69+
70+
public void set(World world, long value) {
71+
update(world);
72+
values[currentIndex] = value;
73+
}
74+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package sunsetsatellite.catalyst.core.util.mixin.interfaces;
2+
3+
public interface IAbsoluteWorldTime {
4+
5+
long getAbsoluteWorldTime();
6+
7+
void setAbsoluteWorldTime(long value);
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package sunsetsatellite.catalyst.core.util.mixin.interfaces;
2+
3+
import net.minecraft.core.block.Block;
4+
5+
public interface ITileEntityInit {
6+
void init(Block block);
7+
8+
default boolean isInitialized() {
9+
return false;
10+
}
11+
12+
default void setInitialized(){
13+
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package sunsetsatellite.catalyst.core.util.tile;
2+
3+
import com.mojang.nbt.CompoundTag;
4+
import com.mojang.nbt.Tag;
5+
import net.minecraft.core.block.Block;
6+
import net.minecraft.core.block.entity.TileEntity;
7+
import sunsetsatellite.catalyst.core.util.mixin.interfaces.ITileEntityInit;
8+
9+
import java.util.HashMap;
10+
import java.util.Map;
11+
12+
public class ExtendableTileEntity extends TileEntity implements ITileEntityInit {
13+
14+
protected Map<String,TEFeature> features = new HashMap<>();
15+
private CompoundTag loadData;
16+
17+
@Override
18+
public void init(Block block) {
19+
loadFeatures();
20+
}
21+
22+
@Override
23+
public void tick() {
24+
super.tick();
25+
features.forEach((S,F)->F.tick());
26+
}
27+
28+
@Override
29+
public void writeToNBT(CompoundTag nbttagcompound) {
30+
super.writeToNBT(nbttagcompound);
31+
CompoundTag featuresTag = new CompoundTag();
32+
33+
features.forEach((S,F)->{
34+
CompoundTag featureTag = new CompoundTag();
35+
F.writeToNBT(featureTag);
36+
featuresTag.putCompound(S,featureTag);
37+
});
38+
nbttagcompound.put("Features",featuresTag);
39+
}
40+
41+
public void loadFeatures(){
42+
CompoundTag featuresTag = loadData.getCompound("Features");
43+
for (Tag<?> tag : featuresTag.getValues()) {
44+
if(tag instanceof CompoundTag) {
45+
CompoundTag featureTag = (CompoundTag) tag;
46+
TEFeature feature = TEFeature.loadFeature(featureTag, worldObj);
47+
if(feature != null) {
48+
features.put(feature.id,feature);
49+
}
50+
}
51+
}
52+
loadData = null;
53+
}
54+
55+
@Override
56+
public void readFromNBT(CompoundTag nbttagcompound) {
57+
super.readFromNBT(nbttagcompound);
58+
loadData = nbttagcompound;
59+
}
60+
61+
public boolean hasFeature(String id){
62+
return features.get(id) != null;
63+
}
64+
65+
public TEFeature getFeature(String id){
66+
return features.get(id);
67+
}
68+
}

0 commit comments

Comments
 (0)