Inspired by 2020's April Fools' 20w14infinite Snapshot, this mod brings endless randomly generated dimensions into Minecraft.
1package net.lerariemann.infinity.block.entity;
2
3import net.lerariemann.infinity.block.custom.AltarBlock;
4import net.lerariemann.infinity.registry.core.ModBlockEntities;
5import net.lerariemann.infinity.util.VersionMethods;
6import net.lerariemann.infinity.util.core.NbtUtils;
7import net.minecraft.core.BlockPos;
8import net.minecraft.core.Holder;
9import net.minecraft.core.HolderLookup;
10import net.minecraft.nbt.CompoundTag;
11import net.minecraft.nbt.ListTag;
12import net.minecraft.nbt.Tag;
13import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
14import net.minecraft.server.level.ServerLevel;
15import net.minecraft.world.entity.Entity;
16import net.minecraft.world.level.Level;
17import net.minecraft.world.level.block.Blocks;
18import net.minecraft.world.level.block.entity.BlockEntity;
19import net.minecraft.world.level.block.state.BlockState;
20//? if >1.21.4 {
21import net.minecraft.world.level.storage.ValueInput;
22import net.minecraft.world.level.storage.ValueOutput;
23//?}
24import net.minecraft.world.level.gameevent.GameEventListener;
25import net.minecraft.world.level.gameevent.vibrations.VibrationSystem;
26import net.minecraft.world.level.gameevent.BlockPositionSource;
27import net.minecraft.world.level.gameevent.PositionSource;
28import net.minecraft.world.level.gameevent.GameEvent;
29import org.apache.logging.log4j.LogManager;
30import org.jspecify.annotations.Nullable;
31
32import java.util.*;
33
34import static net.lerariemann.infinity.block.custom.AltarBlock.numColors;
35
36/// This will be used later for player-performed invocations such as creating new biomes, but for now is kinda deprecated
37public class CosmicAltarBlockEntity extends SpecialBlockEntity.Boopable implements GameEventListener.
38 //? if <1.21 {
39 /*Holder
40 *///?} else {
41 Provider
42 //?}
43 <VibrationSystem.Listener>,
44 VibrationSystem {
45 private VibrationSystem.Data vibrationData;
46 private final VibrationSystem.Listener vibrationListener;
47 private final VibrationSystem.User vibrationUser;
48
49 public Set<Integer> error = new HashSet<>();
50 public Map<Integer, Set<BlockPos>> pedestals = new HashMap<>();
51 public Map<BlockPos, Integer> pedestalsInv = new HashMap<>();
52 public boolean populated = false;
53
54 public CosmicAltarBlockEntity(BlockPos pos, BlockState state) {
55 super(ModBlockEntities.COSMIC_ALTAR.get(), pos, state);
56 this.vibrationUser = new CosmicAltarBlockEntity.User(this);
57 this.vibrationData = new VibrationSystem.Data();
58 this.vibrationListener = new VibrationSystem.Listener(this);
59 }
60
61 void clear() {
62 error.clear();
63 pedestals.clear();
64 pedestalsInv.clear();
65 populated = false;
66 }
67
68 void updatePedestals(ServerLevel level, BlockPos pos,
69 //? if <1.21 {
70 /*GameEvent
71 *///?} else {
72 Holder<GameEvent>
73 //?}
74 event) {
75 if (VersionMethods.gameEventsEqual(event, GameEvent.BLOCK_PLACE)) addPedestal(level, pos);
76 if (VersionMethods.gameEventsEqual(event, GameEvent.BLOCK_CHANGE)) {
77 popPedestal(pos);
78 addPedestal(level, pos);
79 }
80 if (VersionMethods.gameEventsEqual(event, GameEvent.BLOCK_DESTROY)) popPedestal(pos);
81 sync();
82 }
83
84 void addPedestal(Level level, BlockPos pos) {
85 if (pedestalsInv.containsKey(pos)) return;
86 int i = VersionMethods.getPropertyOrElse(level.getBlockState(pos), AltarBlock.COLOR, 0);
87 assert i < numColors;
88 addPedestal(pos, i);
89 }
90
91 void addPedestal(BlockPos pos, int i) {
92 pedestalsInv.put(pos, i);
93
94 if (!pedestals.containsKey(i))
95 pedestals.put(i, new HashSet<>());
96
97 else if (i != 0) error.add(i);
98
99 pedestals.get(i).add(pos);
100
101 populated = true;
102 }
103
104 void popPedestal(BlockPos pos) {
105 if (!pedestalsInv.containsKey(pos)) return;
106
107 int i = pedestalsInv.get(pos);
108 pedestalsInv.remove(pos);
109
110 if (pedestals.containsKey(i)) {
111 pedestals.get(i).remove(pos);
112
113 if (pedestals.get(i).isEmpty())
114 pedestals.remove(i);
115
116 else if (i != 0 && pedestals.get(i).size() == 1)
117 error.remove(i);
118 }
119
120 if (pedestals.isEmpty()) populated = false;
121 }
122
123 //? if >1.21 {
124 @Override
125 public boolean isValidBlockState(BlockState state) {
126 return true;
127 }
128 //?}
129
130 //? if >1.21.4 {
131 public void saveAdditional(ValueOutput tag) {
132 super.saveAdditional(tag);
133//?} else if >1.21 {
134 /*public void saveAdditional(CompoundTag tag, HolderLookup.Provider registryLookup) {
135 super.saveAdditional(tag, registryLookup);
136*///?} else {
137 /*public void saveAdditional(CompoundTag tag) {
138 super.saveAdditional(tag);
139*///?}
140 CompoundTag res = new CompoundTag();
141 if (populated) {
142 ListTag pds = new ListTag();
143 pedestalsInv.keySet().forEach(p -> {
144 CompoundTag pd = new CompoundTag();
145 pd.put("pos", NbtUtils.wrapBP(p));
146 pd.putInt("i", pedestalsInv.get(p));
147 pds.add(pd);
148 });
149 res.put("pedestals", pds);
150 }
151 VersionMethods.saveBlockEntityData(tag, res);
152 }
153
154 //? if >1.21.4 {
155 public void loadAdditional(ValueInput tag) {
156 super.loadAdditional(tag);
157//?} else if >1.21 {
158 /*public void loadAdditional(CompoundTag tag, HolderLookup.Provider registryLookup) {
159 super.loadAdditional(tag, registryLookup);
160*///?} else {
161 /*public void load(CompoundTag tag) {
162 super.load(tag);
163*///?}
164 clear();
165 CompoundTag res = VersionMethods.loadBlockEntityData(tag);
166 ListTag t = NbtUtils.getList(res, "pedestals", Tag.TAG_COMPOUND);
167 for (Tag tg: t) if (tg instanceof CompoundTag pos) {
168 BlockPos p = NbtUtils.unwrapBP(NbtUtils.getCompound(pos, "pos"));
169 addPedestal(p, NbtUtils.getInt(pos, "i"));
170 }
171 }
172
173 @Nullable
174 @Override
175 public ClientboundBlockEntityDataPacket getUpdatePacket() {
176 return ClientboundBlockEntityDataPacket.create(this);
177 }
178
179 @Override
180 public CompoundTag getUpdateTag(
181 //? if >1.21
182 HolderLookup.Provider registryLookup
183 ) {
184 return saveWithoutMetadata(
185 //? if >1.21
186 registryLookup
187 );
188 }
189
190 @Override
191 public VibrationSystem.Listener getListener() {
192 return this.vibrationListener;
193 }
194 @Override
195 public VibrationSystem.Data getVibrationData() {
196 return this.vibrationData;
197 }
198 @Override
199 public VibrationSystem.User getVibrationUser() {
200 return this.vibrationUser;
201 }
202
203 @Override
204 public int getTint() {
205 return -1;
206 }
207
208 public static class User implements VibrationSystem.User {
209 protected final BlockPos pos;
210 private final PositionSource positionSource;
211 private final CosmicAltarBlockEntity parent;
212
213 public User(CosmicAltarBlockEntity parent) {
214 this.pos = parent.getBlockPos();
215 this.positionSource = new BlockPositionSource(pos);
216 this.parent = parent;
217 }
218
219 @Override
220 public int getListenerRadius() {
221 return 6;
222 }
223
224 @Override
225 public PositionSource getPositionSource() {
226 return positionSource;
227 }
228
229
230 //? if <1.21 {
231 /*@Override
232 public boolean canReceiveVibration(ServerLevel level, BlockPos pos, GameEvent gameEvent, GameEvent.Context context) {
233 *///?} else {
234 @Override
235 public boolean canReceiveVibration(ServerLevel level, BlockPos pos, Holder<GameEvent> gameEvent, GameEvent.Context context) {
236 //?}
237 boolean bl = ((!pos.equals(this.pos)) &&
238 pos.getY() == this.pos.getY() &&
239 (VersionMethods.gameEventsEqual(gameEvent, GameEvent.BLOCK_DESTROY)
240 || VersionMethods.gameEventsEqual(gameEvent, GameEvent.BLOCK_PLACE)
241 || VersionMethods.gameEventsEqual(gameEvent, GameEvent.BLOCK_CHANGE))
242 && context.affectedState() != null
243 && context.affectedState().getBlock() instanceof AltarBlock
244 );
245 if (bl) parent.updatePedestals(level, pos, gameEvent);
246 return bl;
247 }
248
249 @Override
250 //? if <1.21 {
251 /*public void onReceiveVibration(ServerLevel serverLevel, BlockPos blockPos, GameEvent gameEvent, @Nullable Entity entity, @Nullable Entity entity1, float v) {
252 *///?} else {
253 public void onReceiveVibration(ServerLevel level, BlockPos pos, Holder<GameEvent> gameEvent, @Nullable Entity entity, @Nullable Entity playerEntity, float distance) {
254 //?}
255 }
256 }
257}