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