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.Boopable;
4import net.lerariemann.infinity.registry.core.ModBlockEntities;
5import net.lerariemann.infinity.registry.core.ModComponentTypes;
6import net.lerariemann.infinity.registry.core.ModItems;
7import net.lerariemann.infinity.util.core.NbtUtils;
8import net.lerariemann.infinity.util.var.ColorLogic;
9import net.minecraft.core.BlockPos;
10//? if >1.21 {
11import net.minecraft.core.HolderLookup;
12import net.minecraft.core.component.DataComponentMap;
13import net.lerariemann.infinity.registry.core.ModComponentTypes;
14//?}
15//? if >1.21.4 {
16import net.minecraft.core.component.DataComponentGetter;
17//?}
18import net.minecraft.nbt.CompoundTag;
19import net.minecraft.nbt.Tag;
20import net.minecraft.network.chat.contents.NbtContents;
21import net.minecraft.network.protocol.Packet;
22import net.minecraft.network.protocol.game.ClientGamePacketListener;
23import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
24import net.minecraft.sounds.SoundEvent;
25import net.minecraft.sounds.SoundEvents;
26import net.minecraft.sounds.SoundSource;
27import net.minecraft.world.item.DyeItem;
28import net.minecraft.world.item.ItemStack;
29import net.minecraft.world.item.Items;
30import net.minecraft.world.level.Level;
31import net.minecraft.world.level.block.entity.BlockEntity;
32import net.minecraft.world.level.block.state.BlockState;
33//? if >1.21.4 {
34import net.minecraft.world.level.storage.ValueInput;
35import net.minecraft.world.level.storage.ValueOutput;
36//?}
37import org.jetbrains.annotations.Nullable;
38
39import java.awt.*;
40import java.util.concurrent.atomic.AtomicBoolean;
41
42public class ChromaticBlockEntity extends TintableBlockEntity {
43 public short hue;
44 public short saturation;
45 public short brightness;
46 public int color;
47 public ChromaticBlockEntity(BlockPos pos, BlockState state) {
48 super(ModBlockEntities.CHROMATIC.get(), pos, state);
49 hue = 0;
50 saturation = 0;
51 brightness = 255;
52 }
53
54 public void setColor(int colorHex) {
55 setColor(colorHex, null);
56 }
57
58 public void setColor(int hue, int saturation, int brightness, @Nullable AtomicBoolean cancel) {
59 if (cancel != null && this.hue == hue && this.saturation == saturation && this.brightness == brightness) {
60 cancel.set(true);
61 return;
62 }
63 this.hue = (short)hue;
64 this.saturation = (short)saturation;
65 this.brightness = (short)brightness;
66 updateColor();
67 sync();
68 }
69
70 public void setColor(int colorHex, @Nullable AtomicBoolean cancel) {
71 if (cancel != null && colorHex == color) {
72 cancel.set(true);
73 return;
74 }
75 Color c = (new Color(colorHex));
76 float[] hsb = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null);
77 hue = (short)(hsb[0] * 360);
78 saturation = (short)(hsb[1] * 255);
79 brightness = (short)(hsb[2] * 255);
80 color = colorHex;
81 sync();
82 }
83 public void updateColor() {
84 color = Color.HSBtoRGB(hue / 360f, saturation / 255f, brightness / 255f) & 0xFFFFFF;
85 }
86
87 //? if >1.21 {
88 @Override
89 protected void collectImplicitComponents(DataComponentMap.Builder componentMapBuilder) {
90 super.collectImplicitComponents(componentMapBuilder);
91 componentMapBuilder.set(ModComponentTypes.COLOR.get(), color);
92 }
93 @Override
94 protected void applyImplicitComponents(
95 //? if >1.21.4 {
96 DataComponentGetter
97 //?} else {
98 /*DataComponentInput
99 *///?}
100 components) {
101 super.applyImplicitComponents(components);
102 setColor(components.getOrDefault(ModComponentTypes.COLOR.get(), 0xFFFFFF));
103 }
104
105 public static DataComponentMap asMap(int i) {
106 return DataComponentMap.builder()
107 .set(ModComponentTypes.COLOR.get(), i)
108 .build();
109 }
110 public DataComponentMap asMap() {
111 return asMap(getTint());
112 }
113 //?} else {
114 /*public CompoundTag asMap() {
115 CompoundTag compoundTag = new CompoundTag();
116 compoundTag.putInt(ModComponentTypes.COLOR, getTint());
117 return compoundTag;
118 }
119 *///?}
120 public short offset(short orig, short amount, AtomicBoolean cancel) {
121 if (amount < 0 ? orig == 0 : orig == 255) {
122 cancel.set(true);
123 return orig;
124 }
125 orig += amount;
126 if (orig < 0) orig = 0;
127 else if (orig > 255) orig = 255;
128 return orig;
129 }
130 public boolean onUse(Level world, BlockPos pos, ItemStack stack) {
131 SoundEvent event = SoundEvents.NOTE_BLOCK_GUITAR.value();
132 float pitch = -1f;
133 float volume = 1f;
134 AtomicBoolean cancel = new AtomicBoolean(false);
135
136 if (stack.is(Items.AMETHYST_SHARD)) {
137 saturation = offset(saturation, (short) 16, cancel);
138 pitch = saturation / 255f;
139 }
140 else if (stack.is(ModItems.FOOTPRINT.get())) {
141 saturation = offset(saturation, (short) -16, cancel);
142 pitch = saturation / 255f;
143 }
144 else if (stack.is(ModItems.WHITE_MATTER.get())) {
145 brightness = offset(brightness, (short) 16, cancel);
146 pitch = brightness / 255f;
147 }
148 else if (stack.is(ModItems.BLACK_MATTER.get())) {
149 brightness = offset(brightness, (short) -16, cancel);
150 pitch = brightness / 255f;
151 }
152 else if (stack.getItem() instanceof DyeItem dye) {
153 setColor(ColorLogic.getChromaticColor(dye.getDyeColor()), cancel);
154 event = SoundEvents.DYE_USE;
155 }
156 else return false;
157 if (cancel.get()) return false; //block was already at extremal saturation / brightness, no need for side effects
158 updateColor();
159 pitch = pitch < 0 ? 1f : 0.5f + 1.5f * pitch; //scaling for Minecraft's sound system
160 if (!world.isClientSide()) world.playSound(null, pos, event, SoundSource.BLOCKS, volume, pitch);
161 sync();
162 return true;
163 }
164
165 public void onIridStarUse(boolean reverse) {
166 if (reverse) {
167 hue -= 10;
168 if (hue < 0) hue += 360;
169 }
170 else {
171 hue += 10;
172 if (hue > 360) hue -= 360;
173 }
174 updateColor();
175 sync();
176 }
177
178 void sync() {
179 setChanged();
180 if (level != null) {
181 Boopable.boop(level, worldPosition);
182 }
183 }
184
185 //? if >1.21 {
186
187 @Override
188 public void loadAdditional(
189 //? if >1.21.2 {
190 ValueInput nbt
191 //?} else {
192 /*CompoundTag nbt
193 *///?}
194 //? if =1.21.1
195 /*,HolderLookup.Provider registryLookup*/
196 ) {
197 super.loadAdditional(nbt
198 //? if =1.21.1
199 /*, registryLookup*/
200 );
201 //?} else {
202
203 /*@Override
204 public void load(CompoundTag nbt) {
205 super.load(nbt);
206 *///?}
207 //? if >1.21.2 {
208 nbt.getInt("color").ifPresent(this::setColor);
209 if (nbt.getInt("color").isEmpty()) {
210 hue = (short) nbt.getShortOr("h", hue);
211 saturation = (short) nbt.getShortOr("s", saturation);
212 brightness = (short) nbt.getShortOr("b", brightness);
213 updateColor();
214 }
215 //?} else {
216 /*if (nbt.getTagType("color") == Tag.TAG_INT)
217 setColor(nbt.getInt("color"));
218 else if (nbt.getTagType("color") == Tag.TAG_COMPOUND) {
219 CompoundTag color = NbtUtils.getCompound(nbt, "color");
220 hue = NbtUtils.getShort(color, "h");
221 saturation = NbtUtils.getShort(color, "s");
222 brightness = NbtUtils.getShort(color, "b");
223 updateColor();
224 }
225 *///?}
226 }
227 @Override
228 protected void saveAdditional(
229 //? if =1.21.1 || 1.20.1 {
230 /*CompoundTag nbt
231 *///?} else {
232 ValueOutput nbt
233 //?}
234 //? if =1.21.1
235 /*, HolderLookup.Provider registryLookup*/
236 ) {
237 super.saveAdditional(nbt
238 //? if =1.21.1
239 /*, registryLookup*/
240 );
241 //? if >1.21.2 {
242 nbt.putShort("h", hue);
243 nbt.putShort("s", saturation);
244 nbt.putShort("b", brightness);
245 //?} else {
246 /*CompoundTag color = new CompoundTag();
247 color.putShort("h", hue);
248 color.putShort("s", saturation);
249 color.putShort("b", brightness);
250 nbt.put("color", color);
251 *///?}
252
253 }
254
255 public int getTint() {
256 return color;
257 }
258
259 @Nullable
260 @Override
261 public Packet<ClientGamePacketListener> getUpdatePacket() {
262 return ClientboundBlockEntityDataPacket.create(this);
263 }
264 @Override
265 public CompoundTag getUpdateTag(
266 //? if >1.21
267 HolderLookup.Provider registryLookup
268 ) {
269 return saveWithoutMetadata(
270 //? if >1.21
271 registryLookup
272 );
273 }
274}