Inspired by 2020's April Fools' 20w14infinite Snapshot, this mod brings endless randomly generated dimensions into Minecraft.
1package net.lerariemann.infinity.util;
2
3import com.google.common.hash.HashCode;
4import com.google.common.hash.Hashing;
5import dev.architectury.platform.Platform;
6import net.lerariemann.infinity.InfinityMod;
7import net.lerariemann.infinity.access.Timebombable;
8import net.lerariemann.infinity.block.entity.BiomeBottleBlockEntity;
9import net.lerariemann.infinity.block.entity.InfinityPortalBlockEntity;
10import net.lerariemann.infinity.block.entity.TintableBlockEntity;
11import net.lerariemann.infinity.registry.core.ModComponentTypes;
12import net.lerariemann.infinity.registry.core.ModItems;
13import net.lerariemann.infinity.util.core.RandomProvider;
14import net.minecraft.block.BlockState;
15import net.minecraft.block.entity.BlockEntity;
16import net.minecraft.item.ItemStack;
17import net.minecraft.registry.RegistryKey;
18import net.minecraft.registry.entry.RegistryEntry;
19import net.minecraft.server.network.ServerPlayerEntity;
20import net.minecraft.server.world.ServerWorld;
21import net.minecraft.text.MutableText;
22import net.minecraft.text.Text;
23import net.minecraft.util.DyeColor;
24import net.minecraft.util.Identifier;
25import net.minecraft.util.Util;
26import net.minecraft.util.math.BlockPos;
27import net.minecraft.util.math.MathHelper;
28import net.minecraft.util.math.noise.DoublePerlinNoiseSampler;
29import net.minecraft.util.math.random.CheckedRandom;
30import net.minecraft.util.math.random.Random;
31import net.minecraft.world.BlockRenderView;
32import net.minecraft.world.BlockView;
33import net.minecraft.world.World;
34import net.minecraft.world.WorldAccess;
35import net.minecraft.world.biome.Biome;
36
37import java.nio.charset.StandardCharsets;
38import java.util.Arrays;
39import java.util.concurrent.atomic.AtomicBoolean;
40
41/** Common mod methods that work identically on Fabric and NeoForge.
42 * @see PlatformMethods */
43public interface InfinityMethods {
44 String ofRandomDim = "infinity:random";
45 DoublePerlinNoiseSampler sampler =
46 DoublePerlinNoiseSampler.create(new CheckedRandom(0L), -5, genOctaves(2));
47
48 static double[] genOctaves(int octaves){
49 double[] a = new double[octaves];
50 Arrays.fill(a, 1);
51 return a;
52 }
53 static double sample(BlockPos pos) {
54 return sampler.sample(pos.getX(), pos.getY(), pos.getZ());
55 }
56
57 /**
58 * Converts a string to an identifier in the Infinite Dimensions namespace.
59 */
60 static Identifier getId(String value){
61 return Identifier.of(InfinityMod.MOD_ID, value);
62 }
63
64 /**
65 * Converts a dimension's long value to an identifier in the Infinite Dimensions namespace.
66 */
67 static Identifier getDimId(long value){
68 return getId("generated_" + value);
69 }
70
71 /**
72 * Checks if a dimension is an Infinite Dimension.
73 */
74 static boolean isInfinity(World w) {
75 return isInfinity(w.getRegistryKey());
76 }
77 static boolean isInfinity(RegistryKey<World> key) {
78 return key.getValue().getNamespace().equals(InfinityMod.MOD_ID);
79 }
80 static boolean isBiomeInfinity(WorldAccess world, BlockPos pos) {
81 AtomicBoolean bl = new AtomicBoolean(false);
82 world.getBiome(pos).getKey().ifPresent(key ->
83 bl.set(key.getValue().getNamespace().equals("infinity")));
84 return bl.get();
85 }
86 static boolean isBiomeInfinity(RegistryEntry<Biome> b) {
87 return b.getKey().get().getValue().getNamespace().equals("infinity");
88 }
89 static boolean isBiomeInfinity(BlockView world, BlockPos pos) {
90 if (world instanceof WorldAccess acc) {
91 return InfinityMethods.isBiomeInfinity(acc, pos);
92 }
93 else return Platform.isFabric()
94 && world.hasBiomes()
95 && world.getBiomeFabric(pos) instanceof RegistryEntry<Biome>
96 && InfinityMethods.isBiomeInfinity(world.getBiomeFabric(pos));
97 }
98
99 /**
100 * Checks if a mod designed for Fabric (using - instead of _) is loaded.
101 * This is most commonly used for FFAPI modules, but also applies to mods
102 * like Item Descriptions or Cloth Config.
103 */
104 static boolean isFabricApiLoaded(String modID) {
105 if (Platform.isFabric()) return Platform.isModLoaded(modID.replace("_", "-"));
106 else return Platform.isModLoaded(modID.replace("-", "_"));
107 }
108
109 static double sample(int x, int y, int z) {
110 return sampler.sample(x, y, z);
111 }
112
113 static int properMod(int a, int b) {
114 int res = a%b;
115 return (res >= 0) ? res : b + res;
116 }
117
118 static void sendUnexpectedError(ServerPlayerEntity player, String type) {
119 player.sendMessage(Text.translatable("error.infinity." + type + ".unexpected"));
120 }
121
122 /**
123 * Convert a provided string into a dimension ID.
124 * This also checks if it matches an Easter Egg dimension.
125 */
126 static Identifier dimTextToId(String text) {
127 if (text.equals("abatised redivides"))
128 return World.END.getValue();
129 if (text.isEmpty())
130 return InfinityMethods.getId("missingno");
131 String easterId = InfinityMod.provider.easterizer.getAsEaster(text);
132 if (easterId != null)
133 return InfinityMethods.getId(easterId);
134 return InfinityMethods.getDimId(getDimensionSeed(text));
135 }
136
137 static boolean isTimebombed(ServerWorld world) {
138 return ((Timebombable)world).infinity$isTimebombed();
139 }
140
141 /**
142 * Check if a dimension exists and has not been timebombed.
143 */
144 static boolean dimExists(ServerWorld world) {
145 return (world != null && !isTimebombed(world));
146 }
147
148 /**
149 * Hashes text into dimension ID.
150 */
151 static long getDimensionSeed(String text) {
152 HashCode f = Hashing.sha256().hashString(text + InfinityMod.provider.salt, StandardCharsets.UTF_8);
153 return InfinityMethods.longArithmeticEnabled() ? f.asLong() & Long.MAX_VALUE : f.asInt() & Integer.MAX_VALUE;
154 }
155
156 static long getNumericFromId(Identifier id) {
157 String dimensionName = id.getPath();
158 String numericId = dimensionName.substring(dimensionName.lastIndexOf("_") + 1);
159 long i;
160 try {
161 i = Long.parseLong(numericId);
162 } catch (Exception e) {
163 /* Simply hash the name if it isn't of "generated_..." format. */
164 i = getDimensionSeed(numericId);
165 }
166 return i;
167 }
168
169 private static float bookBoxSample(BlockPos pos, int offset) {
170 return MathHelper.clamp(0.5f * (1f + (float)sampler.sample(4*pos.getX(), 4*(pos.getY() + offset), 4*pos.getZ())), 0f, 1f);
171 }
172 static int getBookBoxColor(BlockState state, BlockRenderView world, BlockPos pos, int tintIndex) {
173 if (pos != null) {
174 float r = bookBoxSample(pos, -1000);
175 float g = bookBoxSample(pos, 0);
176 float b = bookBoxSample(pos, 1000);
177 return MathHelper.packRgb(r, g, b);
178 }
179 return 16777215;
180 }
181
182 static int getOverlayColorFromComponents(ItemStack stack, int layer) {
183 if (stack.getNbt() != null) {
184 if (layer == 1) {
185 if (stack.isOf(ModItems.TRANSFINITE_KEY.get()))
186 return stack.getNbt().getInt(ModComponentTypes.COLOR);
187 else if (stack.isOf(ModItems.BIOME_BOTTLE_ITEM.get())) {
188 return stack.getNbt().getCompound("BlockEntityTag").getInt("Color");
189 }
190 else if (stack.isOf(ModItems.F4.get())) {
191 return BackportMethods.getOrDefaultInt(stack, ModComponentTypes.COLOR, 10879231);
192 }
193 }
194 else if (stack.isOf(ModItems.CHROMATIC_MATTER.get()) || stack.isOf(ModItems.CHROMATIC_WOOL.get()) || stack.isOf(ModItems.CHROMATIC_CARPET.get()))
195 return stack.getNbt().getInt(ModComponentTypes.COLOR);
196 }
197 return 0xFFFFFF;
198 }
199
200 static int getPortalItemColor(ItemStack stack, int layer) {
201 return 0x00FFFF;
202 }
203
204 /**
205 * For use in color providers with blocks which the block entity sets color for.
206 */
207 static int getBlockEntityColor(BlockState state, BlockRenderView world, BlockPos pos, int tintIndex) {
208 if (world != null && pos != null) {
209 BlockEntity blockEntity = world.getBlockEntity(pos);
210 if (blockEntity instanceof TintableBlockEntity be) {
211 Object j = be.getTint();
212 return (int)j & 0xFFFFFF;
213 }
214 }
215 return 0xFFFFFF;
216 }
217
218 static int getKeyColorFromId(Identifier id) {
219 if(id.getNamespace().equals(InfinityMod.MOD_ID) && id.getPath().contains("generated_"))
220 return Math.toIntExact(getNumericFromId(id));
221 return 0;
222 }
223
224 static long getRandomSeed(java.util.Random random) {
225 return longArithmeticEnabled() ? random.nextLong() : random.nextInt();
226 }
227
228 static long getRandomSeed(Random random) {
229 return longArithmeticEnabled() ? random.nextLong() : random.nextInt();
230 }
231
232 static Identifier getRandomId(java.util.Random random) {
233 return getDimId(getRandomSeed(random));
234 }
235 static Identifier getRandomId(Random random) {
236 return getDimId(getRandomSeed(random));
237 }
238
239 static MutableText getDimensionNameAsText(Identifier dimension) {
240 String name = dimension.toString();
241 // Randomly generated dimensions.
242 if (name.contains("infinity:generated_"))
243 return Text.translatable("tooltip.infinity.key.generated")
244 .append(name.replace("infinity:generated_", ""));
245 if (name.equals(InfinityMethods.ofRandomDim))
246 return Text.translatable("tooltip.infinity.key.randomise");
247 // All other dimensions.
248 return Text.translatableWithFallback(
249 Util.createTranslationKey("dimension", dimension),
250 InfinityMethods.formatAsTitleCase(dimension.getPath()));
251 }
252
253 /**
254 * Creates a fallback for texts without translation by replacing underscores
255 * with spaces and formatting the text as Title Case.
256 */
257 static String formatAsTitleCase(String text) {
258 text = text.replaceAll("[_./]", " ");
259 //i am sure java has a smarter way to do title case, but this works too
260 StringBuilder newText = new StringBuilder();
261 int i = 0;
262 for (Character c : text.toCharArray()) {
263 if (i == 0) {
264 c = c.toString().toUpperCase().charAt(0);
265 }
266 newText.append(c);
267 i++;
268 if (c == ' ') {
269 i = 0;
270 }
271 }
272 return newText.toString();
273 }
274
275 static boolean chaosMobsEnabled() {
276 return RandomProvider.rule("chaosMobsEnabled");
277 }
278
279 static boolean longArithmeticEnabled() {
280 return RandomProvider.rule("longArithmeticEnabled");
281 }
282
283 static boolean isCreateLoaded() {
284 if (Platform.isModLoaded("create")) {
285 return Platform.getMod("create").getVersion().charAt(0) != '5';
286 }
287 return false;
288 }
289}