Bleh POckets
This commit is contained in:
parent
113eb04e0d
commit
642b5582fb
67 changed files with 4004 additions and 308 deletions
|
@ -4,11 +4,17 @@ import dev.architectury.utils.GameInstance;
|
|||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.dimdev.dimdoors.api.DimensionalDoorsApi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DimensionalDoors {
|
||||
public static final String MOD_ID = "dimdoors";
|
||||
public static ResourceLocation id(String id) {
|
||||
public static List<DimensionalDoorsApi> apiSubscribers;
|
||||
|
||||
public static ResourceLocation id(String id) {
|
||||
return new ResourceLocation(MOD_ID, id);
|
||||
}
|
||||
|
||||
|
@ -16,7 +22,7 @@ public class DimensionalDoors {
|
|||
return GameInstance.getServer();
|
||||
}
|
||||
|
||||
public static Level getWorld(ResourceKey<Level> world) {
|
||||
public static ServerLevel getWorld(ResourceKey<Level> world) {
|
||||
return getServer().getLevel(world);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,18 +14,10 @@ import org.dimdev.dimdoors.world.pocket.type.addon.PocketAddon;
|
|||
|
||||
// TODO: javadocs for everything, refactoring
|
||||
public interface DimensionalDoorsApi {
|
||||
default void registerVirtualTargetTypes(Registry<VirtualTarget.VirtualTargetType<?>> registry) {
|
||||
}
|
||||
|
||||
default void registerVirtualSingularPocketTypes(Registry<ImplementedVirtualPocket.VirtualPocketType<?>> registry) {
|
||||
}
|
||||
|
||||
default void registerModifierTypes(Registry<Modifier.ModifierType<?>> registry) {
|
||||
}
|
||||
|
||||
default void registerPocketGeneratorTypes(Registry<PocketGenerator.PocketGeneratorType<?>> registry) {
|
||||
}
|
||||
|
||||
default void registerAbstractPocketTypes(Registry<AbstractPocket.AbstractPocketType<?>> registry) {
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,14 @@ package org.dimdev.dimdoors.api.util;
|
|||
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.nbt.NbtList;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
|
||||
import net.fabricmc.fabric.api.util.NbtType;
|
||||
|
||||
|
@ -41,7 +43,7 @@ public class NbtEquations {
|
|||
} else if (nbt.getType(key) == NbtType.COMPOUND) {
|
||||
solved.put(key, solveNbtCompoundEquations(nbt.getCompound(key), variableMap));
|
||||
} else if (nbt.getType(key) == NbtType.LIST) {
|
||||
solved.put(key, solveNbtListEquations((NbtList) nbt.get(key), variableMap));
|
||||
solved.put(key, solveListTagEquations((ListTag) nbt.get(key), variableMap));
|
||||
} else {
|
||||
solved.put(key, nbt.get(key));
|
||||
}
|
||||
|
@ -49,12 +51,12 @@ public class NbtEquations {
|
|||
return solved;
|
||||
}
|
||||
|
||||
public static NbtList solveNbtListEquations(NbtList nbtList, Map<String, Double> variableMap) {
|
||||
NbtList solved = new NbtList();
|
||||
for (NbtElement nbt : nbtList) {
|
||||
if (nbt.getType() == NbtType.LIST) {
|
||||
solved.add(solveNbtListEquations((NbtList) nbt, variableMap));
|
||||
} else if (nbt.getType() == NbtType.COMPOUND) {
|
||||
public static ListTag solveListTagEquations(ListTag ListTag, Map<String, Double> variableMap) {
|
||||
ListTag solved = new ListTag();
|
||||
for (Tag nbt : ListTag) {
|
||||
if (nbt.getId() == Tag.TAG_LIST) {
|
||||
solved.add(solveListTagEquations((ListTag) nbt, variableMap));
|
||||
} else if (nbt.getId() == Tag.TAG_COMPOUND) {
|
||||
solved.add(solveNbtCompoundEquations((NbtCompound) nbt, variableMap));
|
||||
} else {
|
||||
solved.add(nbt);
|
||||
|
|
|
@ -2,11 +2,13 @@ package org.dimdev.dimdoors.api.util;
|
|||
|
||||
import com.mojang.serialization.Codec;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.nbt.NbtOps;
|
||||
|
||||
import net.fabricmc.fabric.api.util.NbtType;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
public class NbtUtil {
|
||||
public static <T> T deserialize(NbtElement data, Codec<T> codec) {
|
||||
|
@ -19,9 +21,9 @@ public class NbtUtil {
|
|||
});
|
||||
}
|
||||
|
||||
public static NbtCompound asNbtCompound(NbtElement nbt, String error) {
|
||||
if (nbt == null || nbt.getType() == NbtType.COMPOUND) {
|
||||
return (NbtCompound) nbt;
|
||||
public static CompoundTag asNbtCompound(Tag nbt, String error) {
|
||||
if (nbt == null || nbt.getId() == Tag.TAG_COMPOUND) {
|
||||
return (CompoundTag) nbt;
|
||||
}
|
||||
|
||||
throw new RuntimeException(error);
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
package org.dimdev.dimdoors.api.util;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.nbt.NbtOps;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.Resource;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
@ -11,36 +27,19 @@ import java.util.function.BiFunction;
|
|||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.nbt.NbtOps;
|
||||
import net.minecraft.resource.Resource;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class ResourceUtil {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final Gson GSON = new GsonBuilder().setLenient().setPrettyPrinting().create();
|
||||
|
||||
public static final BiFunction<String, Identifier, Path<String>> PATH_KEY_PROVIDER = (startingPath, id) -> Path.stringPath(id.getNamespace() + ":" + id.getPath().substring(0, id.getPath().lastIndexOf(".")).substring(startingPath.length() + (startingPath.endsWith("/") ? 0 : 1)));
|
||||
public static final BiFunction<String, ResourceLocation, Path<String>> PATH_KEY_PROVIDER = (startingPath, id) -> Path.stringPath(id.getNamespace() + ":" + id.getPath().substring(0, id.getPath().lastIndexOf(".")).substring(startingPath.length() + (startingPath.endsWith("/") ? 0 : 1)));
|
||||
|
||||
public static final ComposableFunction<JsonElement, NbtElement> JSON_TO_NBT = json -> JsonOps.INSTANCE.convertTo(NbtOps.INSTANCE, json);
|
||||
public static final ComposableFunction<JsonElement, Tag> JSON_TO_NBT = json -> JsonOps.INSTANCE.convertTo(NbtOps.INSTANCE, json);
|
||||
|
||||
public static final ComposableFunction<NbtElement, JsonElement> NBT_TO_JSON = json -> NbtOps.INSTANCE.convertTo(JsonOps.INSTANCE, json);
|
||||
public static final ComposableFunction<Tag, JsonElement> NBT_TO_JSON = json -> NbtOps.INSTANCE.convertTo(JsonOps.INSTANCE, json);
|
||||
|
||||
public static final ComposableFunction<InputStream, JsonElement> JSON_READER = inputStream -> GSON.fromJson(new InputStreamReader(inputStream), JsonElement.class);
|
||||
public static final ComposableFunction<InputStream, NbtElement> NBT_READER = JSON_READER.andThenComposable(JSON_TO_NBT);
|
||||
public static final ComposableFunction<InputStream, NbtCompound> COMPRESSED_NBT_READER = inputStream -> {
|
||||
public static final ComposableFunction<InputStream, Tag> NBT_READER = JSON_READER.andThenComposable(JSON_TO_NBT);
|
||||
public static final ComposableFunction<InputStream, CompoundTag> COMPRESSED_NBT_READER = inputStream -> {
|
||||
try {
|
||||
return NbtIo.readCompressed(inputStream);
|
||||
} catch (IOException e) {
|
||||
|
@ -67,28 +66,28 @@ public class ResourceUtil {
|
|||
|
||||
String identifier = splitResourceKey[splitResourceKey.length - 1];
|
||||
int identifierSplitIndex = identifier.indexOf(':');
|
||||
R resource = loadResource(manager, new Identifier(identifier.substring(0, identifierSplitIndex), startingPath + identifier.substring(identifierSplitIndex + 1)), reader);
|
||||
R resource = loadResource(manager, new ResourceLocation(identifier.substring(0, identifierSplitIndex), startingPath + identifier.substring(identifierSplitIndex + 1)), reader);
|
||||
resource.processFlags(flags);
|
||||
return resource;
|
||||
}
|
||||
|
||||
public static <R> R loadResource(ResourceManager manager, Identifier resourceKey, Function<InputStream, R> reader) {
|
||||
public static <R> R loadResource(ResourceManager manager, ResourceLocation resourceKey, Function<InputStream, R> reader) {
|
||||
try {
|
||||
return reader.apply(manager.getResource(resourceKey).get().getInputStream());
|
||||
return reader.apply(manager.getResource(resourceKey).get().open());
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <K, T, M extends Map<K, T>> CompletableFuture<M> loadResourcePathToMap(ResourceManager manager, String startingPath, String extension, M map, BiFunction<InputStream, K, T> reader, BiFunction<String, Identifier, K> keyProvider) {
|
||||
Map<Identifier, Resource> ids = manager.findResources(startingPath, str -> str.getPath().endsWith(extension));
|
||||
public static <K, T, M extends Map<K, T>> CompletableFuture<M> loadResourcePathToMap(ResourceManager manager, String startingPath, String extension, M map, BiFunction<InputStream, K, T> reader, BiFunction<String, ResourceLocation, K> keyProvider) {
|
||||
Map<ResourceLocation, Resource> ids = manager.listResources(startingPath, str -> str.getPath().endsWith(extension));
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
map.putAll(ids.entrySet().parallelStream().unordered().collect(new ExceptionHandlingCollector<>(Collectors.toConcurrentMap(
|
||||
id -> keyProvider.apply(startingPath, id.getKey()),
|
||||
id -> {
|
||||
try {
|
||||
return reader.apply(id.getValue().getInputStream(), keyProvider.apply(startingPath, id.getKey()));
|
||||
return reader.apply(id.getValue().open(), keyProvider.apply(startingPath, id.getKey()));
|
||||
} catch (IOException | RuntimeException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -98,12 +97,12 @@ public class ResourceUtil {
|
|||
});
|
||||
}
|
||||
|
||||
public static <T, M extends Collection<T>> CompletableFuture<M> loadResourcePathToCollection(ResourceManager manager, String startingPath, String extension, M collection, BiFunction<InputStream, Identifier, T> reader) {
|
||||
Map<Identifier, Resource> ids = manager.findResources(startingPath, str -> str.getPath().endsWith(extension));
|
||||
public static <T, M extends Collection<T>> CompletableFuture<M> loadResourcePathToCollection(ResourceManager manager, String startingPath, String extension, M collection, BiFunction<InputStream, ResourceLocation, T> reader) {
|
||||
Map<ResourceLocation, Resource> ids = manager.listResources(startingPath, str -> str.getPath().endsWith(extension));
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
collection.addAll(ids.entrySet().parallelStream().unordered().map(id -> {
|
||||
try {
|
||||
return reader.apply(id.getValue().getInputStream(), id.getKey());
|
||||
return reader.apply(id.getValue().open(), id.getKey());
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Error loading resource: " + id, e);
|
||||
return null;
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.mojang.serialization.Lifecycle;
|
|||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.SimpleRegistry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
|
||||
|
@ -32,7 +33,7 @@ public interface Condition {
|
|||
ConditionType<?> getType();
|
||||
|
||||
static Condition fromJson(JsonObject json) {
|
||||
Identifier type = new Identifier(json.getAsJsonPrimitive("type").getAsString());
|
||||
ResourceLocation type = new ResourceLocation(json.getAsJsonPrimitive("type").getAsString());
|
||||
return Objects.requireNonNull(REGISTRY.get(type)).fromJson(json);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
|||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import org.dimdev.dimdoors.api.block.CustomBreakBlock;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
@ -23,26 +23,31 @@ import java.util.function.Consumer;
|
|||
@Mixin(Level.class)
|
||||
public abstract class WorldMixin {
|
||||
|
||||
@Shadow public abstract FluidState getFluidState(BlockPos arg);
|
||||
|
||||
/*
|
||||
I thought about redirecting the entire break method to be handled by the block itself,
|
||||
but I am not quite sure what that would mean for compatibility with other mixins,
|
||||
since then a large part of the method would need to be canceled. This is rather hacky, but it should fulfill the purpose best
|
||||
~CreepyCre
|
||||
*/
|
||||
I thought about redirecting the entire break method to be handled by the block itself,
|
||||
but I am not quite sure what that would mean for compatibility with other mixins,
|
||||
since then a large part of the method would need to be canceled. This is rather hacky, but it should fulfill the purpose best
|
||||
~CreepyCre
|
||||
*/
|
||||
/*
|
||||
Original mixin had a breakingEntity. Mixins are being a but so removed to get working.
|
||||
- Waterpicker
|
||||
*/
|
||||
@Redirect(method = "destroyBlock",
|
||||
at = @At(value = "INVOKE_ASSIGN",
|
||||
target = "Lnet/minecraft/world/level/Level;getFluidState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/material/FluidState;",
|
||||
ordinal = 0))
|
||||
private FluidState replaceFluidStateWithCustomHackyFluidState(FluidState original, BlockPos pos, boolean drop, @Nullable Entity breakingEntity, int maxUpdateDepth) { //TODO: Fix
|
||||
Level world = (Level) (Object) this;
|
||||
private FluidState replaceFluidStateWithCustomHackyFluidState(Level world, BlockPos pos) { //TODO: Fix
|
||||
BlockState blockState = world.getBlockState(pos);
|
||||
Block block = blockState.getBlock();
|
||||
if (!(block instanceof CustomBreakBlock)) {
|
||||
return original;
|
||||
return world.getFluidState(pos);
|
||||
}
|
||||
InteractionResultHolder<Pair<BlockState, Consumer<BlockEntity>>> result = ((CustomBreakBlock) block).customBreakBlock(world, pos, blockState, breakingEntity);
|
||||
InteractionResultHolder<Pair<BlockState, Consumer<BlockEntity>>> result = ((CustomBreakBlock) block).customBreakBlock(world, pos, blockState, null);
|
||||
if (!result.getResult().consumesAction()) {
|
||||
return original;
|
||||
return getFluidState(pos);
|
||||
}
|
||||
Pair<BlockState, Consumer<BlockEntity>> pair = result.getObject();
|
||||
return new CustomBreakBlock.HackyFluidState(pair.getFirst(), pair.getSecond());
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.dimdev.dimdoors.pockets;
|
|||
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
|
@ -9,7 +10,7 @@ import org.dimdev.dimdoors.rift.registry.LinkProperties;
|
|||
import org.dimdev.dimdoors.rift.targets.VirtualTarget;
|
||||
import org.dimdev.dimdoors.world.pocket.VirtualLocation;
|
||||
|
||||
public record PocketGenerationContext(ServerWorld world, VirtualLocation sourceVirtualLocation, VirtualTarget linkTo, LinkProperties linkProperties) {
|
||||
public record PocketGenerationContext(ServerLevel world, VirtualLocation sourceVirtualLocation, VirtualTarget linkTo, LinkProperties linkProperties) {
|
||||
public Map<String, Double> toVariableMap(Map<String, Double> stringDoubleMap) {
|
||||
stringDoubleMap.put("depth", (double) this.sourceVirtualLocation.getDepth());
|
||||
stringDoubleMap.put("public_size", (double) DimensionalDoors.getConfig().getPocketsConfig().publicPocketSize);
|
||||
|
|
|
@ -1,43 +1,36 @@
|
|||
package org.dimdev.dimdoors.pockets.generator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.chunk.UpgradeData;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
|
||||
import net.minecraft.world.level.levelgen.RandomState;
|
||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.server.world.ServerLightingProvider;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Util;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraft.world.ChunkRegion;
|
||||
import net.minecraft.world.HeightLimitView;
|
||||
import net.minecraft.world.Heightmap;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.ChunkStatus;
|
||||
import net.minecraft.world.chunk.ProtoChunk;
|
||||
import net.minecraft.world.chunk.UpgradeData;
|
||||
import net.minecraft.world.gen.GenerationStep;
|
||||
import net.minecraft.world.gen.chunk.Blender;
|
||||
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
|
||||
import net.minecraft.world.gen.noise.NoiseConfig;
|
||||
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.block.ModBlocks;
|
||||
import org.dimdev.dimdoors.block.entity.DetachedRiftBlockEntity;
|
||||
|
@ -48,11 +41,16 @@ import org.dimdev.dimdoors.world.level.registry.DimensionalRegistry;
|
|||
import org.dimdev.dimdoors.world.pocket.VirtualLocation;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ChunkGenerator extends PocketGenerator {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
public static final String KEY = "chunk";
|
||||
|
||||
private Identifier dimensionID;
|
||||
private ResourceLocation dimensionID;
|
||||
private Vec3i size; // TODO: equation-ify
|
||||
private int virtualYOffset; // TODO: equation-ify
|
||||
|
||||
|
@ -60,10 +58,10 @@ public class ChunkGenerator extends PocketGenerator {
|
|||
}
|
||||
|
||||
@Override
|
||||
public PocketGenerator fromNbt(NbtCompound nbt, ResourceManager manager) {
|
||||
public PocketGenerator fromNbt(CompoundTag nbt, ResourceManager manager) {
|
||||
super.fromNbt(nbt, manager);
|
||||
|
||||
this.dimensionID = new Identifier(nbt.getString("dimension_id"));
|
||||
this.dimensionID = new ResourceLocation(nbt.getString("dimension_id"));
|
||||
|
||||
int[] temp = nbt.getIntArray("size");
|
||||
this.size = new Vec3i(temp[0], temp[1], temp[2]);
|
||||
|
@ -73,7 +71,7 @@ public class ChunkGenerator extends PocketGenerator {
|
|||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toNbtInternal(NbtCompound nbt, boolean allowReference) {
|
||||
public CompoundTag toNbtInternal(CompoundTag nbt, boolean allowReference) {
|
||||
super.toNbtInternal(nbt, allowReference);
|
||||
|
||||
nbt.putString("dimension_id", dimensionID.toString());
|
||||
|
@ -84,74 +82,74 @@ public class ChunkGenerator extends PocketGenerator {
|
|||
|
||||
@Override
|
||||
public Pocket prepareAndPlacePocket(PocketGenerationContext parameters, Pocket.PocketBuilder<?, ?> builder) {
|
||||
ServerWorld world = parameters.world();
|
||||
ServerLevel world = parameters.world();
|
||||
VirtualLocation sourceVirtualLocation = parameters.sourceVirtualLocation();
|
||||
|
||||
int chunkSizeX = ((this.size.getX() >> 4) + (this.size.getX() % 16 == 0 ? 0 : 1));
|
||||
int chunkSizeZ = ((this.size.getZ() >> 4) + (this.size.getZ() % 16 == 0 ? 0 : 1));
|
||||
|
||||
Pocket pocket = DimensionalRegistry.getPocketDirectory(world.getRegistryKey()).newPocket(builder);
|
||||
Pocket pocket = DimensionalRegistry.getPocketDirectory(world.dimension()).newPocket(builder);
|
||||
|
||||
LOGGER.info("Generating chunk pocket at location " + pocket.getOrigin());
|
||||
|
||||
ServerWorld genWorld = DimensionalDoors.getWorld(RegistryKey.of(RegistryKeys.WORLD, dimensionID));
|
||||
net.minecraft.world.gen.chunk.ChunkGenerator genWorldChunkGenerator = genWorld.getChunkManager().getChunkGenerator();
|
||||
ServerLevel genWorld = DimensionalDoors.getWorld(ResourceKey.create(Registries.DIMENSION, dimensionID));
|
||||
net.minecraft.world.level.chunk.ChunkGenerator genWorldChunkGenerator = genWorld.getChunkSource().getGenerator();
|
||||
|
||||
NoiseConfig config = NoiseConfig.create(ChunkGeneratorSettings.createMissingSettings(), world.getRegistryManager().get(RegistryKeys.NOISE_PARAMETERS).getReadOnlyWrapper(), world.getSeed());
|
||||
RandomState config = RandomState.create(NoiseGeneratorSettings.dummy(), world.registryAccess().registryOrThrow(Registries.NOISE).asLookup(), world.getSeed());
|
||||
|
||||
ArrayList<Chunk> protoChunks = new ArrayList<>();
|
||||
ArrayList<ChunkAccess> protoChunks = new ArrayList<>();
|
||||
for (int z = 0; z < chunkSizeZ; z++) {
|
||||
for (int x = 0; x < chunkSizeX; x++) {
|
||||
ProtoChunk protoChunk = new ProtoChunk(new ChunkPos(pocket.getOrigin().add(x * 16, 0, z * 16)), UpgradeData.NO_UPGRADE_DATA, world, genWorld.getRegistryManager().get(RegistryKeys.BIOME), null);
|
||||
protoChunk.setLightingProvider(genWorld.getLightingProvider());
|
||||
ProtoChunk protoChunk = new ProtoChunk(new ChunkPos(pocket.getOrigin().offset(x * 16, 0, z * 16)), UpgradeData.EMPTY, world, genWorld.registryAccess().registryOrThrow(Registries.BIOME), null);
|
||||
protoChunk.setLightEngine(genWorld.getLightEngine());
|
||||
protoChunks.add(protoChunk);
|
||||
}
|
||||
}
|
||||
ChunkRegion protoRegion = new ChunkRegionHack(genWorld, protoChunks);//TODO Redo?
|
||||
for (Chunk protoChunk : protoChunks) { // TODO: check wether structures are even activated
|
||||
genWorldChunkGenerator.setStructureStarts(genWorld.getRegistryManager(), genWorld.getChunkManager().getStructurePlacementCalculator(), genWorld.getStructureAccessor(), protoChunk, genWorld.getStructureTemplateManager());
|
||||
WorldGenRegion protoRegion = new ChunkRegionHack(genWorld, protoChunks);//TODO Redo?
|
||||
for (ChunkAccess protoChunk : protoChunks) { // TODO: check wether structures are even activated
|
||||
genWorldChunkGenerator.createStructures(genWorld.registryAccess(), genWorld.getChunkSource().getGeneratorState(), genWorld.structureManager(), protoChunk, genWorld.getStructureManager());
|
||||
((ProtoChunk) protoChunk).setStatus(ChunkStatus.STRUCTURE_STARTS);
|
||||
}
|
||||
for (Chunk protoChunk : protoChunks) {
|
||||
genWorldChunkGenerator.addStructureReferences(protoRegion, genWorld.getStructureAccessor().forRegion(protoRegion), protoChunk);
|
||||
for (ChunkAccess protoChunk : protoChunks) {
|
||||
genWorldChunkGenerator.createReferences(protoRegion, genWorld.structureManager().forWorldGenRegion(protoRegion), protoChunk);
|
||||
((ProtoChunk) protoChunk).setStatus(ChunkStatus.STRUCTURE_REFERENCES);
|
||||
}
|
||||
for (Chunk protoChunk : protoChunks) {
|
||||
genWorldChunkGenerator.populateBiomes(Util.getMainWorkerExecutor(), config, Blender.getNoBlending(), genWorld.getStructureAccessor(), protoChunk);
|
||||
for (ChunkAccess protoChunk : protoChunks) {
|
||||
genWorldChunkGenerator.createBiomes(Util.backgroundExecutor(), config, Blender.empty(), genWorld.structureManager(), protoChunk);
|
||||
((ProtoChunk) protoChunk).setStatus(ChunkStatus.BIOMES);
|
||||
}
|
||||
for (Chunk protoChunk : protoChunks) {
|
||||
for (ChunkAccess protoChunk : protoChunks) {
|
||||
try {
|
||||
genWorldChunkGenerator.populateNoise(net.minecraft.util.Util.getMainWorkerExecutor(), Blender.getNoBlending(), config, genWorld.getStructureAccessor().forRegion(protoRegion), protoChunk).get();
|
||||
genWorldChunkGenerator.fillFromNoise(Util.backgroundExecutor(), Blender.empty(), config, genWorld.structureManager().forWorldGenRegion(protoRegion), protoChunk).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
((ProtoChunk) protoChunk).setStatus(ChunkStatus.NOISE);
|
||||
}
|
||||
for (Chunk protoChunk : protoChunks) {
|
||||
genWorldChunkGenerator.buildSurface(protoRegion, genWorld.getStructureAccessor(), config, protoChunk);
|
||||
for (ChunkAccess protoChunk : protoChunks) {
|
||||
genWorldChunkGenerator.buildSurface(protoRegion, genWorld.structureManager(), config, protoChunk);
|
||||
((ProtoChunk) protoChunk).setStatus(ChunkStatus.SURFACE);
|
||||
}
|
||||
for (GenerationStep.Carver carver : GenerationStep.Carver.values()) {
|
||||
for (Chunk protoChunk : protoChunks) {
|
||||
genWorldChunkGenerator.carve(protoRegion, genWorld.getSeed(), config, genWorld.getBiomeAccess(), genWorld.getStructureAccessor(), protoChunk, carver);
|
||||
for (GenerationStep.Carving carver : GenerationStep.Carving.values()) {
|
||||
for (ChunkAccess protoChunk : protoChunks) {
|
||||
genWorldChunkGenerator.applyCarvers(protoRegion, genWorld.getSeed(), config, genWorld.getBiomeManager(), genWorld.structureManager(), protoChunk, carver);
|
||||
ProtoChunk pChunk = ((ProtoChunk) protoChunk);
|
||||
if (pChunk.getStatus() == ChunkStatus.SURFACE) pChunk.setStatus(ChunkStatus.CARVERS);
|
||||
else pChunk.setStatus(ChunkStatus.LIQUID_CARVERS);
|
||||
}
|
||||
}
|
||||
for (Chunk protoChunk : protoChunks) {
|
||||
ChunkRegion tempRegion = new ChunkRegionHack(genWorld, ChunkPos.stream(protoChunk.getPos(), 10).map(chunkPos -> protoRegion.getChunk(chunkPos.x, chunkPos.z)).collect(Collectors.toList()));
|
||||
genWorldChunkGenerator.generateFeatures(tempRegion, protoChunk, genWorld.getStructureAccessor().forRegion(tempRegion));
|
||||
for (ChunkAccess protoChunk : protoChunks) {
|
||||
WorldGenRegion tempRegion = new ChunkRegionHack(genWorld, ChunkPos.rangeClosed(protoChunk.getPos(), 10).map(chunkPos -> protoRegion.getChunk(chunkPos.x, chunkPos.z)).collect(Collectors.toList()));
|
||||
genWorldChunkGenerator.applyBiomeDecoration(tempRegion, protoChunk, genWorld.structureManager().forWorldGenRegion(tempRegion));
|
||||
((ProtoChunk) protoChunk).setStatus(ChunkStatus.FEATURES);
|
||||
}
|
||||
for (Chunk protoChunk : protoChunks) { // likely only necessary for spawn step since we copy over anyways
|
||||
((ServerLightingProvider) genWorld.getLightingProvider()).light(protoChunk, false);
|
||||
for (ChunkAccess protoChunk : protoChunks) { // likely only necessary for spawn step since we copy over anyways
|
||||
((ThreadedLevelLightEngine) genWorld.getLightEngine()).lightChunk(protoChunk, false);
|
||||
((ProtoChunk) protoChunk).setStatus(ChunkStatus.LIGHT);
|
||||
}
|
||||
for (Chunk protoChunk : protoChunks) { // TODO: does this even work?
|
||||
ChunkRegion tempRegion = new ChunkRegionHack(genWorld, ChunkPos.stream(protoChunk.getPos(), 5).map(chunkPos -> protoRegion.getChunk(chunkPos.x, chunkPos.z)).collect(Collectors.toList()));
|
||||
genWorldChunkGenerator.populateEntities(tempRegion);
|
||||
for (ChunkAccess protoChunk : protoChunks) { // TODO: does this even work?
|
||||
WorldGenRegion tempRegion = new ChunkRegionHack(genWorld, ChunkPos.rangeClosed(protoChunk.getPos(), 5).map(chunkPos -> protoRegion.getChunk(chunkPos.x, chunkPos.z)).collect(Collectors.toList()));
|
||||
genWorldChunkGenerator.spawnOriginalMobs(tempRegion);
|
||||
((ProtoChunk) protoChunk).setStatus(ChunkStatus.SPAWN);
|
||||
}
|
||||
|
||||
|
@ -159,33 +157,33 @@ public class ChunkGenerator extends PocketGenerator {
|
|||
BlockPos firstCorner = pocket.getOrigin();
|
||||
BlockPos secondCorner = new BlockPos(firstCorner.getX() + size.getX() - 1, Math.min(firstCorner.getY() + size.getY() - 1, world.getHeight() - virtualYOffset - 1), firstCorner.getZ() + size.getZ() - 1); // subtracting 1 here since it should be 0 inclusive and size exclusive
|
||||
|
||||
BlockPos pocketOriginChunkOffset = new ChunkPos(pocket.getOrigin()).getStartPos().subtract(firstCorner);
|
||||
for (BlockPos blockPos : BlockPos.iterate(firstCorner, secondCorner)) {
|
||||
BlockPos sourcePos = blockPos.add(pocketOriginChunkOffset).add(0, virtualYOffset, 0);
|
||||
BlockPos pocketOriginChunkOffset = new ChunkPos(pocket.getOrigin()).getWorldPosition().subtract(firstCorner);
|
||||
for (BlockPos blockPos : BlockPos.betweenClosed(firstCorner, secondCorner)) {
|
||||
BlockPos sourcePos = blockPos.offset(pocketOriginChunkOffset).offset(0, virtualYOffset, 0);
|
||||
BlockState blockState = protoRegion.getBlockState(sourcePos);
|
||||
if (!blockState.isAir()) {
|
||||
world.setBlockState(blockPos, protoRegion.getBlockState(blockPos.add(pocketOriginChunkOffset).add(0, virtualYOffset, 0)));
|
||||
world.setBlockAndUpdate(blockPos, protoRegion.getBlockState(blockPos.offset(pocketOriginChunkOffset).offset(0, virtualYOffset, 0)));
|
||||
}
|
||||
}
|
||||
Box realBox = new Box(firstCorner, secondCorner);
|
||||
for (Chunk protoChunk : protoChunks) {
|
||||
for(BlockPos virtualBlockPos : protoChunk.getBlockEntityPositions()) {
|
||||
BlockPos realBlockPos = virtualBlockPos.subtract(pocketOriginChunkOffset).add(0, -virtualYOffset, 0);
|
||||
AABB realBox = new AABB(firstCorner, secondCorner);
|
||||
for (ChunkAccess protoChunk : protoChunks) {
|
||||
for(BlockPos virtualBlockPos : protoChunk.getBlockEntitiesPos()) {
|
||||
BlockPos realBlockPos = virtualBlockPos.subtract(pocketOriginChunkOffset).offset(0, -virtualYOffset, 0);
|
||||
if (realBox.contains(realBlockPos.getX(), realBlockPos.getY(), realBlockPos.getZ())) {
|
||||
world.addBlockEntity(protoChunk.getBlockEntity(virtualBlockPos)); // TODO: ensure this works, likely bugged
|
||||
world.setBlockEntity(protoChunk.getBlockEntity(virtualBlockPos)); // TODO: ensure this works, likely bugged
|
||||
}
|
||||
}
|
||||
}
|
||||
Box virtualBox = realBox.offset(pocketOriginChunkOffset.add(0, virtualYOffset, 0));
|
||||
AABB virtualBox = realBox.move(pocketOriginChunkOffset.offset(0, virtualYOffset, 0));
|
||||
/*
|
||||
for (Entity entity : protoRegion.getOtherEntities(null, virtualBox)) { // TODO: does this even work?
|
||||
TeleportUtil.teleport(entity, world, entity.getPos().add(-pocketOriginChunkOffset.getX(), -pocketOriginChunkOffset.getY() - virtualYOffset, -pocketOriginChunkOffset.getZ()), entity.yaw);
|
||||
} // TODO: Entities?/ Biomes/ Structure Data
|
||||
*/
|
||||
world.setBlockState(world.getTopPosition(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, pocket.getOrigin()), ModBlocks.DETACHED_RIFT.getDefaultState());
|
||||
world.setBlockAndUpdate(world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, pocket.getOrigin()), ModBlocks.DETACHED_RIFT.get().defaultBlockState());
|
||||
|
||||
DetachedRiftBlockEntity rift = ModBlockEntityTypes.DETACHED_RIFT.instantiate(world.getTopPosition(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, pocket.getOrigin()), ModBlocks.DETACHED_RIFT.getDefaultState());
|
||||
world.addBlockEntity(rift);
|
||||
DetachedRiftBlockEntity rift = ModBlockEntityTypes.DETACHED_RIFT.get().create(world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, pocket.getOrigin()), ModBlocks.DETACHED_RIFT.get().defaultBlockState());
|
||||
world.setBlockEntity(rift);
|
||||
|
||||
rift.setDestination(new PocketEntranceMarker());
|
||||
pocket.virtualLocation = sourceVirtualLocation;
|
||||
|
@ -195,7 +193,7 @@ public class ChunkGenerator extends PocketGenerator {
|
|||
|
||||
@Override
|
||||
public PocketGeneratorType<? extends PocketGenerator> getType() {
|
||||
return PocketGeneratorType.CHUNK;
|
||||
return PocketGeneratorType.CHUNK.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -208,38 +206,38 @@ public class ChunkGenerator extends PocketGenerator {
|
|||
return size;
|
||||
}
|
||||
|
||||
private static class ChunkRegionHack extends ChunkRegion { // Please someone tell me if there is a better way
|
||||
ChunkRegionHack(ServerWorld world, List<Chunk> chunks) {
|
||||
private static class ChunkRegionHack extends WorldGenRegion { // Please someone tell me if there is a better way
|
||||
ChunkRegionHack(ServerLevel world, List<ChunkAccess> chunks) {
|
||||
super(world, chunks, ChunkStatus.EMPTY, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) {
|
||||
Chunk chunk = super.getChunk(chunkX, chunkZ, leastStatus, false);
|
||||
return chunk == null ? new ProtoChunkHack(new ChunkPos(chunkX, chunkZ), UpgradeData.NO_UPGRADE_DATA, this, this.getRegistryManager().get(RegistryKeys.BIOME)) : chunk;
|
||||
public ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) {
|
||||
ChunkAccess chunk = super.getChunk(chunkX, chunkZ, leastStatus, false);
|
||||
return chunk == null ? new ProtoChunkHack(new ChunkPos(chunkX, chunkZ), UpgradeData.EMPTY, this, this.registryAccess().registryOrThrow(Registries.BIOME)) : chunk;
|
||||
}
|
||||
|
||||
// TODO: Override getSeed()
|
||||
}
|
||||
|
||||
private static class ProtoChunkHack extends ProtoChunk { // exists solely to make some calls in the non utilized chunks faster
|
||||
public ProtoChunkHack(ChunkPos pos, UpgradeData upgradeData, HeightLimitView world, Registry<Biome> biomeRegistry) {
|
||||
public ProtoChunkHack(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world, Registry<Biome> biomeRegistry) {
|
||||
super(pos, upgradeData, world, biomeRegistry, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState setBlockState(BlockPos pos, BlockState state, boolean moved) {
|
||||
return Blocks.VOID_AIR.getDefaultState();
|
||||
return Blocks.VOID_AIR.defaultBlockState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
return Blocks.VOID_AIR.getDefaultState();
|
||||
return Blocks.VOID_AIR.defaultBlockState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockPos pos) {
|
||||
return Fluids.EMPTY.getDefaultState();
|
||||
return Fluids.EMPTY.defaultFluidState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import java.util.List;
|
|||
import java.util.Queue;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
|
@ -54,7 +56,7 @@ public abstract class LazyPocketGenerator extends PocketGenerator {
|
|||
}
|
||||
|
||||
@Override
|
||||
public PocketGenerator fromNbt(NbtCompound nbt, ResourceManager manager) {
|
||||
public PocketGenerator fromNbt(CompoundTag nbt, ResourceManager manager) {
|
||||
super.fromNbt(nbt, manager);
|
||||
|
||||
if (nbt.contains("lazy_modifiers")) {
|
||||
|
|
|
@ -7,15 +7,24 @@ import java.util.List;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import dev.architectury.registry.registries.Registrar;
|
||||
import dev.architectury.registry.registries.RegistrarManager;
|
||||
import dev.architectury.registry.registries.RegistrySupplier;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.level.block.entity.ChestBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.DispenserBlockEntity;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import net.minecraft.block.entity.ChestBlockEntity;
|
||||
import net.minecraft.block.entity.DispenserBlockEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtList;
|
||||
import net.minecraft.nbt.NbtString;
|
||||
import net.minecraft.registry.Registry;
|
||||
|
@ -23,7 +32,7 @@ import net.minecraft.registry.RegistryKey;
|
|||
import net.minecraft.registry.SimpleRegistry;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
|
||||
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
|
||||
|
@ -46,7 +55,7 @@ import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
|||
|
||||
public abstract class PocketGenerator implements Weighted<PocketGenerationContext>, ReferenceSerializable {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
public static final Registry<PocketGeneratorType<? extends PocketGenerator>> REGISTRY = FabricRegistryBuilder.from(new SimpleRegistry<PocketGeneratorType<? extends PocketGenerator>>(RegistryKey.ofRegistry(DimensionalDoors.id("pocket_generator_type")), Lifecycle.stable(), false)).buildAndRegister();
|
||||
public static final Registrar<PocketGeneratorType<? extends PocketGenerator>> REGISTRY = RegistrarManager.get(DimensionalDoors.MOD_ID).<PocketGeneratorType<? extends PocketGenerator>>builder(DimensionalDoors.id("pocket_generator_type")).build();
|
||||
public static final String RESOURCE_STARTING_PATH = "pockets/generator"; //TODO: might want to restructure data packs
|
||||
|
||||
private static final String defaultWeightEquation = "5"; // TODO: make config
|
||||
|
@ -55,7 +64,7 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationContex
|
|||
|
||||
private String resourceKey = null;
|
||||
|
||||
private NbtCompound builderNbt;
|
||||
private CompoundTag builderNbt;
|
||||
protected String weight = defaultWeightEquation;
|
||||
protected Equation weightEquation;
|
||||
protected Boolean setupLoot;
|
||||
|
@ -69,24 +78,23 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationContex
|
|||
parseWeight();
|
||||
}
|
||||
|
||||
public static PocketGenerator deserialize(NbtElement nbt, ResourceManager manager) {
|
||||
switch (nbt.getType()) {
|
||||
case NbtType.COMPOUND: // It's a serialized Modifier
|
||||
return PocketGenerator.deserialize((NbtCompound) nbt, manager);
|
||||
case NbtType.STRING: // It's a reference to a resource location
|
||||
public static PocketGenerator deserialize(Tag nbt, ResourceManager manager) {
|
||||
return switch (nbt.getType()) {
|
||||
case Tag.TAG_COMPOUND -> // It's a serialized Modifier
|
||||
PocketGenerator.deserialize((CompoundTag) nbt, manager);
|
||||
case Tag.TAG_STRING -> // It's a reference to a resource location
|
||||
// TODO: throw if manager is null
|
||||
return ResourceUtil.loadReferencedResource(manager, RESOURCE_STARTING_PATH, nbt.asString(), ResourceUtil.NBT_READER.andThenComposable(nbtElement -> deserialize(nbtElement, manager)));
|
||||
default:
|
||||
throw new RuntimeException(String.format("Unexpected NbtType %d!", nbt.getType()));
|
||||
}
|
||||
ResourceUtil.loadReferencedResource(manager, RESOURCE_STARTING_PATH, nbt.getAsString(), ResourceUtil.NBT_READER.andThenComposable(Tag -> deserialize(Tag, manager)));
|
||||
default -> throw new RuntimeException(String.format("Unexpected NbtType %d!", nbt.getType()));
|
||||
};
|
||||
}
|
||||
|
||||
public static PocketGenerator deserialize(NbtElement nbt) {
|
||||
public static PocketGenerator deserialize(Tag nbt) {
|
||||
return deserialize(nbt, null);
|
||||
}
|
||||
|
||||
public static PocketGenerator deserialize(NbtCompound nbt, ResourceManager manager) {
|
||||
Identifier id = Identifier.tryParse(nbt.getString("type")); // TODO: return some NONE PocketGenerator if type cannot be found or deserialization fails.
|
||||
public static PocketGenerator deserialize(CompoundTag nbt, ResourceManager manager) {
|
||||
ResourceLocation id = ResourceLocation.tryParse(nbt.getString("type")); // TODO: return some NONE PocketGenerator if type cannot be found or deserialization fails.
|
||||
PocketGeneratorType<? extends PocketGenerator> type = REGISTRY.get(id);
|
||||
if (type == null) {
|
||||
LOGGER.error("Could not deserialize PocketGenerator: " + nbt.toString());
|
||||
|
@ -95,15 +103,15 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationContex
|
|||
return type.fromNbt(nbt, manager);
|
||||
}
|
||||
|
||||
public static PocketGenerator deserialize(NbtCompound nbt) {
|
||||
public static PocketGenerator deserialize(CompoundTag nbt) {
|
||||
return deserialize(nbt, null);
|
||||
}
|
||||
|
||||
public static NbtElement serialize(PocketGenerator pocketGenerator, boolean allowReference) {
|
||||
return pocketGenerator.toNbt(new NbtCompound(), allowReference);
|
||||
public static Tag serialize(PocketGenerator pocketGenerator, boolean allowReference) {
|
||||
return pocketGenerator.toNbt(new CompoundTag(), allowReference);
|
||||
}
|
||||
|
||||
public static NbtElement serialize(PocketGenerator pocketGenerator) {
|
||||
public static Tag serialize(PocketGenerator pocketGenerator) {
|
||||
return serialize(pocketGenerator, false);
|
||||
}
|
||||
|
||||
|
@ -123,8 +131,8 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationContex
|
|||
}
|
||||
}
|
||||
|
||||
public PocketGenerator fromNbt(NbtCompound nbt, ResourceManager manager) {
|
||||
if (nbt.contains("builder", NbtType.COMPOUND)) builderNbt = nbt.getCompound("builder");
|
||||
public PocketGenerator fromNbt(CompoundTag nbt, ResourceManager manager) {
|
||||
if (nbt.contains("builder", Tag.TAG_COMPOUND)) builderNbt = nbt.getCompound("builder");
|
||||
|
||||
this.weight = nbt.contains("weight") ? nbt.getString("weight") : defaultWeightEquation;
|
||||
parseWeight();
|
||||
|
@ -132,21 +140,21 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationContex
|
|||
if (nbt.contains("setup_loot")) setupLoot = nbt.getBoolean("setup_loot");
|
||||
|
||||
if (nbt.contains("modifiers")) {
|
||||
NbtList modifiersNbt = nbt.getList("modifiers", 10);
|
||||
ListTag modifiersNbt = nbt.getList("modifiers", 10);
|
||||
for (int i = 0; i < modifiersNbt.size(); i++) {
|
||||
modifierList.add(Modifier.deserialize(modifiersNbt.getCompound(i), manager));
|
||||
}
|
||||
}
|
||||
|
||||
if (nbt.contains("modifier_references")) {
|
||||
NbtList modifiersNbt = nbt.getList("modifier_references", NbtType.STRING);
|
||||
for (NbtElement nbtElement : modifiersNbt) {
|
||||
modifierList.add(Modifier.deserialize(nbtElement, manager));
|
||||
ListTag modifiersNbt = nbt.getList("modifier_references", Tag.TAG_STRING);
|
||||
for (Tag Tag : modifiersNbt) {
|
||||
modifierList.add(Modifier.deserialize(Tag, manager));
|
||||
}
|
||||
}
|
||||
|
||||
if (nbt.contains("tags")) {
|
||||
NbtList nbtList = nbt.getList("tags", NbtType.STRING);
|
||||
ListTag nbtList = nbt.getList("tags", Tag.TAG_STRING);
|
||||
for (int i = 0; i < nbtList.size(); i++) {
|
||||
tags.add(nbtList.getString(i));
|
||||
}
|
||||
|
@ -154,18 +162,18 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationContex
|
|||
return this;
|
||||
}
|
||||
|
||||
public PocketGenerator fromNbt(NbtCompound nbt) {
|
||||
public PocketGenerator fromNbt(CompoundTag nbt) {
|
||||
return fromNbt(nbt, null);
|
||||
}
|
||||
|
||||
public NbtElement toNbt(NbtCompound nbt, boolean allowReference) {
|
||||
public Tag toNbt(CompoundTag nbt, boolean allowReference) {
|
||||
if (allowReference && this.resourceKey != null) {
|
||||
return NbtString.of(this.resourceKey);
|
||||
return StringTag.valueOf(this.resourceKey);
|
||||
}
|
||||
return toNbtInternal(nbt, allowReference);
|
||||
}
|
||||
|
||||
protected NbtCompound toNbtInternal(NbtCompound nbt, boolean allowReference) {
|
||||
protected CompoundTag toNbtInternal(CompoundTag nbt, boolean allowReference) {
|
||||
this.getType().toNbt(nbt);
|
||||
|
||||
if (builderNbt != null) nbt.put("builder", builderNbt);
|
||||
|
@ -174,28 +182,23 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationContex
|
|||
|
||||
if (setupLoot != null) nbt.putBoolean("setup_loot", setupLoot);
|
||||
|
||||
NbtList modifiersNbt = new NbtList();
|
||||
NbtList modifierReferences = new NbtList();
|
||||
ListTag modifiersNbt = new ListTag();
|
||||
ListTag modifierReferences = new ListTag();
|
||||
for (Modifier modifier : modifierList) {
|
||||
NbtElement modNbt = modifier.toNbt(new NbtCompound(), allowReference);
|
||||
switch (modNbt.getType()) {
|
||||
case NbtType.COMPOUND:
|
||||
modifiersNbt.add(modNbt);
|
||||
break;
|
||||
case NbtType.STRING:
|
||||
modifierReferences.add(modNbt);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException(String.format("Unexpected NbtType %d!", modNbt.getType()));
|
||||
Tag modNbt = modifier.toNbt(new CompoundTag(), allowReference);
|
||||
switch (modNbt.getId()) {
|
||||
case Tag.TAG_COMPOUND -> modifiersNbt.add(modNbt);
|
||||
case Tag.TAG_STRING -> modifierReferences.add(modNbt);
|
||||
default -> throw new RuntimeException(String.format("Unexpected NbtType %d!", modNbt.getType()));
|
||||
}
|
||||
}
|
||||
if (modifiersNbt.size() > 0) nbt.put("modifiers", modifiersNbt);
|
||||
if (modifierReferences.size() > 0) nbt.put("modifier_references", modifierReferences);
|
||||
|
||||
if (tags.size() > 0) {
|
||||
NbtList nbtList = new NbtList();
|
||||
ListTag nbtList = new ListTag();
|
||||
for (String nbtStr : tags) {
|
||||
nbtList.add(NbtString.of(nbtStr));
|
||||
nbtList.add(StringTag.valueOf(nbtStr));
|
||||
}
|
||||
nbt.put("tags", nbtList);
|
||||
}
|
||||
|
@ -203,7 +206,7 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationContex
|
|||
return nbt;
|
||||
}
|
||||
|
||||
public NbtElement toNbt(NbtCompound nbt) {
|
||||
public Tag toNbt(CompoundTag nbt) {
|
||||
return toNbt(nbt, false);
|
||||
}
|
||||
|
||||
|
@ -243,13 +246,13 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationContex
|
|||
}
|
||||
|
||||
public void setup(Pocket pocket, RiftManager manager, PocketGenerationContext parameters, boolean setupLootTables) {
|
||||
ServerWorld world = parameters.world();
|
||||
ServerLevel world = parameters.world();
|
||||
|
||||
if (!(pocket instanceof LazyGenerationPocket)) { // should not iterate over that which does not exist & area may be massive, getBlockEntities() might force generation
|
||||
if (setupLootTables) // temp
|
||||
pocket.getBlockEntities().forEach((blockPos, blockEntity) -> {
|
||||
if (/*setupLootTables &&*/ blockEntity instanceof Inventory) { // comment in if needed
|
||||
Inventory inventory = (Inventory) blockEntity;
|
||||
if (/*setupLootTables &&*/ blockEntity instanceof Container) { // comment in if needed
|
||||
Container inventory = (Container) blockEntity;
|
||||
if (inventory.isEmpty()) {
|
||||
if (blockEntity instanceof ChestBlockEntity || blockEntity instanceof DispenserBlockEntity) {
|
||||
TemplateUtils.setupLootTable(world, blockEntity, inventory, LOGGER);
|
||||
|
@ -261,7 +264,7 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationContex
|
|||
}
|
||||
});
|
||||
}
|
||||
manager.getRifts().forEach(rift -> rift.getDestination().setLocation(new Location(world, rift.getPos())));
|
||||
manager.getRifts().forEach(rift -> rift.getDestination().setLocation(new Location(world, rift.getBlockPos())));
|
||||
TemplateUtils.registerRifts(manager.getRifts(), parameters.linkTo(), parameters.linkProperties(), pocket);
|
||||
}
|
||||
|
||||
|
@ -302,27 +305,25 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationContex
|
|||
public abstract Vec3i getSize(PocketGenerationContext parameters);
|
||||
|
||||
public interface PocketGeneratorType<T extends PocketGenerator> {
|
||||
PocketGeneratorType<SchematicGenerator> SCHEMATIC = register(DimensionalDoors.id(SchematicGenerator.KEY), SchematicGenerator::new);
|
||||
PocketGeneratorType<ChunkGenerator> CHUNK = register(DimensionalDoors.id(ChunkGenerator.KEY), ChunkGenerator::new);
|
||||
PocketGeneratorType<VoidGenerator> VOID = register(DimensionalDoors.id(VoidGenerator.KEY), VoidGenerator::new);
|
||||
RegistrySupplier<PocketGeneratorType<PocketGenerator>> SCHEMATIC = register(DimensionalDoors.id(SchematicGenerator.KEY), SchematicGenerator::new);
|
||||
RegistrySupplier<PocketGeneratorType<ChunkGenerator>> CHUNK = register(DimensionalDoors.id(ChunkGenerator.KEY), ChunkGenerator::new);
|
||||
RegistrySupplier<PocketGeneratorType<VoidGenerator>> VOID = register(DimensionalDoors.id(VoidGenerator.KEY), VoidGenerator::new);
|
||||
|
||||
PocketGenerator fromNbt(NbtCompound nbt, ResourceManager manager);
|
||||
PocketGenerator fromNbt(CompoundTag nbt, ResourceManager manager);
|
||||
|
||||
NbtCompound toNbt(NbtCompound nbt);
|
||||
CompoundTag toNbt(CompoundTag nbt);
|
||||
|
||||
static void register() {
|
||||
DimensionalDoors.apiSubscribers.forEach(d -> d.registerPocketGeneratorTypes(REGISTRY));
|
||||
}
|
||||
static void register() {}
|
||||
|
||||
static <U extends PocketGenerator> PocketGeneratorType<U> register(Identifier id, Supplier<U> constructor) {
|
||||
return Registry.register(REGISTRY, id, new PocketGeneratorType<U>() {
|
||||
static <U extends PocketGenerator> RegistrySupplier<PocketGeneratorType<U>> register(ResourceLocation id, Supplier<U> constructor) {
|
||||
return REGISTRY.register(id, () -> new PocketGeneratorType<U>() {
|
||||
@Override
|
||||
public PocketGenerator fromNbt(NbtCompound nbt, ResourceManager manager) {
|
||||
public PocketGenerator fromNbt(CompoundTag nbt, ResourceManager manager) {
|
||||
return constructor.get().fromNbt(nbt, manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toNbt(NbtCompound nbt) {
|
||||
public CompoundTag toNbt(CompoundTag nbt) {
|
||||
nbt.putString("type", id.toString());
|
||||
return nbt;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
|
@ -77,7 +78,7 @@ public class SchematicGenerator extends LazyPocketGenerator{
|
|||
}
|
||||
|
||||
@Override
|
||||
public PocketGenerator fromNbt(NbtCompound nbt, ResourceManager manager) {
|
||||
public PocketGenerator fromNbt(CompoundTag nbt, ResourceManager manager) {
|
||||
super.fromNbt(nbt, manager);
|
||||
|
||||
this.id = nbt.getString("id"); // TODO: should we force having the "dimdoors:" in the json?
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.dimdev.dimdoors.pockets.generator;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
|
@ -53,7 +54,7 @@ public class VoidGenerator extends LazyPocketGenerator {
|
|||
}
|
||||
|
||||
@Override
|
||||
public PocketGenerator fromNbt(NbtCompound nbt, ResourceManager manager) {
|
||||
public PocketGenerator fromNbt(CompoundTag nbt, ResourceManager manager) {
|
||||
super.fromNbt(nbt, manager);
|
||||
|
||||
try {
|
||||
|
|
|
@ -1,78 +1,71 @@
|
|||
package org.dimdev.dimdoors.pockets.modifier;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.SimpleRegistry;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
|
||||
import net.fabricmc.fabric.api.util.NbtType;
|
||||
|
||||
import dev.architectury.registry.registries.Registrar;
|
||||
import dev.architectury.registry.registries.RegistrarManager;
|
||||
import dev.architectury.registry.registries.RegistrySupplier;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.api.util.ReferenceSerializable;
|
||||
import org.dimdev.dimdoors.api.util.ResourceUtil;
|
||||
import org.dimdev.dimdoors.pockets.PocketGenerationContext;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface Modifier extends ReferenceSerializable {
|
||||
Registry<ModifierType<? extends Modifier>> REGISTRY = FabricRegistryBuilder.from(new SimpleRegistry<ModifierType<? extends Modifier>>(RegistryKey.ofRegistry(DimensionalDoors.id("modifier_type")), Lifecycle.stable(), false)).buildAndRegister();
|
||||
Registrar<ModifierType<? extends Modifier>> REGISTRY = RegistrarManager.get(DimensionalDoors.MOD_ID).<ModifierType<? extends Modifier>>builder(DimensionalDoors.id("modifier_type")).build();
|
||||
|
||||
String RESOURCE_STARTING_PATH = "pockets/modifier"; //TODO: might want to restructure data packs
|
||||
|
||||
static Modifier deserialize(NbtElement nbt, ResourceManager manager) {
|
||||
switch (nbt.getType()) {
|
||||
case NbtType.COMPOUND: // It's a serialized Modifier
|
||||
return Modifier.deserialize((NbtCompound) nbt, manager);
|
||||
case NbtType.STRING: // It's a reference to a resource location
|
||||
static Modifier deserialize(Tag nbt, ResourceManager manager) {
|
||||
return switch (nbt.getId()) {
|
||||
case Tag.TAG_COMPOUND -> // It's a serialized Modifier
|
||||
Modifier.deserialize((CompoundTag) nbt, manager);
|
||||
case Tag.TAG_STRING -> // It's a reference to a resource location
|
||||
// TODO: throw if manager is null
|
||||
return ResourceUtil.loadReferencedResource(manager, RESOURCE_STARTING_PATH, nbt.asString(), ResourceUtil.NBT_READER.andThenComposable(nbtElement -> deserialize(nbtElement, manager)));
|
||||
default:
|
||||
throw new RuntimeException(String.format("Unexpected NbtType %d!", nbt.getType()));
|
||||
}
|
||||
ResourceUtil.loadReferencedResource(manager, RESOURCE_STARTING_PATH, nbt.getAsString(), ResourceUtil.NBT_READER.andThenComposable(Tag -> deserialize(Tag, manager)));
|
||||
default -> throw new RuntimeException(String.format("Unexpected NbtType %d!", nbt.getId()));
|
||||
};
|
||||
}
|
||||
|
||||
static Modifier deserialize(NbtElement nbt) {
|
||||
static Modifier deserialize(Tag nbt) {
|
||||
return deserialize(nbt, null);
|
||||
}
|
||||
|
||||
static Modifier deserialize(NbtCompound nbt, ResourceManager manager) {
|
||||
Identifier id = Identifier.tryParse(nbt.getString("type")); // TODO: return some NONE Modifier if type cannot be found or deserialization fails.
|
||||
static Modifier deserialize(CompoundTag nbt, ResourceManager manager) {
|
||||
ResourceLocation id = ResourceLocation.tryParse(nbt.getString("type")); // TODO: return some NONE Modifier if type cannot be found or deserialization fails.
|
||||
return REGISTRY.get(id).fromNbt(nbt, manager);
|
||||
}
|
||||
|
||||
static Modifier deserialize(NbtCompound nbt) {
|
||||
static Modifier deserialize(CompoundTag nbt) {
|
||||
return deserialize(nbt, null);
|
||||
}
|
||||
|
||||
static NbtElement serialize(Modifier modifier, boolean allowReference) {
|
||||
return modifier.toNbt(new NbtCompound(), allowReference);
|
||||
static Tag serialize(Modifier modifier, boolean allowReference) {
|
||||
return modifier.toNbt(new CompoundTag(), allowReference);
|
||||
}
|
||||
|
||||
static NbtElement serialize(Modifier modifier) {
|
||||
static Tag serialize(Modifier modifier) {
|
||||
return serialize(modifier, false);
|
||||
}
|
||||
|
||||
|
||||
Modifier fromNbt(NbtCompound nbt, ResourceManager manager);
|
||||
Modifier fromNbt(CompoundTag nbt, ResourceManager manager);
|
||||
|
||||
default Modifier fromNbt(NbtCompound nbt) {
|
||||
default Modifier fromNbt(CompoundTag nbt) {
|
||||
return fromNbt(nbt, null);
|
||||
}
|
||||
|
||||
default NbtElement toNbt(NbtCompound nbt, boolean allowReference) {
|
||||
default Tag toNbt(CompoundTag nbt, boolean allowReference) {
|
||||
return this.getType().toNbt(nbt);
|
||||
}
|
||||
|
||||
default NbtElement toNbt(NbtCompound nbt) {
|
||||
default Tag toNbt(CompoundTag nbt) {
|
||||
return toNbt(nbt, false);
|
||||
}
|
||||
|
||||
|
@ -97,35 +90,33 @@ public interface Modifier extends ReferenceSerializable {
|
|||
void apply(PocketGenerationContext parameters, Pocket.PocketBuilder<?, ?> builder);
|
||||
|
||||
interface ModifierType<T extends Modifier> {
|
||||
ModifierType<ShellModifier> SHELL_MODIFIER_TYPE = register(DimensionalDoors.id(ShellModifier.KEY), ShellModifier::new);
|
||||
ModifierType<DimensionalDoorModifier> DIMENSIONAL_DOOR_MODIFIER_TYPE = register(DimensionalDoors.id(DimensionalDoorModifier.KEY), DimensionalDoorModifier::new);
|
||||
ModifierType<PocketEntranceModifier> PUBLIC_MODIFIER_TYPE = register(DimensionalDoors.id(PocketEntranceModifier.KEY), PocketEntranceModifier::new);
|
||||
ModifierType<RiftDataModifier> RIFT_DATA_MODIFIER_TYPE = register(DimensionalDoors.id(RiftDataModifier.KEY), RiftDataModifier::new);
|
||||
ModifierType<RelativeReferenceModifier> RELATIVE_REFERENCE_MODIFIER_TYPE = register(DimensionalDoors.id(RelativeReferenceModifier.KEY), RelativeReferenceModifier::new);
|
||||
ModifierType<OffsetModifier> OFFSET_MODIFIER_TYPE = register(DimensionalDoors.id(OffsetModifier.KEY), OffsetModifier::new);
|
||||
ModifierType<AbsoluteRiftBlockEntityModifier> ABSOLUTE_RIFT_BLOCK_ENTITY_MODIFIER_TYPE = register(DimensionalDoors.id(AbsoluteRiftBlockEntityModifier.KEY), AbsoluteRiftBlockEntityModifier::new);
|
||||
RegistrySupplier<ModifierType<ShellModifier>> SHELL_MODIFIER_TYPE = register(DimensionalDoors.id(ShellModifier.KEY), ShellModifier::new);
|
||||
RegistrySupplier<ModifierType<DimensionalDoorModifier>> DIMENSIONAL_DOOR_MODIFIER_TYPE = register(DimensionalDoors.id(DimensionalDoorModifier.KEY), DimensionalDoorModifier::new);
|
||||
RegistrySupplier<ModifierType<Modifier>> PUBLIC_MODIFIER_TYPE = register(DimensionalDoors.id(PocketEntranceModifier.KEY), PocketEntranceModifier::new);
|
||||
RegistrySupplier<ModifierType<RiftDataModifier>> RIFT_DATA_MODIFIER_TYPE = register(DimensionalDoors.id(RiftDataModifier.KEY), RiftDataModifier::new);
|
||||
RegistrySupplier<ModifierType<RelativeReferenceModifier>> RELATIVE_REFERENCE_MODIFIER_TYPE = register(DimensionalDoors.id(RelativeReferenceModifier.KEY), RelativeReferenceModifier::new);
|
||||
RegistrySupplier<ModifierType<OffsetModifier>> OFFSET_MODIFIER_TYPE = register(DimensionalDoors.id(OffsetModifier.KEY), OffsetModifier::new);
|
||||
RegistrySupplier<ModifierType<Modifier>> ABSOLUTE_RIFT_BLOCK_ENTITY_MODIFIER_TYPE = register(DimensionalDoors.id(AbsoluteRiftBlockEntityModifier.KEY), AbsoluteRiftBlockEntityModifier::new);
|
||||
|
||||
Modifier fromNbt(NbtCompound nbt, ResourceManager manager);
|
||||
Modifier fromNbt(CompoundTag nbt, ResourceManager manager);
|
||||
|
||||
default Modifier fromNbt(NbtCompound nbt) {
|
||||
default Modifier fromNbt(CompoundTag nbt) {
|
||||
return fromNbt(nbt, null);
|
||||
}
|
||||
|
||||
NbtCompound toNbt(NbtCompound nbt);
|
||||
CompoundTag toNbt(CompoundTag nbt);
|
||||
|
||||
static void register() {
|
||||
DimensionalDoors.apiSubscribers.forEach(d -> d.registerModifierTypes(REGISTRY));
|
||||
}
|
||||
static void register() {}
|
||||
|
||||
static <U extends Modifier> ModifierType<U> register(Identifier id, Supplier<U> factory) {
|
||||
return Registry.register(REGISTRY, id, new ModifierType<U>() {
|
||||
static <U extends Modifier> RegistrySupplier<ModifierType<U>> register(ResourceLocation id, Supplier<U> factory) {
|
||||
return REGISTRY.register(id, () -> new ModifierType<U>() {
|
||||
@Override
|
||||
public Modifier fromNbt(NbtCompound nbt, ResourceManager manager) {
|
||||
public Modifier fromNbt(CompoundTag nbt, ResourceManager manager) {
|
||||
return factory.get().fromNbt(nbt, manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toNbt(NbtCompound nbt) {
|
||||
public CompoundTag toNbt(CompoundTag nbt) {
|
||||
nbt.putString("type", id.toString());
|
||||
return nbt;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package org.dimdev.dimdoors.pockets.virtual;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.nbt.NbtString;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
public abstract class AbstractVirtualPocket implements ImplementedVirtualPocket {
|
||||
private String resourceKey = null;
|
||||
|
@ -18,7 +20,7 @@ public abstract class AbstractVirtualPocket implements ImplementedVirtualPocket
|
|||
}
|
||||
|
||||
@Override
|
||||
public NbtElement toNbt(NbtCompound nbt, boolean allowReference) {
|
||||
public Tag toNbt(CompoundTag nbt, boolean allowReference) {
|
||||
if (allowReference && this.getResourceKey() != null) {
|
||||
return NbtString.of(this.getResourceKey());
|
||||
}
|
||||
|
@ -28,7 +30,7 @@ public abstract class AbstractVirtualPocket implements ImplementedVirtualPocket
|
|||
// utility so the first part of toNbt can be extracted into default method
|
||||
// at this point we know for a fact, that we need to serialize into the NbtCompound
|
||||
// overwrite in subclass
|
||||
protected NbtCompound toNbtInternal(NbtCompound nbt, boolean allowReference) {
|
||||
protected CompoundTag toNbtInternal(CompoundTag nbt, boolean allowReference) {
|
||||
return this.getType().toNbt(nbt);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.dimdev.dimdoors.pockets.virtual;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
|
@ -32,10 +33,10 @@ public interface ImplementedVirtualPocket extends VirtualPocket {
|
|||
Registry<VirtualPocketType<? extends ImplementedVirtualPocket>> REGISTRY = FabricRegistryBuilder.from(new SimpleRegistry<VirtualPocketType<? extends ImplementedVirtualPocket>>(RegistryKey.ofRegistry(DimensionalDoors.id("virtual_pocket_type")), Lifecycle.stable(), false)).buildAndRegister();
|
||||
|
||||
static ImplementedVirtualPocket deserialize(NbtElement nbt, @Nullable ResourceManager manager) {
|
||||
return switch (nbt.getType()) {
|
||||
return switch (nbt.getId()) {
|
||||
case NbtType.COMPOUND -> deserialize((NbtCompound) nbt, manager);
|
||||
case NbtType.STRING -> ResourceUtil.loadReferencedResource(manager, RESOURCE_STARTING_PATH, nbt.asString(), ResourceUtil.NBT_READER.andThenComposable(nbtElement -> deserialize(nbtElement, manager)));
|
||||
default -> throw new RuntimeException(String.format("Unexpected NbtType %d!", nbt.getType()));
|
||||
default -> throw new RuntimeException(String.format("Unexpected NbtType %d!", nbt.getId()));
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -84,7 +85,7 @@ public interface ImplementedVirtualPocket extends VirtualPocket {
|
|||
VirtualPocketType<ConditionalSelector> CONDITIONAL_SELECTOR = register(DimensionalDoors.id(ConditionalSelector.KEY), ConditionalSelector::new);
|
||||
VirtualPocketType<PathSelector> PATH_SELECTOR = register(DimensionalDoors.id(PathSelector.KEY), PathSelector::new);
|
||||
|
||||
ImplementedVirtualPocket fromNbt(NbtCompound nbt, @Nullable ResourceManager manager);
|
||||
ImplementedVirtualPocket fromNbt(CompoundTag nbt, @Nullable ResourceManager manager);
|
||||
|
||||
default ImplementedVirtualPocket fromNbt(NbtCompound nbt) {
|
||||
return fromNbt(nbt, null);
|
||||
|
|
|
@ -29,7 +29,7 @@ public interface VirtualPocket extends Weighted<PocketGenerationContext>, Refere
|
|||
|
||||
//TODO: split up in ImplementedVirtualPocket and VirtualPocketList
|
||||
static VirtualPocket deserialize(NbtElement nbt, @Nullable ResourceManager manager) {
|
||||
switch (nbt.getType()) {
|
||||
switch (nbt.getId()) {
|
||||
case NbtType.LIST: // It's a list of VirtualPocket
|
||||
return VirtualPocketList.deserialize((NbtList) nbt, manager);
|
||||
case NbtType.COMPOUND: // It's a serialized VirtualPocket
|
||||
|
@ -38,7 +38,7 @@ public interface VirtualPocket extends Weighted<PocketGenerationContext>, Refere
|
|||
case NbtType.STRING: // It's a reference to a resource location
|
||||
return ResourceUtil.loadReferencedResource(manager, RESOURCE_STARTING_PATH, nbt.asString(), ResourceUtil.NBT_READER.andThenComposable(nbtElement -> deserialize(nbtElement, manager)));
|
||||
default:
|
||||
throw new RuntimeException(String.format("Unexpected NbtType %d!", nbt.getType()));
|
||||
throw new RuntimeException(String.format("Unexpected NbtType %d!", nbt.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,13 +19,13 @@ public class VirtualPocketList extends WeightedList<VirtualPocket, PocketGenerat
|
|||
private String resourceKey = null;
|
||||
|
||||
public static VirtualPocketList deserialize(NbtElement nbt, @Nullable ResourceManager manager) {
|
||||
switch (nbt.getType()) {
|
||||
switch (nbt.getId()) {
|
||||
case NbtType.LIST:
|
||||
return deserialize((NbtList) nbt, manager);
|
||||
case NbtType.STRING:
|
||||
return ResourceUtil.loadReferencedResource(manager, RESOURCE_STARTING_PATH, nbt.asString(), ResourceUtil.NBT_READER.andThenComposable(nbtElement -> deserialize(nbtElement, manager)));
|
||||
default:
|
||||
throw new RuntimeException(String.format("Unexpected NbtType %d!", nbt.getType()));
|
||||
throw new RuntimeException(String.format("Unexpected NbtType %d!", nbt.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,12 +4,9 @@ import java.util.Map;
|
|||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import dev.architectury.registry.registries.DeferredRegister;
|
||||
import dev.architectury.registry.registries.Registrar;
|
||||
import dev.architectury.registry.registries.RegistrarManager;
|
||||
import dev.architectury.registry.registries.RegistrySupplier;
|
||||
import dev.architectury.registry.registries.options.RegistrarOption;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
@ -128,12 +125,10 @@ public abstract class VirtualTarget implements Target {
|
|||
});
|
||||
}
|
||||
|
||||
static void register() {
|
||||
DimensionalDoors.apiSubscribers.forEach(d -> d.registerVirtualTargetTypes(REGISTRY));
|
||||
}
|
||||
static void register() {}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T extends VirtualTarget> VirtualTargetType<T> register(String id, Function<CompoundTag, T> fromNbt, Function<T, CompoundTag> toNbt, RGBA color) {
|
||||
static <T extends VirtualTarget> RegistrySupplier<VirtualTargetType<T>> register(String id, Function<CompoundTag, T> fromNbt, Function<T, CompoundTag> toNbt, RGBA color) {
|
||||
return REGISTRY.register(new ResourceLocation(id), () -> new VirtualTargetType<T>() {
|
||||
@Override
|
||||
public T fromNbt(CompoundTag nbt) {
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package org.dimdev.dimdoors.world;
|
||||
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
||||
import static org.dimdev.dimdoors.DimensionalDoors.id;
|
||||
|
||||
public final class ModBiomes {
|
||||
public static final RegistryKey<Biome> PERSONAL_WHITE_VOID_KEY = register("white_void");
|
||||
public static final RegistryKey<Biome> PUBLIC_BLACK_VOID_KEY = register("black_void");
|
||||
public static final RegistryKey<Biome> DUNGEON_DANGEROUS_BLACK_VOID_KEY = register("dangerous_black_void");
|
||||
public static final RegistryKey<Biome> LIMBO_KEY = register("limbo");
|
||||
|
||||
public static void init() {
|
||||
}
|
||||
|
||||
private static RegistryKey<Biome> register(String name) {
|
||||
return RegistryKey.of(RegistryKeys.BIOME, id(name));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package org.dimdev.dimdoors.world;
|
||||
|
||||
import dev.architectury.event.events.common.LifecycleEvent;
|
||||
import dev.architectury.registry.registries.DeferredRegister;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.world.pocket.BlankChunkGenerator;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class ModDimensions {
|
||||
public static final ResourceKey<Level> LIMBO = ResourceKey.create(Registries.DIMENSION, DimensionalDoors.id("limbo"));
|
||||
public static final ResourceKey<Level> PERSONAL = ResourceKey.create(Registries.DIMENSION, DimensionalDoors.id("personal_pockets"));
|
||||
public static final ResourceKey<Level> PUBLIC = ResourceKey.create(Registries.DIMENSION, DimensionalDoors.id("public_pockets"));
|
||||
public static final ResourceKey<Level> DUNGEON = ResourceKey.create(Registries.DIMENSION, DimensionalDoors.id("dungeon_pockets"));
|
||||
|
||||
public static final ResourceKey<DimensionType> LIMBO_TYPE_KEY = ResourceKey.create(Registries.DIMENSION_TYPE, DimensionalDoors.id("limbo"));
|
||||
public static final ResourceKey<DimensionType> POCKET_TYPE_KEY = ResourceKey.create(Registries.DIMENSION_TYPE, DimensionalDoors.id("personal_pockets"));
|
||||
|
||||
public static DimensionType LIMBO_TYPE;
|
||||
public static DimensionType POCKET_TYPE;
|
||||
|
||||
public static ServerLevel LIMBO_DIMENSION;
|
||||
public static ServerLevel PERSONAL_POCKET_DIMENSION;
|
||||
public static ServerLevel PUBLIC_POCKET_DIMENSION;
|
||||
public static ServerLevel DUNGEON_POCKET_DIMENSION;
|
||||
|
||||
public static boolean isPocketDimension(Level world) {
|
||||
return isPocketDimension(world.dimension());
|
||||
}
|
||||
|
||||
public static boolean isPrivatePocketDimension(Level world) {
|
||||
return world != null && world == PERSONAL_POCKET_DIMENSION;
|
||||
}
|
||||
|
||||
public static boolean isPocketDimension(ResourceKey<Level> type) {
|
||||
return Objects.equals(type, PERSONAL) || Objects.equals(type, PUBLIC) || Objects.equals(type, DUNGEON);
|
||||
}
|
||||
|
||||
public static boolean isLimboDimension(Level world) {
|
||||
return world != null && world.dimension().equals(LIMBO);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
LifecycleEvent.SERVER_STARTED.register(server -> {
|
||||
ModDimensions.LIMBO_TYPE = server.registryAccess().registryOrThrow(Registries.DIMENSION_TYPE).get(LIMBO_TYPE_KEY);
|
||||
ModDimensions.POCKET_TYPE = server.registryAccess().registryOrThrow(Registries.DIMENSION_TYPE).get(POCKET_TYPE_KEY);
|
||||
ModDimensions.LIMBO_DIMENSION = server.getLevel(LIMBO);
|
||||
ModDimensions.PERSONAL_POCKET_DIMENSION = server.getLevel(PERSONAL);
|
||||
ModDimensions.PUBLIC_POCKET_DIMENSION = server.getLevel(PUBLIC);
|
||||
ModDimensions.DUNGEON_POCKET_DIMENSION = server.getLevel(DUNGEON);
|
||||
});
|
||||
DeferredRegister.create(DimensionalDoors.MOD_ID, Registries.CHUNK_GENERATOR).register("blank", () -> BlankChunkGenerator.CODEC);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package org.dimdev.dimdoors.world.decay;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
|
||||
public class DecayPattern {
|
||||
public static final Event<EntropyEvent> ENTROPY_EVENT = EventFactory.createArrayBacked(EntropyEvent.class, (world, pos, entorpy) -> {}, entropyEvents -> (world, pos, entorpy) -> {
|
||||
for (EntropyEvent event : entropyEvents) event.entropy(world, pos, entorpy);
|
||||
});
|
||||
|
||||
private DecayPredicate predicate;
|
||||
private DecayProcessor processor;
|
||||
|
||||
public DecayPattern() {}
|
||||
|
||||
public DecayPattern(DecayPredicate predicate, DecayProcessor processor) {
|
||||
this.predicate = predicate;
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
public static DecayPattern deserialize(NbtCompound nbt) {
|
||||
DecayPredicate predicate = DecayPredicate.deserialize(nbt.getCompound("predicate"));
|
||||
DecayProcessor processor = DecayProcessor.deserialize(nbt.getCompound("processor"));
|
||||
return DecayPattern.builder().predicate(predicate).processor(processor).create();
|
||||
}
|
||||
|
||||
public boolean test(World world, BlockPos pos, BlockState origin, BlockState targetBlock, FluidState targetFluid) {
|
||||
return predicate.test(world, pos, origin, targetBlock, targetFluid);
|
||||
}
|
||||
|
||||
public void process(World world, BlockPos pos, BlockState origin, BlockState targetBlock, FluidState targetFluid) {
|
||||
ENTROPY_EVENT.invoker().entropy(world, pos, processor.process(world, pos, origin, targetBlock, targetFluid));
|
||||
}
|
||||
|
||||
public Set<Block> constructApplicableBlocks() {
|
||||
return predicate.constructApplicableBlocks();
|
||||
}
|
||||
|
||||
public Set<Fluid> constructApplicableFluids() {
|
||||
return predicate.constructApplicableFluids();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private DecayPredicate predicate = DecayPredicate.NONE;
|
||||
private DecayProcessor processor = DecayProcessor.NONE;
|
||||
|
||||
public Builder predicate(DecayPredicate predicate) {
|
||||
this.predicate = predicate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder processor(DecayProcessor processor) {
|
||||
this.processor = processor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DecayPattern create() {
|
||||
return new DecayPattern(predicate, processor);
|
||||
}
|
||||
}
|
||||
|
||||
private interface EntropyEvent {
|
||||
void entropy(World world, BlockPos pos, int entorpy);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package org.dimdev.dimdoors.world.decay;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.SimpleRegistry;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
|
||||
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.datagen.FluidDecayPredicate;
|
||||
import org.dimdev.dimdoors.world.decay.predicates.SimpleDecayPredicate;
|
||||
|
||||
public interface DecayPredicate {
|
||||
Registry<DecayPredicateType<? extends DecayPredicate>> REGISTRY = FabricRegistryBuilder.from(new SimpleRegistry<DecayPredicateType<? extends DecayPredicate>>(RegistryKey.ofRegistry(DimensionalDoors.id("decay_predicate_type")), Lifecycle.stable(), false)).buildAndRegister();
|
||||
|
||||
DecayPredicate NONE = new DecayPredicate() {
|
||||
private static final String ID = "none";
|
||||
|
||||
@Override
|
||||
public DecayPredicate fromNbt(NbtCompound nbt) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecayPredicateType<? extends DecayPredicate> getType() {
|
||||
return DecayPredicateType.NONE_PREDICATE_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(World world, BlockPos pos, BlockState origin, BlockState targetBlock, FluidState targetFluid) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
static DecayPredicate deserialize(NbtCompound nbt) {
|
||||
Identifier id = Identifier.tryParse(nbt.getString("type"));
|
||||
return REGISTRY.getOrEmpty(id).orElse(DecayPredicateType.NONE_PREDICATE_TYPE).fromNbt(nbt);
|
||||
}
|
||||
|
||||
static NbtCompound serialize(DecayPredicate modifier) {
|
||||
return modifier.toNbt(new NbtCompound());
|
||||
}
|
||||
|
||||
|
||||
DecayPredicate fromNbt(NbtCompound nbt);
|
||||
|
||||
default NbtCompound toNbt(NbtCompound nbt) {
|
||||
return this.getType().toNbt(nbt);
|
||||
}
|
||||
|
||||
DecayPredicateType<? extends DecayPredicate> getType();
|
||||
|
||||
String getKey();
|
||||
|
||||
boolean test(World world, BlockPos pos, BlockState origin, BlockState targetBlock, FluidState targetFluid);
|
||||
|
||||
default Set<Fluid> constructApplicableFluids() {
|
||||
return Set.of();
|
||||
}
|
||||
|
||||
default Set<Block> constructApplicableBlocks() {
|
||||
return Set.of();
|
||||
}
|
||||
|
||||
interface DecayPredicateType<T extends DecayPredicate> {
|
||||
DecayPredicateType<DecayPredicate> NONE_PREDICATE_TYPE = register(DimensionalDoors.id("none"), () -> NONE);
|
||||
DecayPredicateType<SimpleDecayPredicate> SIMPLE_PREDICATE_TYPE = register(DimensionalDoors.id(SimpleDecayPredicate.KEY), SimpleDecayPredicate::new);
|
||||
DecayPredicateType<FluidDecayPredicate> FLUID_PREDICATE_TYPE = register(DimensionalDoors.id(FluidDecayPredicate.KEY), FluidDecayPredicate::new);
|
||||
|
||||
DecayPredicate fromNbt(NbtCompound nbt);
|
||||
|
||||
NbtCompound toNbt(NbtCompound nbt);
|
||||
|
||||
static void register() {
|
||||
DimensionalDoors.apiSubscribers.forEach(d -> d.registerDecayPredicates(REGISTRY));
|
||||
}
|
||||
|
||||
static <U extends DecayPredicate> DecayPredicateType<U> register(Identifier id, Supplier<U> factory) {
|
||||
return Registry.register(REGISTRY, id, new DecayPredicateType<U>() {
|
||||
@Override
|
||||
public DecayPredicate fromNbt(NbtCompound nbt) {
|
||||
return factory.get().fromNbt(nbt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toNbt(NbtCompound nbt) {
|
||||
nbt.putString("type", id.toString());
|
||||
return nbt;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package org.dimdev.dimdoors.world.decay;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.SimpleRegistry;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
|
||||
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.datagen.FluidDecayProcessor;
|
||||
import org.dimdev.dimdoors.world.decay.processors.DoorDecayProccessor;
|
||||
import org.dimdev.dimdoors.world.decay.processors.DoubleDecayProcessor;
|
||||
import org.dimdev.dimdoors.world.decay.processors.SelfDecayProcessor;
|
||||
import org.dimdev.dimdoors.world.decay.processors.BlockDecayProcessor;
|
||||
|
||||
public interface DecayProcessor {
|
||||
Registry<DecayProcessorType<? extends DecayProcessor>> REGISTRY = FabricRegistryBuilder.from(new SimpleRegistry<DecayProcessorType<? extends DecayProcessor>>(RegistryKey.ofRegistry(DimensionalDoors.id("decay_processor_type")), Lifecycle.stable(), false)).buildAndRegister();
|
||||
|
||||
DecayProcessor NONE = new DecayProcessor() {
|
||||
@Override
|
||||
public DecayProcessor fromNbt(NbtCompound nbt) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecayProcessorType<? extends DecayProcessor> getType() {
|
||||
return DecayProcessorType.NONE_PROCESSOR_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int process(World world, BlockPos pos, BlockState origin, BlockState targetBlock, FluidState targetFluid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static final String ID = "none";
|
||||
};
|
||||
|
||||
static DecayProcessor deserialize(NbtCompound nbt) {
|
||||
Identifier id = Identifier.tryParse(nbt.getString("type"));
|
||||
return REGISTRY.getOrEmpty(id).orElse(DecayProcessorType.NONE_PROCESSOR_TYPE).fromNbt(nbt);
|
||||
}
|
||||
|
||||
static NbtCompound serialize(DecayProcessor modifier) {
|
||||
return modifier.toNbt(new NbtCompound());
|
||||
}
|
||||
|
||||
|
||||
DecayProcessor fromNbt(NbtCompound nbt);
|
||||
|
||||
default NbtCompound toNbt(NbtCompound nbt) {
|
||||
return this.getType().toNbt(nbt);
|
||||
}
|
||||
|
||||
DecayProcessorType<? extends DecayProcessor> getType();
|
||||
|
||||
String getKey();
|
||||
|
||||
int process(World world, BlockPos pos, BlockState origin, BlockState targetState, FluidState targetFluid);
|
||||
|
||||
interface DecayProcessorType<T extends DecayProcessor> {
|
||||
DecayProcessorType<BlockDecayProcessor> SIMPLE_PROCESSOR_TYPE = register(DimensionalDoors.id(BlockDecayProcessor.KEY), BlockDecayProcessor::new);
|
||||
DecayProcessorType<DecayProcessor> NONE_PROCESSOR_TYPE = register(DimensionalDoors.id("none"), () -> NONE);
|
||||
DecayProcessorType<SelfDecayProcessor> SELF = register(DimensionalDoors.id(SelfDecayProcessor.KEY), SelfDecayProcessor::instance);
|
||||
DecayProcessorType<DoorDecayProccessor> DOOR_PROCESSOR_TYPE = register(DimensionalDoors.id(DoorDecayProccessor.KEY), DoorDecayProccessor::new);
|
||||
DecayProcessorType<DoubleDecayProcessor> DOUBLE_PROCESSOR_TYPE = register(DimensionalDoors.id(DoubleDecayProcessor.KEY), DoubleDecayProcessor::new);
|
||||
DecayProcessorType<FluidDecayProcessor> FLUID_PROCESSOR_TYPE = register(DimensionalDoors.id(FluidDecayProcessor.KEY), FluidDecayProcessor::new);
|
||||
|
||||
DecayProcessor fromNbt(NbtCompound nbt);
|
||||
|
||||
NbtCompound toNbt(NbtCompound nbt);
|
||||
|
||||
static void register() {
|
||||
DimensionalDoors.apiSubscribers.forEach(d -> d.registerDecayProcessors(REGISTRY));
|
||||
}
|
||||
|
||||
static <U extends DecayProcessor> DecayProcessorType<U> register(Identifier id, Supplier<U> factory) {
|
||||
return Registry.register(REGISTRY, id, new DecayProcessorType<U>() {
|
||||
@Override
|
||||
public DecayProcessor fromNbt(NbtCompound nbt) {
|
||||
return factory.get().fromNbt(nbt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toNbt(NbtCompound nbt) {
|
||||
nbt.putString("type", id.toString());
|
||||
return nbt;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
package org.dimdev.dimdoors.world.decay;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
|
||||
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.api.util.ResourceUtil;
|
||||
import org.dimdev.dimdoors.network.ExtendedServerPlayNetworkHandler;
|
||||
import org.dimdev.dimdoors.network.packet.s2c.RenderBreakBlockS2CPacket;
|
||||
import org.dimdev.dimdoors.sound.ModSoundEvents;
|
||||
|
||||
/**
|
||||
* Provides methods for applying Limbo decay. Limbo decay refers to the effect that most blocks placed in Limbo
|
||||
* naturally change into stone, then cobble, then gravel, and finally Unraveled Fabric as time passes.
|
||||
*/
|
||||
public final class LimboDecay {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final Map<RegistryKey<World>, Set<DecayTask>> DECAY_QUEUE = new HashMap<>();
|
||||
|
||||
private static final Random RANDOM = Random.create();
|
||||
|
||||
/**
|
||||
* Checks the blocks orthogonally around a given location (presumably the location of an Unraveled Fabric block)
|
||||
* and applies Limbo decay to them. This gives the impression that decay spreads outward from Unraveled Fabric.
|
||||
*/
|
||||
public static void applySpreadDecay(ServerWorld world, BlockPos pos) {
|
||||
//Check if we randomly apply decay spread or not. This can be used to moderate the frequency of
|
||||
//full spread decay checks, which can also shift its performance impact on the game.
|
||||
if (RANDOM.nextDouble() < DimensionalDoors.getConfig().getLimboConfig().decaySpreadChance) {
|
||||
BlockState origin = world.getBlockState(pos);
|
||||
|
||||
//Apply decay to the blocks above, below, and on all four sides.
|
||||
// TODO: make max amount configurable
|
||||
int decayAmount = RANDOM.nextInt(5) + 1;
|
||||
List<Direction> directions = new ArrayList<>(Arrays.asList(Direction.values()));
|
||||
for (int i = 0; i < decayAmount; i++) {
|
||||
decayBlock(world, pos.offset(directions.remove(RANDOM.nextInt(5 - i))), origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a block can be decayed and, if so, changes it to the next block ID along the decay sequence.
|
||||
*/
|
||||
public static void decayBlock(ServerWorld world, BlockPos pos, BlockState origin) {
|
||||
BlockState targetState = world.getBlockState(pos);
|
||||
FluidState fluidState = world.getFluidState(pos);
|
||||
|
||||
Collection<DecayPattern> patterns = DecayLoader.getInstance().getPatterns(targetState.getBlock());
|
||||
|
||||
if(patterns.isEmpty()) patterns = DecayLoader.getInstance().getPatterns(fluidState.getFluid());
|
||||
|
||||
if(patterns.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for(DecayPattern pattern : patterns) {
|
||||
if (!pattern.test(world, pos, origin, targetState, fluidState)) {
|
||||
continue;
|
||||
}
|
||||
world.getPlayers(EntityPredicates.maxDistance(pos.getX(), pos.getY(), pos.getZ(), 100)).forEach(player -> {
|
||||
ExtendedServerPlayNetworkHandler.get(player.networkHandler).getDimDoorsPacketHandler().sendPacket(new RenderBreakBlockS2CPacket(pos, 5));
|
||||
});
|
||||
world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), ModSoundEvents.TEARING, SoundCategory.BLOCKS, 0.5f, 1f);
|
||||
queueDecay(world, pos, origin, pattern, DimensionalDoors.getConfig().getLimboConfig().limboDecay);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void queueDecay(ServerWorld world, BlockPos pos, BlockState origin, DecayPattern pattern, int delay) {
|
||||
DecayTask task = new DecayTask(pos, origin, pattern, delay);
|
||||
if (delay <= 0) {
|
||||
task.process(world);
|
||||
} else {
|
||||
DECAY_QUEUE.computeIfAbsent(world.getRegistryKey(), k -> new HashSet<>()).add(task);
|
||||
}
|
||||
}
|
||||
|
||||
public static void tick(ServerWorld world) {
|
||||
RegistryKey<World> key = world.getRegistryKey();
|
||||
if (DECAY_QUEUE.containsKey(key)) {
|
||||
Set<DecayTask> tasks = DECAY_QUEUE.get(key);
|
||||
Set<DecayTask> tasksToRun = tasks.stream().filter(DecayTask::reduceDelayIsDone).collect(Collectors.toSet());
|
||||
tasks.removeAll(tasksToRun);
|
||||
tasksToRun.forEach(task -> task.process(world));
|
||||
}
|
||||
}
|
||||
|
||||
public static class DecayLoader implements SimpleSynchronousResourceReloadListener {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final DecayLoader INSTANCE = new DecayLoader();
|
||||
private final Map<Block, List<DecayPattern>> blockPatterns = new HashMap<>();
|
||||
private final Map<Fluid, List<DecayPattern>> fluidPatterns = new HashMap<>();
|
||||
|
||||
private DecayLoader() {
|
||||
}
|
||||
|
||||
public static DecayLoader getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(ResourceManager manager) {
|
||||
blockPatterns.clear();
|
||||
CompletableFuture<List<DecayPattern>> futurePatternList = ResourceUtil.loadResourcePathToCollection(manager, "decay_patterns", ".json", new ArrayList<>(), ResourceUtil.NBT_READER.andThenReader(this::loadPattern));
|
||||
for (DecayPattern pattern : futurePatternList.join()) {
|
||||
for (Block block : pattern.constructApplicableBlocks()) {
|
||||
blockPatterns.computeIfAbsent(block, (b) -> new ArrayList<>());
|
||||
blockPatterns.get(block).add(pattern);
|
||||
}
|
||||
|
||||
for (Fluid fluid : pattern.constructApplicableFluids()) {
|
||||
fluidPatterns.computeIfAbsent(fluid, (b) -> new ArrayList<>());
|
||||
fluidPatterns.get(fluid).add(pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DecayPattern loadPattern(NbtElement nbt, Identifier ignored) {
|
||||
return DecayPattern.deserialize((NbtCompound) nbt);
|
||||
}
|
||||
|
||||
public Collection<DecayPattern> getPatterns(Block block) {
|
||||
return blockPatterns.getOrDefault(block, new ArrayList<>());
|
||||
}
|
||||
|
||||
public Collection<DecayPattern> getPatterns(Fluid fluid) {
|
||||
return fluidPatterns.getOrDefault(fluid, new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getFabricId() {
|
||||
return DimensionalDoors.id("decay_pattern");
|
||||
}
|
||||
}
|
||||
|
||||
private static class DecayTask {
|
||||
private final BlockPos pos;
|
||||
private final BlockState origin;
|
||||
private final DecayPattern processor;
|
||||
private int delay;
|
||||
|
||||
|
||||
public DecayTask(BlockPos pos, BlockState origin, DecayPattern processor, int delay) {
|
||||
this.pos = pos;
|
||||
this.origin = origin;
|
||||
this.processor = processor;
|
||||
this.delay = delay;
|
||||
}
|
||||
|
||||
public boolean reduceDelayIsDone() {
|
||||
return --delay <= 0;
|
||||
}
|
||||
|
||||
public void process(ServerWorld world) {
|
||||
BlockState targetBlock = world.getBlockState(pos);
|
||||
FluidState targetFluid = world.getFluidState(pos);
|
||||
if (world.isChunkLoaded(pos) && processor.test(world, pos, origin, targetBlock, targetFluid)) {
|
||||
world.getPlayers(EntityPredicates.maxDistance(pos.getX(), pos.getY(), pos.getZ(), 100)).forEach(player -> {
|
||||
ExtendedServerPlayNetworkHandler.get(player.networkHandler).getDimDoorsPacketHandler().sendPacket(new RenderBreakBlockS2CPacket(pos, -1));
|
||||
});
|
||||
world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), targetBlock.getSoundGroup().getBreakSound(), SoundCategory.BLOCKS, 0.5f, 1f);
|
||||
processor.process(world, pos, origin, targetBlock, targetFluid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package org.dimdev.dimdoors.world.decay.predicates;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.Streams;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.registry.entry.RegistryEntry;
|
||||
import net.minecraft.registry.tag.TagKey;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.dimdev.dimdoors.world.decay.DecayPredicate;
|
||||
|
||||
public class SimpleDecayPredicate implements DecayPredicate {
|
||||
public static final String KEY = "block";
|
||||
|
||||
private Block block;
|
||||
private TagKey<Block> tag;
|
||||
|
||||
public SimpleDecayPredicate() {}
|
||||
|
||||
public SimpleDecayPredicate(TagKey<Block> tag, Block block) {
|
||||
this.tag = tag;
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecayPredicate fromNbt(NbtCompound nbt) {
|
||||
String name = nbt.getString("entry");
|
||||
|
||||
if(name.startsWith("#")) tag = TagKey.of(RegistryKeys.BLOCK, Identifier.tryParse(name.substring(1)));
|
||||
else block = Registries.BLOCK.get(Identifier.tryParse(name));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toNbt(NbtCompound nbt) {
|
||||
DecayPredicate.super.toNbt(nbt);
|
||||
nbt.putString("entry", tag != null ? "#" + tag.id().toString() : Registries.BLOCK.getId(block).toString());
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecayPredicateType<? extends DecayPredicate> getType() {
|
||||
return DecayPredicateType.SIMPLE_PREDICATE_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(World world, BlockPos pos, BlockState origin, BlockState targetBlock, FluidState targetFluid) {
|
||||
return block != null ? targetBlock.isOf(block) : targetBlock.isIn(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Block> constructApplicableBlocks() {
|
||||
return block != null ? Set.of(block) : Streams.stream(Registries.BLOCK.iterateEntries(tag)).map(RegistryEntry::value).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private Block block;
|
||||
private TagKey<Block> tag;
|
||||
|
||||
public Builder block(Block block) {
|
||||
this.block = block;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder tag(TagKey<Block> tag) {
|
||||
this.tag = tag;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleDecayPredicate create() {
|
||||
return new SimpleDecayPredicate(tag, block);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package org.dimdev.dimdoors.world.decay.processors;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.TallPlantBlock;
|
||||
import net.minecraft.block.enums.DoubleBlockHalf;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.state.property.Property;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.dimdev.dimdoors.world.decay.DecayProcessor;
|
||||
|
||||
public class BlockDecayProcessor implements DecayProcessor {
|
||||
public static final String KEY = "block";
|
||||
|
||||
protected Block block;
|
||||
|
||||
protected int entropy;
|
||||
|
||||
public BlockDecayProcessor() {}
|
||||
|
||||
protected BlockDecayProcessor(Block block, int entropy) {
|
||||
this.block = block;
|
||||
this.entropy = entropy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecayProcessor fromNbt(NbtCompound json) {
|
||||
block = Registries.BLOCK.get(Identifier.tryParse(json.getString("block")));
|
||||
entropy = json.getInt("entropy");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toNbt(NbtCompound nbt) {
|
||||
DecayProcessor.super.toNbt(nbt);
|
||||
nbt.putString("block", Registries.BLOCK.getId(block).toString());
|
||||
nbt.putInt("entropy", entropy);
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecayProcessorType<? extends DecayProcessor> getType() {
|
||||
return DecayProcessorType.SIMPLE_PROCESSOR_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int process(World world, BlockPos pos, BlockState origin, BlockState target, FluidState targetFluid) {
|
||||
BlockState newState = block.getDefaultState();
|
||||
|
||||
if(target.getBlock() instanceof TallPlantBlock) pos = target.get(TallPlantBlock.HALF) == DoubleBlockHalf.UPPER ? pos.down() : pos;
|
||||
|
||||
Set<Property<?>> commonProperties = target.getProperties().stream().filter(newState.getProperties()::contains).collect(Collectors.toSet());
|
||||
for(Property<?> property : commonProperties) {
|
||||
newState = transferProperty(target, newState, property);
|
||||
}
|
||||
world.setBlockState(pos, newState);
|
||||
return entropy;
|
||||
}
|
||||
|
||||
private static <T extends Comparable<T>> BlockState transferProperty(BlockState from, BlockState to, Property<T> property) {
|
||||
return to.with(property, from.get(property));
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private Block block = Blocks.AIR;
|
||||
private int entropy;
|
||||
|
||||
public Builder block(Block block) {
|
||||
this.block = block;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder entropy(int entropy) {
|
||||
this.entropy = entropy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BlockDecayProcessor create() {
|
||||
return new BlockDecayProcessor(block, entropy);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package org.dimdev.dimdoors.world.decay.processors;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.DoorBlock;
|
||||
import net.minecraft.block.TrapdoorBlock;
|
||||
import net.minecraft.block.enums.DoorHinge;
|
||||
import net.minecraft.block.enums.DoubleBlockHalf;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.dimdev.dimdoors.world.decay.DecayProcessor;
|
||||
|
||||
public class DoorDecayProccessor implements DecayProcessor {
|
||||
public static final String KEY = "door";
|
||||
|
||||
protected Block block;
|
||||
|
||||
protected int entropy;
|
||||
|
||||
public DoorDecayProccessor() {}
|
||||
|
||||
protected DoorDecayProccessor(Block block, int entropy) {
|
||||
this.block = block;
|
||||
this.entropy = entropy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecayProcessor fromNbt(NbtCompound json) {
|
||||
block = Registries.BLOCK.get(Identifier.tryParse(json.getString("block")));
|
||||
entropy = json.getInt("entropy");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toNbt(NbtCompound nbt) {
|
||||
DecayProcessor.super.toNbt(nbt);
|
||||
nbt.putString("block", Registries.BLOCK.getId(block).toString());
|
||||
nbt.putInt("entropy", entropy);
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecayProcessorType<? extends DecayProcessor> getType() {
|
||||
return DecayProcessorType.DOOR_PROCESSOR_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int process(World world, BlockPos pos, BlockState origin, BlockState target, FluidState targetFluid) {
|
||||
if(target.getBlock() instanceof DoorBlock) {
|
||||
BlockPos otherPos = target.get(DoorBlock.HALF) == DoubleBlockHalf.UPPER ? pos.down() : pos.up();
|
||||
|
||||
Direction facing = target.get(DoorBlock.FACING);
|
||||
|
||||
if(target.get(DoorBlock.OPEN)) facing = target.get(DoorBlock.HINGE) == DoorHinge.RIGHT ? facing.rotateYCounterclockwise() : facing.rotateYClockwise();
|
||||
|
||||
BlockState newState = block.getDefaultState().with(TrapdoorBlock.OPEN, true).with(TrapdoorBlock.FACING, facing);
|
||||
|
||||
world.setBlockState(pos, newState);
|
||||
world.setBlockState(otherPos, newState);
|
||||
|
||||
return entropy;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private Block block = Blocks.AIR;
|
||||
private int entropy;
|
||||
|
||||
public Builder block(Block block) {
|
||||
this.block = block;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder entropy(int entropy) {
|
||||
this.entropy = entropy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DoorDecayProccessor create() {
|
||||
return new DoorDecayProccessor(block, entropy);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package org.dimdev.dimdoors.world.decay.processors;
|
||||
|
||||
import net.minecraft.block.BedBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.DoorBlock;
|
||||
import net.minecraft.block.TrapdoorBlock;
|
||||
import net.minecraft.block.enums.DoorHinge;
|
||||
import net.minecraft.block.enums.DoubleBlockHalf;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.dimdev.dimdoors.world.decay.DecayProcessor;
|
||||
|
||||
public class DoubleDecayProcessor implements DecayProcessor {
|
||||
public static final String KEY = "double";
|
||||
|
||||
protected Block block;
|
||||
|
||||
protected int entropy;
|
||||
|
||||
public DoubleDecayProcessor() {}
|
||||
|
||||
protected DoubleDecayProcessor(Block block, int entropy) {
|
||||
this.block = block;
|
||||
this.entropy = entropy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecayProcessor fromNbt(NbtCompound json) {
|
||||
block = Registries.BLOCK.get(Identifier.tryParse(json.getString("block")));
|
||||
entropy = json.getInt("entropy");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toNbt(NbtCompound nbt) {
|
||||
DecayProcessor.super.toNbt(nbt);
|
||||
nbt.putString("block", Registries.BLOCK.getId(block).toString());
|
||||
nbt.putInt("entropy", entropy);
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecayProcessorType<? extends DecayProcessor> getType() {
|
||||
return DecayProcessorType.DOOR_PROCESSOR_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int process(World world, BlockPos pos, BlockState origin, BlockState target, FluidState targetFluid) {
|
||||
if(target.getBlock() instanceof DoorBlock) {
|
||||
BlockPos otherPos = target.get(DoorBlock.HALF) == DoubleBlockHalf.UPPER ? pos.down() : pos.up();
|
||||
|
||||
Direction facing = target.get(DoorBlock.FACING);
|
||||
|
||||
if(target.get(DoorBlock.OPEN)) facing = target.get(DoorBlock.HINGE) == DoorHinge.RIGHT ? facing.rotateYCounterclockwise() : facing.rotateYClockwise();
|
||||
|
||||
BlockState newState = block.getDefaultState().with(TrapdoorBlock.OPEN, true).with(TrapdoorBlock.FACING, facing);
|
||||
|
||||
world.setBlockState(pos, newState);
|
||||
world.setBlockState(otherPos, newState);
|
||||
|
||||
return entropy;
|
||||
} else if(target.getBlock() instanceof BedBlock) {
|
||||
BlockPos otherPos = pos.offset(BedBlock.getOppositePartDirection(target));
|
||||
BlockState newState = block.getDefaultState();
|
||||
|
||||
world.setBlockState(pos, newState);
|
||||
world.setBlockState(otherPos, newState);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private Block block = Blocks.AIR;
|
||||
private int entropy;
|
||||
|
||||
public Builder block(Block block) {
|
||||
this.block = block;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder entropy(int entropy) {
|
||||
this.entropy = entropy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DoubleDecayProcessor create() {
|
||||
return new DoubleDecayProcessor(block, entropy);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package org.dimdev.dimdoors.world.decay.processors;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.dimdev.dimdoors.world.decay.DecayProcessor;
|
||||
|
||||
import static org.dimdev.dimdoors.world.decay.DecayProcessor.DecayProcessorType.SELF;
|
||||
|
||||
public class SelfDecayProcessor implements DecayProcessor {
|
||||
public static final String KEY = "self";
|
||||
|
||||
private static final SelfDecayProcessor instance = new SelfDecayProcessor();
|
||||
|
||||
public static SelfDecayProcessor instance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecayProcessor fromNbt(NbtCompound nbt) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecayProcessorType<? extends DecayProcessor> getType() {
|
||||
return SELF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int process(World world, BlockPos pos, BlockState origin, BlockState targetBlock, FluidState targetFluid) {
|
||||
world.setBlockState(pos, origin);
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
package org.dimdev.dimdoors.world.feature;
|
||||
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.world.biome.BiomeKeys;
|
||||
import net.minecraft.world.gen.GenerationStep;
|
||||
import net.minecraft.world.gen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
|
||||
import net.minecraft.world.gen.feature.Feature;
|
||||
import net.minecraft.world.gen.feature.PlacedFeature;
|
||||
|
||||
import net.fabricmc.fabric.api.biome.v1.BiomeModifications;
|
||||
import net.fabricmc.fabric.api.tag.convention.v1.ConventionalBiomeTags;
|
||||
|
||||
import org.dimdev.dimdoors.world.feature.gateway.LimboGatewayFeature;
|
||||
import org.dimdev.dimdoors.world.feature.gateway.schematic.EndGateway;
|
||||
import org.dimdev.dimdoors.world.feature.gateway.schematic.SandstonePillarsGateway;
|
||||
import org.dimdev.dimdoors.world.feature.gateway.schematic.SchematicGateway;
|
||||
import org.dimdev.dimdoors.world.feature.gateway.schematic.SchematicGatewayFeature;
|
||||
import org.dimdev.dimdoors.world.feature.gateway.schematic.SchematicGatewayFeatureConfig;
|
||||
import org.dimdev.dimdoors.world.feature.gateway.schematic.TwoPillarsGateway;
|
||||
|
||||
import static org.dimdev.dimdoors.DimensionalDoors.id;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class ModFeatures {
|
||||
public static final SchematicGateway SANDSTONE_PILLARS_GATEWAY = new SandstonePillarsGateway();
|
||||
public static final SchematicGateway TWO_PILLARS_GATEWAY = new TwoPillarsGateway();
|
||||
public static final SchematicGateway END_GATEWAY = new EndGateway();
|
||||
|
||||
public static final Feature<SchematicGatewayFeatureConfig> SCHEMATIC_GATEWAY_FEATURE = Registry.register(Registries.FEATURE, id("schematic_gateway"), new SchematicGatewayFeature(SchematicGatewayFeatureConfig.CODEC));
|
||||
public static final Feature<DefaultFeatureConfig> LIMBO_GATEWAY_FEATURE = Registry.register(Registries.FEATURE, id("limbo_gateway"), new LimboGatewayFeature());
|
||||
|
||||
public static void init() {
|
||||
SANDSTONE_PILLARS_GATEWAY.init();
|
||||
TWO_PILLARS_GATEWAY.init();
|
||||
END_GATEWAY.init();
|
||||
|
||||
Configured.init();
|
||||
Placed.init();
|
||||
}
|
||||
|
||||
public static final class Configured {
|
||||
public static final RegistryKey<ConfiguredFeature<?, ?>> SANDSTONE_PILLARS = of("sandstone_pillars");
|
||||
public static final RegistryKey<ConfiguredFeature<?, ?>> TWO_PILLARS = of("two_pillars");
|
||||
public static final RegistryKey<ConfiguredFeature<?, ?>> END_GATEWAY = of("end_gateway");
|
||||
public static final RegistryKey<ConfiguredFeature<?, ?>> LIMBO_GATEWAY = of("limbo_gateway");
|
||||
public static final RegistryKey<ConfiguredFeature<?, ?>> SOLID_STATIC_ORE = of("solid_static_ore");
|
||||
public static final RegistryKey<ConfiguredFeature<?, ?>> DECAYED_BLOCK_ORE = of("decayed_block_ore");
|
||||
public static final RegistryKey<ConfiguredFeature<?, ?>> ETERNAL_FLUID_SPRING = of("eternal_fluid_spring");
|
||||
|
||||
public static void init() {}
|
||||
|
||||
public static RegistryKey<ConfiguredFeature<?, ?>> of(String id) {
|
||||
return RegistryKey.of(RegistryKeys.CONFIGURED_FEATURE, id(id));
|
||||
}
|
||||
}
|
||||
|
||||
public static class Placed {
|
||||
public static final RegistryKey<PlacedFeature> SANDSTONE_PILLARS = of("sandstone_pillars");
|
||||
public static final RegistryKey<PlacedFeature> TWO_PILLARS = of("two_pillars");
|
||||
public static final RegistryKey<PlacedFeature> END_GATEWAY = of("end_gateway");
|
||||
public static final RegistryKey<PlacedFeature> LIMBO_GATEWAY = of("limbo_gateway");
|
||||
public static final RegistryKey<PlacedFeature> SOLID_STATIC_ORE = of("solid_static_ore");
|
||||
public static final RegistryKey<PlacedFeature> DECAYED_BLOCK_ORE = of("decayed_block_ore");
|
||||
public static final RegistryKey<PlacedFeature> ETERNAL_FLUID_SPRING = of("eternal_fluid_spring");
|
||||
|
||||
public static void init() {
|
||||
BiomeModifications.addFeature(ctx -> ctx.hasTag(ConventionalBiomeTags.IN_OVERWORLD) &&
|
||||
!ctx.hasTag(ConventionalBiomeTags.DESERT) &&
|
||||
!ctx.hasTag(ConventionalBiomeTags.OCEAN),
|
||||
GenerationStep.Feature.SURFACE_STRUCTURES,
|
||||
TWO_PILLARS
|
||||
);
|
||||
BiomeModifications.addFeature(
|
||||
ctx -> ctx.hasTag(ConventionalBiomeTags.DESERT),
|
||||
GenerationStep.Feature.SURFACE_STRUCTURES,
|
||||
SANDSTONE_PILLARS
|
||||
);
|
||||
|
||||
BiomeModifications.addFeature(
|
||||
ctx -> !ctx.getBiomeKey().equals(BiomeKeys.THE_END) && ctx.hasTag(ConventionalBiomeTags.IN_THE_END),
|
||||
GenerationStep.Feature.SURFACE_STRUCTURES,
|
||||
END_GATEWAY
|
||||
);
|
||||
}
|
||||
|
||||
public static RegistryKey<PlacedFeature> of(String id) {
|
||||
return RegistryKey.of(RegistryKeys.PLACED_FEATURE, id(id));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package org.dimdev.dimdoors.world.feature.gateway;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.StructureWorldAccess;
|
||||
|
||||
public interface Gateway {
|
||||
void generate(StructureWorldAccess world, BlockPos pos);
|
||||
|
||||
default boolean isLocationValid(StructureWorldAccess world, BlockPos pos) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package org.dimdev.dimdoors.world.feature.gateway;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.StructureWorldAccess;
|
||||
|
||||
import org.dimdev.dimdoors.block.ModBlocks;
|
||||
import org.dimdev.dimdoors.block.entity.ModBlockEntityTypes;
|
||||
import org.dimdev.dimdoors.rift.targets.EscapeTarget;
|
||||
import org.dimdev.dimdoors.world.ModDimensions;
|
||||
|
||||
public enum LimboGateway implements Gateway {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public void generate(StructureWorldAccess world, BlockPos pos) {
|
||||
if (!this.isLocationValid(world, pos)) {
|
||||
return;
|
||||
}
|
||||
BlockState unravelledFabric = ModBlocks.UNRAVELLED_FABRIC.getDefaultState();
|
||||
// Build the gateway out of Unraveled Fabric. Since nearly all the blocks in Limbo are of
|
||||
// that type, there is no point replacing the ground.
|
||||
world.setBlockState(pos.add(1, 3, 0), unravelledFabric, 2);
|
||||
world.setBlockState(pos.add(-1, 3, 0), unravelledFabric, 2);
|
||||
|
||||
// Build the columns around the door
|
||||
world.setBlockState(pos.add(-1, 2, 0), unravelledFabric, 2);
|
||||
world.setBlockState(pos.add(1, 2, 0), unravelledFabric, 2);
|
||||
world.setBlockState(pos.add(1, 1, 0), unravelledFabric, 2);
|
||||
world.setBlockState(pos.add(1, 1, 0), unravelledFabric, 2);
|
||||
|
||||
this.placePortal(world, pos.add(0, 1, 0), Direction.NORTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocationValid(StructureWorldAccess world, BlockPos pos) {
|
||||
return ModDimensions.isLimboDimension(world.toServerWorld());
|
||||
}
|
||||
|
||||
private void placePortal(StructureWorldAccess world, BlockPos pos, Direction facing) {
|
||||
world.setBlockState(pos, ModBlocks.DIMENSIONAL_PORTAL.getDefaultState(), 2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.dimdev.dimdoors.world.feature.gateway;
|
||||
|
||||
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
|
||||
import net.minecraft.world.gen.feature.Feature;
|
||||
import net.minecraft.world.gen.feature.util.FeatureContext;
|
||||
|
||||
public class LimboGatewayFeature extends Feature<DefaultFeatureConfig> {
|
||||
public LimboGatewayFeature() {
|
||||
super(DefaultFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generate(FeatureContext<DefaultFeatureConfig> context) {
|
||||
LimboGateway.INSTANCE.generate(context.getWorld(), context.getOrigin());
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.dimdev.dimdoors.world.feature.gateway.schematic;
|
||||
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.StructureWorldAccess;
|
||||
|
||||
public class EndGateway extends SchematicGateway{
|
||||
public EndGateway() {
|
||||
super("end_gateway");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(StructureWorldAccess structureWorldAccess, BlockPos blockPos) {
|
||||
return structureWorldAccess.getBlockState(blockPos.down()).isOf(Blocks.END_STONE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.dimdev.dimdoors.world.feature.gateway.schematic;
|
||||
|
||||
import net.minecraft.block.SandBlock;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.StructureWorldAccess;
|
||||
|
||||
public class SandstonePillarsGateway extends SchematicGateway {
|
||||
public SandstonePillarsGateway() {
|
||||
super("sandstone_pillars");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(StructureWorldAccess structureWorldAccess, BlockPos blockPos) {
|
||||
return structureWorldAccess.getBlockState(blockPos.down()).getBlock() instanceof SandBlock;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package org.dimdev.dimdoors.world.feature.gateway.schematic;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.StructureWorldAccess;
|
||||
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.api.util.BlockPlacementType;
|
||||
import org.dimdev.dimdoors.pockets.TemplateUtils;
|
||||
import org.dimdev.dimdoors.util.schematic.Schematic;
|
||||
import org.dimdev.dimdoors.util.schematic.SchematicPlacer;
|
||||
import org.dimdev.dimdoors.world.feature.gateway.Gateway;
|
||||
|
||||
public abstract class SchematicGateway implements Gateway, BiPredicate<StructureWorldAccess, BlockPos> {
|
||||
private Schematic schematic;
|
||||
private final String id;
|
||||
public static final BiMap<String, SchematicGateway> ID_SCHEMATIC_MAP = HashBiMap.create();
|
||||
private boolean replaced;
|
||||
|
||||
public SchematicGateway(String id) {
|
||||
ID_SCHEMATIC_MAP.putIfAbsent(id, this);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
String schematicJarDirectory = "/data/dimdoors/gateways/";
|
||||
|
||||
try (InputStream stream = DimensionalDoors.class.getResourceAsStream(schematicJarDirectory + this.id + ".schem")) {
|
||||
if (stream == null) {
|
||||
throw new RuntimeException("Schematic '" + this.id + "' was not found in the jar.");
|
||||
}
|
||||
try {
|
||||
this.schematic = Schematic.fromNbt(NbtIo.readCompressed(stream));
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Schematic file for " + this.id + " could not be read as a valid schematic NBT file.", ex);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public final void generate(StructureWorldAccess world, BlockPos pos) {
|
||||
if (DimensionalDoors.getConfig()
|
||||
.getWorldConfig()
|
||||
.gatewayDimBlacklist
|
||||
.contains(world.toServerWorld().getRegistryKey().getValue().toString())
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (!this.replaced) {
|
||||
TemplateUtils.replacePlaceholders(this.schematic, world);
|
||||
this.replaced = true;
|
||||
}
|
||||
SchematicPlacer.place(this.schematic, world, pos, BlockPlacementType.SECTION_NO_UPDATE_QUEUE_BLOCK_ENTITY);
|
||||
this.generateRandomBits(world, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates randomized portions of the gateway structure (e.g. rubble, foliage)
|
||||
*
|
||||
* @param world - the world in which to generate the gateway
|
||||
* @param pos - the position at which the schematic is placed
|
||||
*/
|
||||
protected void generateRandomBits(StructureWorldAccess world, BlockPos pos) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package org.dimdev.dimdoors.world.feature.gateway.schematic;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
|
||||
import net.minecraft.block.AirBlock;
|
||||
import net.minecraft.world.gen.feature.Feature;
|
||||
import net.minecraft.world.gen.feature.util.FeatureContext;
|
||||
|
||||
public class SchematicGatewayFeature extends Feature<SchematicGatewayFeatureConfig> {
|
||||
public SchematicGatewayFeature(Codec<SchematicGatewayFeatureConfig> codec) {
|
||||
super(codec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generate(FeatureContext<SchematicGatewayFeatureConfig> featureContext) {
|
||||
if (featureContext.getWorld().getBlockState(featureContext.getOrigin()).getBlock() instanceof AirBlock && featureContext.getConfig().getGateway().test(featureContext.getWorld(), featureContext.getOrigin())) {
|
||||
featureContext.getConfig().getGateway().generate(featureContext.getWorld(), featureContext.getOrigin());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package org.dimdev.dimdoors.world.feature.gateway.schematic;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import net.minecraft.world.gen.feature.FeatureConfig;
|
||||
|
||||
public class SchematicGatewayFeatureConfig implements FeatureConfig {
|
||||
public static final Codec<SchematicGatewayFeatureConfig> CODEC = RecordCodecBuilder.create((instance) -> instance.group(
|
||||
Codec.STRING.fieldOf("gatewayId").forGetter(SchematicGatewayFeatureConfig::getGatewayId)
|
||||
).apply(instance, SchematicGatewayFeatureConfig::new));
|
||||
|
||||
private final SchematicGateway gateway;
|
||||
private final String gatewayId;
|
||||
|
||||
public SchematicGatewayFeatureConfig(String id) {
|
||||
this.gatewayId = id;
|
||||
this.gateway = SchematicGateway.ID_SCHEMATIC_MAP.get(id);
|
||||
}
|
||||
|
||||
public SchematicGateway getGateway() {
|
||||
return this.gateway;
|
||||
}
|
||||
|
||||
public String getGatewayId() {
|
||||
return this.gatewayId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package org.dimdev.dimdoors.world.feature.gateway.schematic;
|
||||
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.StructureWorldAccess;
|
||||
|
||||
public class TwoPillarsGateway extends SchematicGateway {
|
||||
private static final int GATEWAY_RADIUS = 4;
|
||||
|
||||
public TwoPillarsGateway() {
|
||||
super("two_pillars");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateRandomBits(StructureWorldAccess world, BlockPos pos) {
|
||||
//Replace some of the ground around the gateway with bricks
|
||||
for (int xc = -GATEWAY_RADIUS; xc <= GATEWAY_RADIUS; xc++) {
|
||||
for (int zc = -GATEWAY_RADIUS; zc <= GATEWAY_RADIUS; zc++) {
|
||||
//Check that the block is supported by an opaque block.
|
||||
//This prevents us from building over a cliff, on the peak of a mountain,
|
||||
//or the surface of the ocean or a frozen lake.
|
||||
if (world.getBlockState(pos.add(xc, -1, zc)).getMaterial().isSolid()) {
|
||||
//Randomly choose whether to place bricks or not. The math is designed so that the
|
||||
//chances of placing a block decrease as we get farther from the gateway's center.
|
||||
int i = Math.abs(xc) + Math.abs(zc);
|
||||
if (i < world.getRandom().nextInt(2) + 3) {
|
||||
//Place Stone Bricks
|
||||
world.setBlockState(pos.add(xc, 0, zc), Blocks.STONE_BRICKS.getDefaultState(), 2);
|
||||
} else if (i < world.getRandom().nextInt(3) + 3) {
|
||||
//Place Cracked Stone Bricks
|
||||
world.setBlockState(pos.add(xc, 0, zc), Blocks.CRACKED_STONE_BRICKS.getDefaultState(), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(StructureWorldAccess structureWorldAccess, BlockPos blockPos) {
|
||||
return !structureWorldAccess.getBlockState(blockPos).isOf(Blocks.WATER);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package org.dimdev.dimdoors.world.level.component;
|
||||
|
||||
import dev.onyxstudios.cca.api.v3.component.Component;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
import net.fabricmc.fabric.api.util.NbtType;
|
||||
|
||||
import org.dimdev.dimdoors.DimensionalDoorsComponents;
|
||||
|
||||
public class ChunkLazilyGeneratedComponent implements Component {
|
||||
private boolean hasBeenLazyGenned = false;
|
||||
|
||||
public boolean hasBeenLazyGenned() {
|
||||
return hasBeenLazyGenned;
|
||||
}
|
||||
|
||||
public void setGenned() {
|
||||
if (hasBeenLazyGenned) throw new UnsupportedOperationException("This chunk seems to have already been lazily generated!");
|
||||
hasBeenLazyGenned = true;
|
||||
}
|
||||
|
||||
public static ChunkLazilyGeneratedComponent get(Chunk chunk) {
|
||||
return DimensionalDoorsComponents.CHUNK_LAZILY_GENERATED_COMPONENT_KEY.get(chunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNbt(NbtCompound nbt) {
|
||||
if (nbt.contains("has_been_lazy_genned", NbtType.INT)) {
|
||||
hasBeenLazyGenned = nbt.getInt("has_been_lazy_genned") == 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNbt(NbtCompound nbt) {
|
||||
if (hasBeenLazyGenned) {
|
||||
nbt.putInt("has_been_lazy_genned", 1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
package org.dimdev.dimdoors.world.level.registry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import dev.onyxstudios.cca.api.v3.component.ComponentV3;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Pair;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelProperties;
|
||||
|
||||
import org.dimdev.dimdoors.DimensionalDoorsComponents;
|
||||
import org.dimdev.dimdoors.rift.registry.RiftRegistry;
|
||||
import org.dimdev.dimdoors.world.ModDimensions;
|
||||
import org.dimdev.dimdoors.world.pocket.PocketDirectory;
|
||||
import org.dimdev.dimdoors.world.pocket.PrivateRegistry;
|
||||
|
||||
import static org.dimdev.dimdoors.DimensionalDoors.getServer;
|
||||
|
||||
public class DimensionalRegistry implements ComponentV3 {
|
||||
public static final int RIFT_DATA_VERSION = 1; // Increment this number every time a new schema is added
|
||||
private Map<RegistryKey<World>, PocketDirectory> pocketRegistry = new HashMap<>();
|
||||
private RiftRegistry riftRegistry = new RiftRegistry();
|
||||
private PrivateRegistry privateRegistry = new PrivateRegistry();
|
||||
|
||||
@Override
|
||||
public void readFromNbt(NbtCompound nbt) {
|
||||
int riftDataVersion = nbt.getInt("RiftDataVersion");
|
||||
if (riftDataVersion < RIFT_DATA_VERSION) {
|
||||
nbt = RiftSchemas.update(riftDataVersion, nbt);
|
||||
} else if (RIFT_DATA_VERSION < riftDataVersion) {
|
||||
throw new UnsupportedOperationException("Downgrading is not supported!");
|
||||
}
|
||||
|
||||
NbtCompound pocketRegistryNbt = nbt.getCompound("pocket_registry");
|
||||
CompletableFuture<Map<RegistryKey<World>, PocketDirectory>> futurePocketRegistry = CompletableFuture.supplyAsync(() -> pocketRegistryNbt.getKeys().stream().map(key -> {
|
||||
NbtCompound pocketDirectoryNbt = pocketRegistryNbt.getCompound(key);
|
||||
return CompletableFuture.supplyAsync(() -> new Pair<>(RegistryKey.of(RegistryKeys.WORLD, Identifier.tryParse(key)), PocketDirectory.readFromNbt(key, pocketDirectoryNbt)));
|
||||
}).parallel().map(CompletableFuture::join).collect(Collectors.toConcurrentMap(Pair::getLeft, Pair::getRight)));
|
||||
|
||||
NbtCompound privateRegistryNbt = nbt.getCompound("private_registry");
|
||||
CompletableFuture<PrivateRegistry> futurePrivateRegistry = CompletableFuture.supplyAsync(() -> {
|
||||
PrivateRegistry privateRegistry = new PrivateRegistry();
|
||||
privateRegistry.fromNbt(privateRegistryNbt);
|
||||
return privateRegistry;
|
||||
});
|
||||
|
||||
pocketRegistry = futurePocketRegistry.join();
|
||||
|
||||
NbtCompound riftRegistryNbt = nbt.getCompound("rift_registry");
|
||||
CompletableFuture<RiftRegistry> futureRiftRegistry = CompletableFuture.supplyAsync(() -> RiftRegistry.fromNbt(pocketRegistry, riftRegistryNbt));
|
||||
riftRegistry = futureRiftRegistry.join();
|
||||
|
||||
this.privateRegistry = futurePrivateRegistry.join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNbt(NbtCompound nbt) {
|
||||
CompletableFuture<NbtElement> futurePocketRegistryNbt = CompletableFuture.supplyAsync(() -> {
|
||||
List<CompletableFuture<Pair<String, NbtElement>>> futurePocketRegistryNbts = new ArrayList<>();
|
||||
pocketRegistry.forEach((key, value) -> futurePocketRegistryNbts.add(CompletableFuture.supplyAsync(() -> new Pair<>(key.getValue().toString(), value.writeToNbt()))));
|
||||
NbtCompound pocketRegistryNbt = new NbtCompound();
|
||||
futurePocketRegistryNbts.parallelStream().unordered().map(CompletableFuture::join).collect(Collectors.toConcurrentMap(Pair::getLeft, Pair::getRight)).forEach(pocketRegistryNbt::put);
|
||||
return pocketRegistryNbt;
|
||||
});
|
||||
|
||||
CompletableFuture<NbtElement> futureRiftRegistryNbt = CompletableFuture.supplyAsync(riftRegistry::toNbt);
|
||||
CompletableFuture<NbtElement> futurePrivateRegistryNbt = CompletableFuture.supplyAsync(() -> privateRegistry.toNbt(new NbtCompound()));
|
||||
|
||||
nbt.put("pocket_registry", futurePocketRegistryNbt.join());
|
||||
nbt.put("rift_registry", futureRiftRegistryNbt.join());
|
||||
nbt.put("private_registry", futurePrivateRegistryNbt.join());
|
||||
|
||||
nbt.putInt("RiftDataVersion", RIFT_DATA_VERSION);
|
||||
}
|
||||
|
||||
public static DimensionalRegistry instance() {
|
||||
return DimensionalDoorsComponents.DIMENSIONAL_REGISTRY_COMPONENT_KEY.get((LevelProperties) getServer().getSaveProperties());
|
||||
}
|
||||
|
||||
public static RiftRegistry getRiftRegistry() {
|
||||
return instance().riftRegistry;
|
||||
}
|
||||
|
||||
public static PrivateRegistry getPrivateRegistry() {
|
||||
return instance().privateRegistry;
|
||||
}
|
||||
|
||||
public static PocketDirectory getPocketDirectory(ResourceKey<Level> key) {
|
||||
if (!(ModDimensions.isPocketDimension(key))) {
|
||||
throw new UnsupportedOperationException("PocketRegistry is only available for pocket dimensions!");
|
||||
}
|
||||
|
||||
return instance().pocketRegistry.computeIfAbsent(key, PocketDirectory::new);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package org.dimdev.dimdoors.world.level.registry;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import com.mojang.datafixers.DSL;
|
||||
import com.mojang.datafixers.DataFixer;
|
||||
import com.mojang.datafixers.DataFixerBuilder;
|
||||
import com.mojang.datafixers.schemas.Schema;
|
||||
import com.mojang.serialization.Dynamic;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtOps;
|
||||
import net.minecraft.util.Util;
|
||||
|
||||
import org.dimdev.dimdoors.world.level.registry.schema.Schema1;
|
||||
|
||||
public class RiftSchemas {
|
||||
public static final DSL.TypeReference RIFT_DATA_TYPE_REF = () -> "rift_data";
|
||||
public static final int RIFT_DATA_VERSION = DimensionalRegistry.RIFT_DATA_VERSION;
|
||||
public static final BiFunction<Integer, Schema, Schema> EMPTY = Schema::new;
|
||||
public static final DataFixer DATA_FIXER = Util.make(new DataFixerBuilder(RIFT_DATA_VERSION), builder -> {
|
||||
builder.addSchema(1, Schema1::new);
|
||||
// TODO: add schemas if schema changes
|
||||
}).buildUnoptimized();
|
||||
|
||||
public static NbtCompound update(int oldVersion, NbtCompound original) {
|
||||
return (NbtCompound) DATA_FIXER.update(RIFT_DATA_TYPE_REF, new Dynamic<>( NbtOps.INSTANCE, original), oldVersion, RIFT_DATA_VERSION).getValue();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package org.dimdev.dimdoors.world.level.registry.schema;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.mojang.datafixers.DSL;
|
||||
import com.mojang.datafixers.schemas.Schema;
|
||||
import com.mojang.datafixers.types.templates.TypeTemplate;
|
||||
|
||||
import org.dimdev.dimdoors.world.level.registry.RiftSchemas;
|
||||
|
||||
public class Schema1 extends Schema {
|
||||
public Schema1(int versionKey, Schema parent) {
|
||||
super(versionKey, parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTypes(Schema schema, Map<String, Supplier<TypeTemplate>> entityTypes, Map<String, Supplier<TypeTemplate>> blockEntityTypes) {
|
||||
schema.registerType(false, RiftSchemas.RIFT_DATA_TYPE_REF, DSL::remainder);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package org.dimdev.dimdoors.world.pocket;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.NoiseColumn;
|
||||
import net.minecraft.world.level.StructureManager;
|
||||
import net.minecraft.world.level.biome.BiomeManager;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.levelgen.RandomState;
|
||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
public class BlankChunkGenerator extends ChunkGenerator {
|
||||
public static final Codec<BlankChunkGenerator> CODEC = RecordCodecBuilder.create((instance) ->
|
||||
instance.group(BiomeSource.CODEC.fieldOf("biome_source")
|
||||
.forGetter((generator) -> generator.biomeSource)
|
||||
).apply(instance, instance.stable(BlankChunkGenerator::of))
|
||||
);
|
||||
|
||||
private static BlankChunkGenerator of(BiomeSource biomeSource) {
|
||||
return new BlankChunkGenerator(biomeSource);
|
||||
}
|
||||
|
||||
private BlankChunkGenerator(BiomeSource biomeSource) {
|
||||
super(biomeSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec<? extends ChunkGenerator> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyCarvers(WorldGenRegion worldGenRegion, long l, RandomState randomState, BiomeManager biomeManager, StructureManager structureManager, ChunkAccess chunkAccess, GenerationStep.Carving carving) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildSurface(WorldGenRegion worldGenRegion, StructureManager structureManager, RandomState randomState, ChunkAccess chunkAccess) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnOriginalMobs(WorldGenRegion worldGenRegion) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGenDepth() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ChunkAccess> fillFromNoise(Executor executor, Blender blender, RandomState randomState, StructureManager structureManager, ChunkAccess chunkAccess) {
|
||||
return CompletableFuture.supplyAsync(() -> chunkAccess);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSeaLevel() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinY() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBaseHeight(int i, int j, Heightmap.Types types, LevelHeightAccessor levelHeightAccessor, RandomState randomState) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoiseColumn getBaseColumn(int i, int j, LevelHeightAccessor levelHeightAccessor, RandomState randomState) {
|
||||
return new NoiseColumn(0, new BlockState[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDebugScreenInfo(List<String> list, RandomState randomState, BlockPos blockPos) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,242 @@
|
|||
package org.dimdev.dimdoors.world.pocket;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.commands.TagCommand;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Pair;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.api.util.math.GridUtil;
|
||||
import org.dimdev.dimdoors.world.pocket.type.AbstractPocket;
|
||||
import org.dimdev.dimdoors.world.pocket.type.IdReferencePocket;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
|
||||
public class PocketDirectory {
|
||||
int gridSize; // Determines how much pockets in their dimension are spaced
|
||||
int privatePocketSize;
|
||||
int publicPocketSize;
|
||||
Map<Integer, AbstractPocket<?>> pockets;
|
||||
private SortedMap<Integer, Integer> nextIDMap;
|
||||
ResourceKey<Level> worldKey;
|
||||
|
||||
public PocketDirectory(ResourceKey<Level> worldKey) {
|
||||
this.gridSize = DimensionalDoors.getConfig().getPocketsConfig().pocketGridSize;
|
||||
this.worldKey = worldKey;
|
||||
this.nextIDMap = new TreeMap<>();
|
||||
this.pockets = new HashMap<>();
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public PocketDirectory(ResourceKey<Level> worldKey, int gridSize) {
|
||||
this.gridSize = gridSize;
|
||||
this.worldKey = worldKey;
|
||||
this.nextIDMap = new TreeMap<>();
|
||||
this.pockets = new HashMap<>();
|
||||
}
|
||||
|
||||
public static PocketDirectory readFromNbt(String id, CompoundTag nbt) {
|
||||
PocketDirectory directory = new PocketDirectory(ResourceKey.create(Registries.DIMENSION, new ResourceLocation(id)));
|
||||
// no need to parallelize
|
||||
directory.gridSize = nbt.getInt("grid_size");
|
||||
directory.privatePocketSize = nbt.getInt("private_pocket_size");
|
||||
directory.publicPocketSize = nbt.getInt("public_pocket_size");
|
||||
// same thing, too short anyways
|
||||
CompoundTag nextIdMapNbt = nbt.getCompound("next_id_map");
|
||||
directory.nextIDMap.putAll(nextIdMapNbt.getAllKeys().stream().collect(Collectors.toMap(Integer::parseInt, nextIdMapNbt::getInt)));
|
||||
|
||||
CompoundTag pocketsNbt = nbt.getCompound("pockets");
|
||||
directory.pockets = pocketsNbt.getAllKeys().stream().unordered().map(key -> {
|
||||
CompoundTag pocketNbt = pocketsNbt.getCompound(key);
|
||||
return CompletableFuture.supplyAsync(() -> new Pair<>(Integer.parseInt(key), AbstractPocket.deserialize(pocketNbt)));
|
||||
}).parallel().map(CompletableFuture::join).collect(Collectors.toConcurrentMap(Pair::getFirst, Pair::getSecond));
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
public CompoundTag writeToNbt() {
|
||||
CompoundTag nbt = new CompoundTag();
|
||||
nbt.putInt("grid_size", this.gridSize);
|
||||
nbt.putInt("private_pocket_size", this.privatePocketSize);
|
||||
nbt.putInt("public_pocket_size", this.publicPocketSize);
|
||||
|
||||
CompoundTag nextIdMapNbt = new CompoundTag();
|
||||
this.nextIDMap.forEach((key, value) -> nextIdMapNbt.putInt(key.toString(), value));
|
||||
nbt.put("next_id_map", nextIdMapNbt);
|
||||
|
||||
CompoundTag pocketsNbt = new CompoundTag();
|
||||
this.pockets.entrySet().parallelStream().unordered().map(entry -> CompletableFuture.supplyAsync(() -> new Pair<>(entry.getKey().toString(), entry.getValue().toNbt(new CompoundTag()))))
|
||||
.map(CompletableFuture::join).sequential().forEach(pair -> pocketsNbt.put(pair.getFirst(), pair.getSecond()));
|
||||
nbt.put("pockets", pocketsNbt);
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new blank pocket.
|
||||
*
|
||||
* @return The newly created pockets
|
||||
*/
|
||||
public <T extends Pocket> T newPocket(Pocket.PocketBuilder<?, T> builder) {
|
||||
Vec3i size = builder.getExpectedSize();
|
||||
int longest = Math.max(Math.max(size.getX(), size.getZ()), 1);
|
||||
longest = (Math.floorDiv(longest - 1, gridSize * 16)) + 1;
|
||||
|
||||
int base3Size = 1;
|
||||
while (longest > base3Size) {
|
||||
base3Size *= 3;
|
||||
}
|
||||
|
||||
int squaredSize = base3Size * base3Size;
|
||||
|
||||
int cursor = nextIDMap.headMap(base3Size+1).values().stream().mapToInt(num -> num).max().orElse(0);
|
||||
cursor = cursor - Math.floorMod(cursor, squaredSize);
|
||||
|
||||
Pocket pocketAt = getPocket(cursor);
|
||||
while (pocketAt != null) {
|
||||
size = pocketAt.getSize();
|
||||
longest = Math.max(size.getX(), size.getZ());
|
||||
longest = (longest / (gridSize * 16)) + 1;
|
||||
|
||||
int pocketBase3Size = 1;
|
||||
while (longest > pocketBase3Size) {
|
||||
pocketBase3Size *= 3;
|
||||
}
|
||||
|
||||
cursor += Math.max(squaredSize, pocketBase3Size * pocketBase3Size);
|
||||
pocketAt = getPocket(cursor);
|
||||
}
|
||||
|
||||
cursor = cursor + squaredSize - 1; // we actually want to use the last id of
|
||||
// the assigned grid space since it is in the bottom left corner
|
||||
|
||||
T pocket = builder
|
||||
.id(cursor)
|
||||
.world(worldKey)
|
||||
.range(squaredSize)
|
||||
.offsetOrigin(idToCenteredPos(cursor, base3Size, builder.getExpectedSize()))
|
||||
.build();
|
||||
|
||||
nextIDMap.put(base3Size, cursor + squaredSize);
|
||||
addPocket(pocket);
|
||||
|
||||
IdReferencePocket.IdReferencePocketBuilder idReferenceBuilder = IdReferencePocket.builder();
|
||||
for (int i = 1; i < squaredSize; i++) {
|
||||
addPocket(idReferenceBuilder
|
||||
.id(cursor - i)
|
||||
.world(worldKey)
|
||||
.referencedId(cursor)
|
||||
.build());
|
||||
}
|
||||
return pocket;
|
||||
}
|
||||
|
||||
private void addPocket(AbstractPocket<?> pocket) {
|
||||
pockets.put(pocket.getId(), pocket);
|
||||
}
|
||||
|
||||
// TODO: rework this method to remove references as well
|
||||
public void removePocket(int id) {
|
||||
this.pockets.remove(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pocket that occupies the GridPos which a certain ID represents, or null if there is no pocket at that GridPos.
|
||||
*
|
||||
* @return The pocket which occupies the GridPos represented by that ID, or null if there was no pocket occupying that GridPos.
|
||||
*/
|
||||
public Pocket getPocket(int id) {
|
||||
AbstractPocket<?> pocket = this.pockets.get(id);
|
||||
return pocket == null ? null : pocket.getReferencedPocket(this);
|
||||
}
|
||||
|
||||
public <P extends Pocket> P getPocket(int id, Class<P> clazz) {
|
||||
Pocket pocket = getPocket(id);
|
||||
if (clazz.isInstance(pocket)) return clazz.cast(pocket);
|
||||
return null;
|
||||
}
|
||||
|
||||
public GridUtil.GridPos idToGridPos(int id) {
|
||||
return GridUtil.idToGridPos(id);
|
||||
}
|
||||
|
||||
public int gridPosToID(GridUtil.GridPos pos) {
|
||||
return GridUtil.gridPosToID(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the default BlockPos where a pocket should be based on the ID. Use this only for placing
|
||||
* pockets, and use Pocket.getGridPos() for getting the position
|
||||
*
|
||||
* @param id The ID of the pocket
|
||||
* @return The BlockPos of the pocket
|
||||
*/
|
||||
public BlockPos idToPos(int id) {
|
||||
GridUtil.GridPos pos = this.idToGridPos(id);
|
||||
return new BlockPos(pos.x * this.gridSize * 16, 0, pos.z * this.gridSize * 16);
|
||||
}
|
||||
|
||||
public BlockPos idToCenteredPos(int id, int base3Size, Vec3i expectedSize) {
|
||||
GridUtil.GridPos pos = this.idToGridPos(id);
|
||||
// you actually need the "/ 2 * 16" here. "*8" would not work the same since it doesn't guarantee chunk alignment
|
||||
return new BlockPos((pos.x * this.gridSize * 16) + (base3Size * this.gridSize - expectedSize.getX() / 16) / 2 * 16, 0, (pos.z * this.gridSize * 16) + (base3Size * this.gridSize - expectedSize.getZ() / 16) / 2 * 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the ID of a pocket at a certain BlockPos.
|
||||
*
|
||||
* @param pos The position
|
||||
* @return The ID of the pocket, or -1 if there is no pocket at that location
|
||||
*/
|
||||
public int posToID(BlockPos pos) {
|
||||
return this.gridPosToID(new GridUtil.GridPos(Math.floorDiv(pos.getX(), this.gridSize * 16), Math.floorDiv(pos.getZ(), this.gridSize * 16)));
|
||||
}
|
||||
|
||||
public Pocket getPocketAt(BlockPos pos) { // TODO: use BlockPos
|
||||
return this.getPocket(this.posToID(pos));
|
||||
}
|
||||
|
||||
public boolean isWithinPocketBounds(BlockPos pos) {
|
||||
Pocket pocket = this.getPocketAt(pos);
|
||||
return pocket != null && pocket.isInBounds(pos);
|
||||
}
|
||||
|
||||
public int getGridSize() {
|
||||
return this.gridSize;
|
||||
}
|
||||
|
||||
public int getPrivatePocketSize() {
|
||||
return this.privatePocketSize;
|
||||
}
|
||||
|
||||
public int getPublicPocketSize() {
|
||||
return this.publicPocketSize;
|
||||
}
|
||||
|
||||
public Map<Integer, AbstractPocket<?>> getPockets() {
|
||||
return this.pockets;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
package org.dimdev.dimdoors.world.pocket;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Pair;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.dimdev.dimdoors.world.level.registry.DimensionalRegistry;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
import org.dimdev.dimdoors.world.pocket.type.PrivatePocket;
|
||||
|
||||
public class PrivateRegistry {
|
||||
protected static class PocketInfo {
|
||||
public final RegistryKey<World> world;
|
||||
public final int id;
|
||||
|
||||
public PocketInfo(RegistryKey<World> world, int id) {
|
||||
this.world = world;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public static NbtCompound toNbt(PocketInfo info) {
|
||||
NbtCompound nbt = new NbtCompound();
|
||||
nbt.putString("world", info.world.getValue().toString());
|
||||
nbt.putInt("id", info.id);
|
||||
return nbt;
|
||||
}
|
||||
|
||||
public static PocketInfo fromNbt(NbtCompound nbt) {
|
||||
return new PocketInfo(
|
||||
RegistryKey.of(RegistryKeys.WORLD, new Identifier(nbt.getString("world"))),
|
||||
nbt.getInt("id")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String DATA_NAME = "dimdoors_private_pockets";
|
||||
|
||||
protected BiMap<UUID, PocketInfo> privatePocketMap = HashBiMap.create(); // Player UUID -> Pocket Info TODO: fix AnnotatedNBT and use UUID rather than String
|
||||
|
||||
public PrivateRegistry() {
|
||||
}
|
||||
|
||||
public void fromNbt(NbtCompound nbt) {
|
||||
privatePocketMap.clear();
|
||||
NbtCompound privatePocketMapNbt = nbt.getCompound("private_pocket_map");
|
||||
CompletableFuture<Map<UUID, PocketInfo>> futurePrivatePocketMap = CompletableFuture.supplyAsync(() ->
|
||||
privatePocketMapNbt.getKeys().stream().unordered().map(key -> {
|
||||
NbtCompound pocketInfoNbt = privatePocketMapNbt.getCompound(key);
|
||||
return CompletableFuture.supplyAsync(() -> new Pair<>(UUID.fromString(key), PocketInfo.fromNbt(pocketInfoNbt)));
|
||||
}).parallel().map(CompletableFuture::join).collect(Collectors.toConcurrentMap(Pair::getLeft, Pair::getRight)));
|
||||
|
||||
futurePrivatePocketMap.join().forEach(this.privatePocketMap::put);
|
||||
}
|
||||
|
||||
public NbtCompound toNbt(NbtCompound nbt) {
|
||||
CompletableFuture<NbtCompound> futurePrivatePocketMapNbt = CompletableFuture.supplyAsync(() -> {
|
||||
Map<String, NbtElement> privatePocketNbtMap = this.privatePocketMap.entrySet().parallelStream().unordered().collect(Collectors.toConcurrentMap(entry -> entry.getKey().toString(), entry -> PocketInfo.toNbt(entry.getValue())));
|
||||
NbtCompound privatePocketMapNbt = new NbtCompound();
|
||||
privatePocketNbtMap.forEach(privatePocketMapNbt::put);
|
||||
return privatePocketMapNbt;
|
||||
});
|
||||
|
||||
nbt.put("private_pocket_map", futurePrivatePocketMapNbt.join());
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
public PrivatePocket getPrivatePocket(UUID playerUUID) {
|
||||
PocketInfo pocket = this.privatePocketMap.get(playerUUID);
|
||||
if (pocket == null) return null;
|
||||
return DimensionalRegistry.getPocketDirectory(pocket.world).getPocket(pocket.id, PrivatePocket.class);
|
||||
}
|
||||
|
||||
public void setPrivatePocketID(UUID playerUUID, Pocket pocket) {
|
||||
this.privatePocketMap.put(playerUUID, new PocketInfo(pocket.getWorld(), pocket.getId()));
|
||||
}
|
||||
|
||||
public UUID getPrivatePocketOwner(Pocket pocket) {
|
||||
return this.privatePocketMap.inverse().get(new PocketInfo(pocket.getWorld(), pocket.getId()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
package org.dimdev.dimdoors.world.pocket;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkSectionPos;
|
||||
import net.minecraft.world.Heightmap;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.api.util.Location;
|
||||
import org.dimdev.dimdoors.world.ModDimensions;
|
||||
import org.dimdev.dimdoors.world.level.registry.DimensionalRegistry;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
|
||||
import static net.minecraft.world.World.OVERWORLD;
|
||||
import static net.minecraft.world.level.Level.OVERWORLD;
|
||||
|
||||
public class VirtualLocation {
|
||||
public static Codec<VirtualLocation> CODEC = RecordCodecBuilder.create(instance ->
|
||||
instance.group(
|
||||
Level.RESOURCE_KEY_CODEC.fieldOf("world").forGetter(virtualLocation -> virtualLocation.world),
|
||||
Codec.INT.fieldOf("x").forGetter(virtualLocation -> virtualLocation.x),
|
||||
Codec.INT.fieldOf("z").forGetter(virtualLocation -> virtualLocation.z),
|
||||
Codec.INT.fieldOf("depth").forGetter(virtualLocation -> virtualLocation.depth)
|
||||
).apply(instance, VirtualLocation::new)
|
||||
);
|
||||
|
||||
private final ResourceKey<Level> world;
|
||||
private final int x;
|
||||
private final int z;
|
||||
private final int depth;
|
||||
|
||||
public VirtualLocation(ResourceKey<Level> world, int x, int z, int depth) {
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.depth = depth;
|
||||
}
|
||||
|
||||
public static CompoundTag toNbt(VirtualLocation virtualLocation) {
|
||||
CompoundTag nbt = new CompoundTag();
|
||||
nbt.putString("world", virtualLocation.world.location().toString());
|
||||
nbt.putInt("x", virtualLocation.x);
|
||||
nbt.putInt("z", virtualLocation.z);
|
||||
nbt.putInt("depth", virtualLocation.depth);
|
||||
return nbt;
|
||||
}
|
||||
|
||||
public static VirtualLocation fromNbt(CompoundTag nbt) {
|
||||
return new VirtualLocation(
|
||||
ResourceKey.create(Registries.DIMENSION, new ResourceLocation(nbt.getString("world"))),
|
||||
nbt.getInt("x"),
|
||||
nbt.getInt("z"),
|
||||
nbt.getInt("depth")
|
||||
);
|
||||
}
|
||||
|
||||
public static VirtualLocation fromLocation(Location location) {
|
||||
VirtualLocation virtualLocation = null;
|
||||
|
||||
if (ModDimensions.isPocketDimension(location.world)) {
|
||||
Pocket pocket = DimensionalRegistry.getPocketDirectory(location.world).getPocketAt(location.pos);
|
||||
if (pocket != null) {
|
||||
virtualLocation = pocket.virtualLocation; // TODO: pockets-relative coordinates
|
||||
} else {
|
||||
virtualLocation = null; // TODO: door was placed in a pockets dim but outside of a pockets...
|
||||
}
|
||||
} else if (ModDimensions.isLimboDimension(location.getWorld())) { // TODO: convert to interface on worldprovider
|
||||
virtualLocation = new VirtualLocation(location.world, location.getX(), location.getZ(), DimensionalDoors.getConfig().getDungeonsConfig().maxDungeonDepth);
|
||||
} // TODO: nether coordinate transform
|
||||
|
||||
if (virtualLocation == null) {
|
||||
return new VirtualLocation(OVERWORLD, location.getX(), location.getZ(), 5);
|
||||
}
|
||||
return new VirtualLocation(location.getWorldId(), location.getX(), location.getZ(), virtualLocation.getDepth());
|
||||
}
|
||||
|
||||
public Location projectToWorld(boolean acceptLimbo) {
|
||||
ServerLevel world = DimensionalDoors.getServer().getLevel(this.world);
|
||||
|
||||
if (!acceptLimbo && ModDimensions.isLimboDimension(world)) {
|
||||
world = world.getServer().overworld();
|
||||
}
|
||||
|
||||
float spread = DimensionalDoors.getConfig().getGeneralConfig().depthSpreadFactor * this.depth;
|
||||
int newX = (int) (this.x + spread * 2 * (Math.random() - 0.5));
|
||||
int newZ = (int) (this.z + spread * 2 * (Math.random() - 0.5));
|
||||
//BlockPos pos = world.getTopPosition(Heightmap.Type.WORLD_SURFACE, new BlockPos(newX, 1, newZ));
|
||||
BlockPos pos = getTopPos(world, newX, newZ).above();
|
||||
return new Location(world, pos);
|
||||
}
|
||||
|
||||
public static BlockPos getTopPos(Level world, int x, int z) {
|
||||
int topHeight = world.getChunk(SectionPos.blockToSectionCoord(x), SectionPos.blockToSectionCoord(z)) // guarantees WorldChunk
|
||||
.getHeight(Heightmap.Types.MOTION_BLOCKING, x, z);
|
||||
return new BlockPos(x, topHeight, z);
|
||||
}
|
||||
|
||||
public ResourceKey<Level> getWorld() {
|
||||
return this.world;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return this.z;
|
||||
}
|
||||
|
||||
public int getDepth() {
|
||||
return this.depth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add("world", this.world)
|
||||
.add("x", this.x)
|
||||
.add("z", this.z)
|
||||
.add("depth", this.depth)
|
||||
.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import dev.architectury.registry.registries.Registrar;
|
||||
import dev.architectury.registry.registries.RegistrarManager;
|
||||
import dev.architectury.registry.registries.RegistrySupplier;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.ResourceKey;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.registry.SimpleRegistry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraft.world.Level;
|
||||
|
||||
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
|
||||
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.world.pocket.PocketDirectory;
|
||||
|
||||
public abstract class AbstractPocket<V extends AbstractPocket<?>> {
|
||||
public static final Registrar<AbstractPocketType<? extends AbstractPocket<?>>> REGISTRY = RegistrarManager.get(DimensionalDoors.MOD_ID).<AbstractPocketType<? extends AbstractPocket<?>>>builder(DimensionalDoors.id("abstract_pocket_type")).build();
|
||||
|
||||
protected Integer id;
|
||||
protected ResourceKey<Level> world;
|
||||
|
||||
public AbstractPocket(int id, ResourceKey<Level> world) {
|
||||
this.id = id;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
protected AbstractPocket() {
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static AbstractPocket<? extends AbstractPocket<?>> deserialize(CompoundTag nbt) {
|
||||
ResourceLocation id = ResourceLocation.tryParse(nbt.getString("type"));
|
||||
return REGISTRY.get(id).fromNbt(nbt);
|
||||
}
|
||||
|
||||
public static AbstractPocketBuilder<?, ?> deserializeBuilder(CompoundTag nbt) {
|
||||
ResourceLocation id = ResourceLocation.tryParse(nbt.getString("type"));
|
||||
return REGISTRY.get(id).builder().fromNbt(nbt);
|
||||
}
|
||||
|
||||
public static CompoundTag serialize(AbstractPocket<?> pocket) {
|
||||
return pocket.toNbt(new CompoundTag());
|
||||
}
|
||||
|
||||
public V fromNbt(CompoundTag nbt) {
|
||||
this.id = nbt.getInt("id");
|
||||
this.world = ResourceKey.create(Registries.DIMENSION, new ResourceLocation(nbt.getString("world")));
|
||||
|
||||
return (V) this;
|
||||
}
|
||||
|
||||
public CompoundTag toNbt(CompoundTag nbt) {
|
||||
nbt.putInt("id", id);
|
||||
nbt.putString("world", world.location().toString());
|
||||
|
||||
getType().toNbt(nbt);
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
public abstract AbstractPocketType<?> getType();
|
||||
|
||||
public Map<String, Double> toVariableMap(Map<String, Double> variableMap) {
|
||||
variableMap.put("id", (double) this.id);
|
||||
return variableMap;
|
||||
}
|
||||
|
||||
public abstract Pocket getReferencedPocket();
|
||||
|
||||
// for bypassing the world check in some cases
|
||||
public Pocket getReferencedPocket(PocketDirectory directory) {
|
||||
return getReferencedPocket();
|
||||
}
|
||||
|
||||
public ResourceKey<Level> getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public interface AbstractPocketType<T extends AbstractPocket<?>> {
|
||||
RegistrySupplier<AbstractPocketType<IdReferencePocket>> ID_REFERENCE = register(DimensionalDoors.id(IdReferencePocket.KEY), IdReferencePocket::new, IdReferencePocket::builder);
|
||||
|
||||
RegistrySupplier<AbstractPocketType<Pocket>> POCKET = register(DimensionalDoors.id(Pocket.KEY), Pocket::new, Pocket::builder);
|
||||
RegistrySupplier<AbstractPocketType<PrivatePocket>> PRIVATE_POCKET = register(DimensionalDoors.id(PrivatePocket.KEY), PrivatePocket::new, PrivatePocket::builderPrivatePocket);
|
||||
RegistrySupplier<AbstractPocketType<LazyGenerationPocket>> LAZY_GENERATION_POCKET = register(DimensionalDoors.id(LazyGenerationPocket.KEY), LazyGenerationPocket::new, LazyGenerationPocket::builderLazyGenerationPocket);
|
||||
|
||||
|
||||
T fromNbt(CompoundTag nbt);
|
||||
|
||||
CompoundTag toNbt(CompoundTag nbt);
|
||||
|
||||
T instance();
|
||||
|
||||
AbstractPocketBuilder<?, T> builder();
|
||||
|
||||
static void register() {
|
||||
DimensionalDoors.apiSubscribers.forEach(d -> d.registerAbstractPocketTypes(REGISTRY));
|
||||
}
|
||||
|
||||
static <U extends AbstractPocket<P>, P extends AbstractPocket<P>> RegistrySupplier<AbstractPocketType<U>> register(ResourceLocation id, Supplier<U> supplier, Supplier<? extends AbstractPocketBuilder<?, U>> factorySupplier) {
|
||||
return REGISTRY.register(id, () -> new AbstractPocketType<U>() {
|
||||
@Override
|
||||
public U fromNbt(CompoundTag nbt) {
|
||||
return (U) supplier.get().fromNbt(nbt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toNbt(CompoundTag nbt) {
|
||||
nbt.putString("type", id.toString());
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public U instance() {
|
||||
return supplier.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractPocketBuilder<?, U> builder() {
|
||||
return factorySupplier.get();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class AbstractPocketBuilder<P extends AbstractPocketBuilder<P, T>, T extends AbstractPocket<?>> {
|
||||
protected final AbstractPocketType<T> type;
|
||||
|
||||
private int id;
|
||||
private ResourceKey<Level> world;
|
||||
|
||||
protected AbstractPocketBuilder(AbstractPocketType<T> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Vec3i getExpectedSize() {
|
||||
return new Vec3i(1, 1, 1);
|
||||
}
|
||||
|
||||
public T build() {
|
||||
T instance = type.instance();
|
||||
|
||||
instance.id = id;
|
||||
instance.world = world;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public P id(int id) {
|
||||
this.id = id;
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public P world(ResourceKey<Level> world) {
|
||||
this.world = world;
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public P getSelf() {
|
||||
return (P) this;
|
||||
}
|
||||
|
||||
abstract public P fromNbt(CompoundTag nbt);
|
||||
|
||||
abstract public CompoundTag toNbt(CompoundTag nbt);
|
||||
|
||||
/*
|
||||
public P fromTag(CompoundTag tag) {
|
||||
id = tag.getInt("id");
|
||||
world = ResourceKey.of(Registry.DIMENSION, new ResourceLocation(tag.getString("world")));
|
||||
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
tag.putInt("id", id);
|
||||
tag.putString("world", world.getValue().toString());
|
||||
|
||||
return tag;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
|
||||
import net.fabricmc.fabric.api.util.NbtType;
|
||||
|
||||
import org.dimdev.dimdoors.world.level.registry.DimensionalRegistry;
|
||||
import org.dimdev.dimdoors.world.pocket.PocketDirectory;
|
||||
|
||||
public class IdReferencePocket extends AbstractPocket<IdReferencePocket> {
|
||||
public static String KEY = "id_reference";
|
||||
|
||||
protected int referencedId;
|
||||
|
||||
@Override
|
||||
public IdReferencePocket fromNbt(NbtCompound nbt) {
|
||||
super.fromNbt(nbt);
|
||||
|
||||
this.referencedId = nbt.getInt("referenced_id");
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toNbt(NbtCompound nbt) {
|
||||
nbt = super.toNbt(nbt);
|
||||
|
||||
nbt.putInt("referenced_id", referencedId);
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractPocketType<IdReferencePocket> getType() {
|
||||
return AbstractPocketType.ID_REFERENCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pocket getReferencedPocket() {
|
||||
return getReferencedPocket(DimensionalRegistry.getPocketDirectory(getWorld()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pocket getReferencedPocket(PocketDirectory directory) {
|
||||
return directory.getPocket(referencedId);
|
||||
}
|
||||
|
||||
public static IdReferencePocketBuilder builder() {
|
||||
return new IdReferencePocketBuilder(AbstractPocketType.ID_REFERENCE);
|
||||
}
|
||||
|
||||
public static class IdReferencePocketBuilder extends AbstractPocketBuilder<IdReferencePocketBuilder, IdReferencePocket> {
|
||||
private int referencedId = Integer.MIN_VALUE;
|
||||
|
||||
protected IdReferencePocketBuilder(AbstractPocketType<IdReferencePocket> type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdReferencePocket build() {
|
||||
IdReferencePocket pocket = super.build();
|
||||
pocket.referencedId = referencedId;
|
||||
return pocket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdReferencePocketBuilder fromNbt(NbtCompound nbt) {
|
||||
if (nbt.contains("referenced_id", NbtType.INT)) referencedId = nbt.getInt("referenced_id");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toNbt(NbtCompound nbt) {
|
||||
if (referencedId != Integer.MIN_VALUE) nbt.putInt("referenced_id", referencedId);
|
||||
return nbt;
|
||||
}
|
||||
|
||||
public IdReferencePocketBuilder referencedId(int referencedId) {
|
||||
this.referencedId = referencedId;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
import net.fabricmc.fabric.api.util.NbtType;
|
||||
|
||||
import org.dimdev.dimdoors.api.util.BlockBoxUtil;
|
||||
import org.dimdev.dimdoors.pockets.generator.LazyPocketGenerator;
|
||||
import org.dimdev.dimdoors.pockets.generator.PocketGenerator;
|
||||
import org.dimdev.dimdoors.world.level.component.ChunkLazilyGeneratedComponent;
|
||||
|
||||
public class LazyGenerationPocket extends Pocket {
|
||||
public static String KEY = "lazy_gen_pocket";
|
||||
|
||||
private LazyPocketGenerator generator;
|
||||
private int toBeGennedChunkCount = 0;
|
||||
|
||||
public void chunkLoaded(Chunk chunk) {
|
||||
if (isDoneGenerating()) return;
|
||||
|
||||
ChunkLazilyGeneratedComponent lazyGenned = ChunkLazilyGeneratedComponent.get(chunk);
|
||||
if (lazyGenned.hasBeenLazyGenned()) return;
|
||||
|
||||
BlockBox chunkBox = BlockBoxUtil.getBox(chunk);
|
||||
if (!chunkBox.intersects(getBox())) return;
|
||||
|
||||
generator.generateChunk(this, chunk);
|
||||
lazyGenned.setGenned();
|
||||
toBeGennedChunkCount--;
|
||||
|
||||
if (isDoneGenerating()) {
|
||||
this.generator = null; // saving up on some ram
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDoneGenerating() {
|
||||
return toBeGennedChunkCount == 0;
|
||||
}
|
||||
|
||||
public void attachGenerator(LazyPocketGenerator generator) {
|
||||
this.generator = generator;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
BlockBox box = getBox();
|
||||
|
||||
toBeGennedChunkCount = (Math.floorDiv(box.getMaxX(), 16) - Math.floorDiv(box.getMinX(), 16) + 1) * (Math.floorDiv(box.getMaxZ(), 16) - Math.floorDiv(box.getMinZ(), 16) + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toNbt(NbtCompound nbt) {
|
||||
super.toNbt(nbt);
|
||||
|
||||
if (generator != null) nbt.put("generator", generator.toNbt(new NbtCompound()));
|
||||
if (toBeGennedChunkCount > 0) nbt.putInt("to_be_genned_chunks", toBeGennedChunkCount);
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractPocketType<?> getType() {
|
||||
return AbstractPocketType.LAZY_GENERATION_POCKET;
|
||||
}
|
||||
|
||||
public static String getKEY() {
|
||||
return KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pocket fromNbt(NbtCompound nbt) {
|
||||
super.fromNbt(nbt);
|
||||
|
||||
if (nbt.contains("generator", NbtType.COMPOUND)) generator = (LazyPocketGenerator) PocketGenerator.deserialize(nbt.getCompound("generator"));
|
||||
if (nbt.contains("to_be_genned_chunks", NbtType.INT)) toBeGennedChunkCount = nbt.getInt("to_be_genned_chunks");
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<BlockPos, BlockEntity> getBlockEntities() {
|
||||
|
||||
return super.getBlockEntities();
|
||||
}
|
||||
|
||||
public static LazyGenerationPocketBuilder<?, LazyGenerationPocket> builderLazyGenerationPocket() {
|
||||
return new LazyGenerationPocketBuilder<>(AbstractPocketType.LAZY_GENERATION_POCKET);
|
||||
}
|
||||
|
||||
public static class LazyGenerationPocketBuilder<P extends LazyGenerationPocketBuilder<P, T>, T extends LazyGenerationPocket> extends PocketBuilder<P, T> {
|
||||
protected LazyGenerationPocketBuilder(AbstractPocketType<T> type) {
|
||||
super(type);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,284 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.world.level.registry.DimensionalRegistry;
|
||||
import org.dimdev.dimdoors.world.pocket.VirtualLocation;
|
||||
import org.dimdev.dimdoors.world.pocket.type.addon.AddonProvider;
|
||||
import org.dimdev.dimdoors.world.pocket.type.addon.PocketAddon;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Pocket extends AbstractPocket<Pocket> implements AddonProvider {
|
||||
public static String KEY = "pocket";
|
||||
|
||||
private final Map<ResourceLocation, PocketAddon> addons = new HashMap<>();
|
||||
private int range = -1;
|
||||
private BoundingBox box; // TODO: make protected
|
||||
public VirtualLocation virtualLocation;
|
||||
|
||||
public Pocket(int id, ResourceKey<Level> world, int x, int z) {
|
||||
super(id, world);
|
||||
int gridSize = DimensionalRegistry.getPocketDirectory(world).getGridSize() * 16;
|
||||
this.box = BoundingBox.fromCorners(new Vec3i(x * gridSize, 0, z * gridSize), new Vec3i((x + 1) * gridSize, 0, (z + 1) * gridSize));
|
||||
this.virtualLocation = new VirtualLocation(world, x, z, 0);
|
||||
}
|
||||
|
||||
protected Pocket() {
|
||||
}
|
||||
|
||||
public boolean hasAddon(ResourceLocation id) {
|
||||
return addons.containsKey(id);
|
||||
}
|
||||
|
||||
public <C extends PocketAddon> boolean addAddon(C addon) {
|
||||
if (addon.applicable(this)) {
|
||||
addon.addAddon(addons);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public <C extends PocketAddon> C getAddon(ResourceLocation id) {
|
||||
return (C) addons.get(id);
|
||||
}
|
||||
|
||||
public <T> List<T> getAddonsInstanceOf(Class<T> clazz) {
|
||||
return addons.values().stream()
|
||||
.filter(clazz::isInstance)
|
||||
.map(clazz::cast)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public boolean isInBounds(BlockPos pos) {
|
||||
return this.box.isInside(pos);
|
||||
}
|
||||
|
||||
public BlockPos getOrigin() {
|
||||
return new BlockPos(this.box.minX(), this.box.minY(), this.box.minZ());
|
||||
}
|
||||
|
||||
public void offsetOrigin(Vec3i vec) {
|
||||
this.box.move(vec);
|
||||
}
|
||||
|
||||
public void offsetOrigin(int x, int y, int z) {
|
||||
this.box.move(x, y, z);
|
||||
}
|
||||
|
||||
public void setSize(Vec3i size) {
|
||||
setSize(size.getX(), size.getY(), size.getZ());
|
||||
}
|
||||
|
||||
public void setSize(int x, int y, int z) {
|
||||
this.box = BoundingBox.fromCorners(new Vec3i(this.box.minX(), this.box.minY(), this.box.minZ()), new Vec3i(this.box.minX() + x - 1, this.box.minY() + y - 1, this.box.minZ() + z - 1));
|
||||
}
|
||||
|
||||
public void setRange(int range) {
|
||||
if (this.range > 0) throw new UnsupportedOperationException("Cannot set range of Pocket that has already been initialized.");
|
||||
this.range = range;
|
||||
}
|
||||
|
||||
public int getRange() {
|
||||
if (range < 1) throw new UnsupportedOperationException("Range of pocket has not been initialized yet.");
|
||||
return range;
|
||||
}
|
||||
|
||||
public Vec3i getSize() {
|
||||
return this.box.getLength();
|
||||
}
|
||||
|
||||
public CompoundTag toNbt(CompoundTag nbt) {
|
||||
super.toNbt(nbt);
|
||||
|
||||
nbt.putInt("range", range);
|
||||
nbt.putIntArray("box", IntStream.of(this.box.minX(), this.box.minY(), this.box.minZ(), this.box.maxX(), this.box.maxY(), this.box.maxZ()).toArray());
|
||||
nbt.put("virtualLocation", VirtualLocation.toNbt(this.virtualLocation));
|
||||
|
||||
ListTag addonsTag = new ListTag();
|
||||
addonsTag.addAll(addons.values().stream().map(addon -> addon.toNbt(new CompoundTag())).collect(Collectors.toList()));
|
||||
if (addonsTag.size() > 0) nbt.put("addons", addonsTag);
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractPocketType<?> getType() {
|
||||
return AbstractPocketType.POCKET.get();
|
||||
}
|
||||
|
||||
public Pocket fromNbt(CompoundTag nbt) {
|
||||
super.fromNbt(nbt);
|
||||
|
||||
this.range = nbt.getInt("range");
|
||||
int[] box = nbt.getIntArray("box");
|
||||
this.box = BoundingBox.fromCorners(new Vec3i(box[0], box[1], box[2]), new Vec3i(box[3], box[4], box[5]));
|
||||
this.virtualLocation = VirtualLocation.fromNbt(nbt.getCompound("virtualLocation"));
|
||||
|
||||
if (nbt.contains("addons", Tag.TAG_LIST)) {
|
||||
for (Tag addonTag : nbt.getList("addons", Tag.TAG_COMPOUND)) {
|
||||
PocketAddon addon = PocketAddon.deserialize((CompoundTag) addonTag);
|
||||
addons.put(addon.getId(), addon);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Map<BlockPos, BlockEntity> getBlockEntities() {
|
||||
Level serverWorld = DimensionalDoors.getWorld(this.getWorld());
|
||||
Map<BlockPos, BlockEntity> blockEntities = new HashMap<>();
|
||||
ChunkPos.rangeClosed(new ChunkPos(new BlockPos(box.minX(), box.minY(), box.minY())), new ChunkPos(new BlockPos(box.maxX(), box.maxY(), box.maxZ()))).forEach(chunkPos -> serverWorld.getChunk(chunkPos.x, chunkPos.z).getBlockEntities().forEach((blockPos, blockEntity) -> {
|
||||
if (this.box.isInside(blockPos)) blockEntities.put(blockPos, blockEntity);
|
||||
}));
|
||||
return blockEntities;
|
||||
}
|
||||
|
||||
public BoundingBox getBox() {
|
||||
return box;
|
||||
}
|
||||
|
||||
public Map<String, Double> toVariableMap(Map<String, Double> variableMap) {
|
||||
variableMap = super.toVariableMap(variableMap);
|
||||
variableMap.put("originX", (double) this.box.minX());
|
||||
variableMap.put("originY", (double) this.box.minY());
|
||||
variableMap.put("originZ", (double) this.box.minZ());
|
||||
variableMap.put("width", (double) this.box.getLength().getX());
|
||||
variableMap.put("height", (double) this.box.getLength().getY());
|
||||
variableMap.put("length", (double) this.box.getLength().getZ());
|
||||
variableMap.put("depth", (double) this.virtualLocation.getDepth());
|
||||
return variableMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pocket getReferencedPocket() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void expand(int amount) {
|
||||
this.box.inflatedBy(amount);
|
||||
}
|
||||
|
||||
public static PocketBuilder<?, Pocket> builder() {
|
||||
return new PocketBuilder(AbstractPocketType.POCKET.get());
|
||||
}
|
||||
|
||||
protected void setBox(BoundingBox box) {
|
||||
this.box = box;
|
||||
}
|
||||
|
||||
// TODO: flesh this out a bit more, stuff like box() makes little sense in how it is implemented atm
|
||||
public static class PocketBuilder<P extends PocketBuilder<P, T>, T extends Pocket> extends AbstractPocketBuilder<P, T> {
|
||||
private final Map<ResourceLocation, PocketAddon.PocketBuilderAddon<?>> addons = new HashMap<>();
|
||||
|
||||
private Vec3i origin = new Vec3i(0, 0, 0);
|
||||
private Vec3i size = new Vec3i(0, 0, 0);
|
||||
private Vec3i expected = new Vec3i(0, 0, 0);
|
||||
private VirtualLocation virtualLocation;
|
||||
private int range = -1;
|
||||
|
||||
protected PocketBuilder(AbstractPocketType<T> type) {
|
||||
super(type);
|
||||
initAddons();
|
||||
}
|
||||
|
||||
public void initAddons() {
|
||||
|
||||
}
|
||||
|
||||
// TODO: actually utilize fromTag/ toTag methods + implement them
|
||||
public P fromNbt(CompoundTag nbt) {
|
||||
if (nbt.contains("addons", Tag.TAG_LIST)) {
|
||||
for (Tag addonTag : nbt.getList("addons", Tag.TAG_COMPOUND)) {
|
||||
PocketAddon.PocketBuilderAddon<?> addon = PocketAddon.deserializeBuilder((CompoundTag) addonTag);
|
||||
addons.put(addon.getId(), addon);
|
||||
}
|
||||
}
|
||||
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public CompoundTag toNbt(CompoundTag nbt) {
|
||||
ListTag addonsTag = new ListTag();
|
||||
addonsTag.addAll(addons.values().stream().map(addon -> addon.toNbt(new CompoundTag())).collect(Collectors.toList()));
|
||||
if (addonsTag.size() > 0) nbt.put("addons", addonsTag);
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
public boolean hasAddon(ResourceLocation id) {
|
||||
return addons.containsKey(id);
|
||||
}
|
||||
|
||||
protected <C extends PocketAddon.PocketBuilderAddon<?>> boolean addAddon(C addon) {
|
||||
if (addon.applicable(this)) {
|
||||
addon.addAddon(addons);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public <C extends PocketAddon.PocketBuilderAddon<?>> C getAddon(ResourceLocation id) {
|
||||
return (C) addons.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3i getExpectedSize() {
|
||||
return expected;
|
||||
}
|
||||
|
||||
public T build() {
|
||||
if (range < 1) throw new RuntimeException("Cannot create pocket with range < 1");
|
||||
|
||||
T instance = super.build();
|
||||
|
||||
instance.setRange(range);
|
||||
instance.setBox(BoundingBox.fromCorners(new Vec3i(origin.getX(), origin.getY(), origin.getZ()), new Vec3i(origin.getX() + size.getX(), origin.getY() + size.getY(), origin.getZ() + size.getZ())));
|
||||
instance.virtualLocation = virtualLocation;
|
||||
|
||||
addons.values().forEach(addon -> addon.apply(instance));
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public P offsetOrigin(Vec3i offset) {
|
||||
this.origin = new Vec3i(origin.getX() + offset.getX(), origin.getY() + offset.getY(), origin.getZ() + offset.getZ());
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public P expand(Vec3i expander) {
|
||||
this.size = new Vec3i(size.getX() + expander.getX(), size.getY() + expander.getY(), size.getZ() + expander.getZ());
|
||||
this.expected = new Vec3i(expected.getX() + expander.getX(), expected.getY() + expander.getY(), expected.getZ() + expander.getZ());
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public P expandExpected(Vec3i expander) {
|
||||
this.expected = new Vec3i(expected.getX() + expander.getX(), expected.getY() + expander.getY(), expected.getZ() + expander.getZ());
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public P virtualLocation(VirtualLocation virtualLocation) {
|
||||
this.virtualLocation = virtualLocation;
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public P range(int range) {
|
||||
this.range = range;
|
||||
return getSelf();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.world.item.DyeColor;
|
||||
|
||||
public enum PocketColor {
|
||||
WHITE(0, DyeColor.WHITE),
|
||||
ORANGE(1, DyeColor.ORANGE),
|
||||
MAGENTA(2, DyeColor.MAGENTA),
|
||||
LIGHT_BLUE(3, DyeColor.LIGHT_BLUE),
|
||||
YELLOW(4, DyeColor.YELLOW),
|
||||
LIME(5, DyeColor.LIME),
|
||||
PINK(6, DyeColor.PINK),
|
||||
GRAY(7, DyeColor.GRAY),
|
||||
LIGHT_GRAY(8, DyeColor.LIGHT_GRAY),
|
||||
CYAN(9, DyeColor.CYAN),
|
||||
PURPLE(10, DyeColor.PURPLE),
|
||||
BLUE(11, DyeColor.BLUE),
|
||||
BROWN(12, DyeColor.BROWN),
|
||||
GREEN(13, DyeColor.GREEN),
|
||||
RED(14, DyeColor.RED),
|
||||
BLACK(15, DyeColor.BLACK),
|
||||
NONE(16, null);
|
||||
|
||||
private final int id;
|
||||
private final DyeColor color;
|
||||
|
||||
public static Codec<PocketColor> CODEC = Codec.INT.xmap(PocketColor::from, PocketColor::getId);
|
||||
|
||||
PocketColor(int id, DyeColor color) {
|
||||
this.id = id;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public DyeColor getColor() {
|
||||
return this.color;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public static PocketColor from(DyeColor color) {
|
||||
for (PocketColor a : PocketColor.values()) {
|
||||
if (color == a.color) {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
return NONE;
|
||||
}
|
||||
|
||||
public static PocketColor from(int id) {
|
||||
for (PocketColor a : PocketColor.values()) {
|
||||
if (id == a.id) {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
return NONE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type;
|
||||
|
||||
import org.dimdev.dimdoors.world.pocket.type.addon.DyeableAddon;
|
||||
|
||||
public class PrivatePocket extends LazyGenerationPocket implements DyeableAddon.DyeablePocket {
|
||||
public static String KEY = "private_pocket";
|
||||
|
||||
public static PrivatePocketBuilder<?, PrivatePocket> builderPrivatePocket() {
|
||||
return new PrivatePocketBuilder<>(AbstractPocketType.PRIVATE_POCKET.get());
|
||||
}
|
||||
|
||||
public static class PrivatePocketBuilder<P extends PrivatePocketBuilder<P, T>, T extends PrivatePocket> extends PocketBuilder<P, T> implements DyeableAddon.DyeablePocketBuilder<P> {
|
||||
protected PrivatePocketBuilder(AbstractPocketType<T> type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initAddons() {
|
||||
super.initAddons();
|
||||
addAddon(new DyeableAddon.DyeableBuilderAddon());
|
||||
this.dyeColor(PocketColor.WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractPocketType<?> getType() {
|
||||
return AbstractPocketType.PRIVATE_POCKET.get();
|
||||
}
|
||||
|
||||
public static String getKEY() {
|
||||
return KEY;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type.addon;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AddonContainer<T extends ContainedAddon> implements PocketAddon {
|
||||
protected ResourceLocation id;
|
||||
protected List<T> addons = new ArrayList<>();
|
||||
|
||||
public AddonContainer() {
|
||||
}
|
||||
|
||||
public void setId(ResourceLocation id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void addAll(Collection<T> addons) {
|
||||
this.addons.addAll(addons);
|
||||
}
|
||||
|
||||
public void add(T addon) {
|
||||
this.addons.add(addon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketAddon fromNbt(CompoundTag nbt) {
|
||||
this.id = ResourceLocation.tryParse(nbt.getString("id"));
|
||||
|
||||
if (nbt.contains("addons", Tag.TAG_LIST)) {
|
||||
for (Tag addonTag : nbt.getList("addons", Tag.TAG_COMPOUND)) {
|
||||
addons.add((T) PocketAddon.deserialize((CompoundTag) addonTag));
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toNbt(CompoundTag nbt) {
|
||||
PocketAddon.super.toNbt(nbt);
|
||||
|
||||
ListTag addonsTag = new ListTag();
|
||||
for(T addon : addons) {
|
||||
addonsTag.add(addon.toNbt(new CompoundTag()));
|
||||
}
|
||||
nbt.put("addons", addonsTag);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type.addon;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
|
||||
public interface AddonProvider {
|
||||
<C extends PocketAddon> C getAddon(ResourceLocation id);
|
||||
|
||||
boolean hasAddon(ResourceLocation id);
|
||||
|
||||
<C extends PocketAddon> boolean addAddon(C addon);
|
||||
|
||||
default void ensureIsPocket() {
|
||||
if (! (this instanceof Pocket)) throw new UnsupportedOperationException("Cannot apply pocket addons to non Pocket Object.");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type.addon;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public interface AutoSyncedAddon extends PocketAddon {
|
||||
static <T extends AutoSyncedAddon> List<T> readAutoSyncedAddonList(FriendlyByteBuf buf) throws IOException {
|
||||
List<T> addons = new ArrayList<>();
|
||||
int addonCount = buf.readInt();
|
||||
try {
|
||||
for (int i = 0; i < addonCount; i++) {
|
||||
addons.add((T) ((AutoSyncedAddon) PocketAddon.REGISTRY.get(buf.readResourceLocation()).instance()).read(buf));
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
return addons;
|
||||
}
|
||||
|
||||
static FriendlyByteBuf writeAutoSyncedAddonList(FriendlyByteBuf buf, List<? extends AutoSyncedAddon> addons) throws IOException {
|
||||
buf.writeInt(addons.size());
|
||||
for (AutoSyncedAddon addon : addons) {
|
||||
buf.writeResourceLocation(addon.getType().identifier());
|
||||
addon.write(buf);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
// you can generally use FriendlyByteBuf#readCompoundTag for reading
|
||||
AutoSyncedAddon read(FriendlyByteBuf buf) throws IOException;
|
||||
|
||||
// you can generally use FriendlyByteBuf#writeCompoundTag for writing
|
||||
FriendlyByteBuf write(FriendlyByteBuf buf) throws IOException;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type.addon;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
abstract public class AutoSyncedAddonContainer<T extends ContainedAddon & AutoSyncedAddon> extends AddonContainer<T> implements AutoSyncedAddon {
|
||||
@Override
|
||||
public AutoSyncedAddon read(FriendlyByteBuf buf) throws IOException {
|
||||
id = ResourceLocation.tryParse(buf.readUtf());
|
||||
addons = AutoSyncedAddon.readAutoSyncedAddonList(buf);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FriendlyByteBuf write(FriendlyByteBuf buf) throws IOException {
|
||||
buf.writeUtf(id.toString());
|
||||
AutoSyncedAddon.writeAutoSyncedAddonList(buf, addons);
|
||||
return buf;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type.addon;
|
||||
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface ContainedAddon extends PocketAddon {
|
||||
ResourceLocation getContainerId();
|
||||
|
||||
@Override
|
||||
default void addAddon(Map<ResourceLocation, PocketAddon> addons) {
|
||||
throw new UnsupportedOperationException("ContainedEventListenerAddons cannot be attach to a Pocket directly");
|
||||
}
|
||||
|
||||
interface ContainedBuilderAddon<T extends ContainedAddon> extends PocketBuilderAddon<T> {
|
||||
ResourceLocation getContainerId();
|
||||
|
||||
AddonContainer<T> supplyContainer();
|
||||
|
||||
@Override
|
||||
default void apply(Pocket pocket) {
|
||||
AddonContainer<T> container;
|
||||
if (pocket.hasAddon(getContainerId())) {
|
||||
container = pocket.getAddon(getContainerId());
|
||||
} else {
|
||||
container = supplyContainer();
|
||||
pocket.addAddon(container);
|
||||
}
|
||||
container.add(buildAddon());
|
||||
}
|
||||
|
||||
T buildAddon();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type.addon;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.DyeColor;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.api.util.EntityUtils;
|
||||
import org.dimdev.dimdoors.block.AncientFabricBlock;
|
||||
import org.dimdev.dimdoors.block.FabricBlock;
|
||||
import org.dimdev.dimdoors.block.ModBlocks;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
import org.dimdev.dimdoors.world.pocket.type.PocketColor;
|
||||
import org.dimdev.dimdoors.world.pocket.type.PrivatePocket;
|
||||
|
||||
public class DyeableAddon implements PocketAddon {
|
||||
public static ResourceLocation ID = DimensionalDoors.id("dyeable");
|
||||
|
||||
private static final int BLOCKS_PAINTED_PER_DYE = 1000000;
|
||||
|
||||
protected PocketColor dyeColor = PocketColor.WHITE;
|
||||
private PocketColor nextDyeColor = PocketColor.NONE;
|
||||
private int count = 0;
|
||||
|
||||
private static int amountOfDyeRequiredToColor(Pocket pocket) {
|
||||
int outerVolume = pocket.getBox().getYSpan() * pocket.getBox().getZSpan() * pocket.getBox().getXSpan();
|
||||
int innerVolume = (pocket.getBox().getYSpan() - 5) * (pocket.getBox().getZSpan() - 5) * (pocket.getBox().getXSpan() - 5);
|
||||
|
||||
return Math.max((outerVolume - innerVolume) / BLOCKS_PAINTED_PER_DYE, 1);
|
||||
}
|
||||
|
||||
private void repaint(Pocket pocket, DyeColor dyeColor) {
|
||||
Level serverWorld = DimensionalDoors.getWorld(pocket.getWorld());
|
||||
BlockState innerWall = ModBlocks.fabricFromDye(dyeColor).getOrNull().defaultBlockState();;
|
||||
BlockState outerWall = ModBlocks.ancientFabricFromDye(dyeColor).getOrNull().defaultBlockState();;
|
||||
|
||||
BlockPos.betweenClosedStream(pocket.getBox()).forEach(pos -> {
|
||||
if (serverWorld.getBlockState(pos).getBlock() instanceof AncientFabricBlock) {
|
||||
serverWorld.setBlockAndUpdate(pos, outerWall);
|
||||
} else if (serverWorld.getBlockState(pos).getBlock() instanceof FabricBlock) {
|
||||
serverWorld.setBlockAndUpdate(pos, innerWall);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean addDye(Pocket pocket, Entity entity, DyeColor dyeColor) {
|
||||
PocketColor color = PocketColor.from(dyeColor);
|
||||
|
||||
int maxDye = amountOfDyeRequiredToColor(pocket);
|
||||
|
||||
if (this.dyeColor == color) {
|
||||
EntityUtils.chat(entity, Component.translatable("dimdoors.pockets.dyeAlreadyAbsorbed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.nextDyeColor != PocketColor.NONE && this.nextDyeColor == color) {
|
||||
if (this.count + 1 > maxDye) {
|
||||
repaint(pocket, dyeColor);
|
||||
this.dyeColor = color;
|
||||
this.nextDyeColor = PocketColor.NONE;
|
||||
this.count = 0;
|
||||
EntityUtils.chat(entity, Component.translatable("dimdoors.pocket.pocketHasBeenDyed", dyeColor));
|
||||
} else {
|
||||
this.count++;
|
||||
EntityUtils.chat(entity, Component.translatable("dimdoors.pocket.remainingNeededDyes", this.count, maxDye, color));
|
||||
}
|
||||
} else {
|
||||
this.nextDyeColor = color;
|
||||
this.count = 1;
|
||||
EntityUtils.chat(entity, Component.translatable("dimdoors.pocket.remainingNeededDyes", this.count, maxDye, color));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applicable(Pocket pocket) {
|
||||
return pocket instanceof PrivatePocket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketAddon fromNbt(CompoundTag nbt) {
|
||||
|
||||
this.dyeColor = PocketColor.from(nbt.getInt("dyeColor"));
|
||||
this.nextDyeColor = PocketColor.from(nbt.getInt("nextDyeColor"));
|
||||
this.count = nbt.getInt("count");
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toNbt(CompoundTag nbt) {
|
||||
PocketAddon.super.toNbt(nbt);
|
||||
|
||||
nbt.putInt("dyeColor", this.dyeColor.getId());
|
||||
nbt.putInt("nextDyeColor", this.nextDyeColor.getId());
|
||||
nbt.putInt("count", this.count);
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketAddonType<? extends PocketAddon> getType() {
|
||||
return PocketAddonType.DYEABLE_ADDON.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public interface DyeablePocketBuilder<T extends Pocket.PocketBuilder<T, ?>> extends PocketBuilderExtension<T> {
|
||||
default T dyeColor(PocketColor dyeColor) {
|
||||
|
||||
this.<DyeableBuilderAddon>getAddon(ID).dyeColor = dyeColor;
|
||||
|
||||
return getSelf();
|
||||
}
|
||||
}
|
||||
|
||||
public static class DyeableBuilderAddon implements PocketBuilderAddon<DyeableAddon> {
|
||||
|
||||
private PocketColor dyeColor = PocketColor.NONE;
|
||||
// TODO: add some Pocket#init so that we can have boolean shouldRepaintOnInit
|
||||
|
||||
@Override
|
||||
public void apply(Pocket pocket) {
|
||||
DyeableAddon addon = new DyeableAddon();
|
||||
addon.dyeColor = dyeColor;
|
||||
pocket.addAddon(addon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketBuilderAddon<DyeableAddon> fromNbt(CompoundTag nbt) {
|
||||
this.dyeColor = PocketColor.from(nbt.getInt("dye_color"));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toNbt(CompoundTag nbt) {
|
||||
PocketBuilderAddon.super.toNbt(nbt);
|
||||
|
||||
nbt.putInt("dye_color", dyeColor.getId());
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketAddonType<DyeableAddon> getType() {
|
||||
return PocketAddonType.DYEABLE_ADDON.get();
|
||||
}
|
||||
}
|
||||
|
||||
public interface DyeablePocket extends AddonProvider {
|
||||
default boolean addDye(Entity entity, DyeColor dyeColor) {
|
||||
ensureIsPocket();
|
||||
if (!this.hasAddon(ID)) {
|
||||
DyeableAddon addon = new DyeableAddon();
|
||||
this.addAddon(addon);
|
||||
return addon.addDye((Pocket) this, entity, dyeColor);
|
||||
}
|
||||
return this.<DyeableAddon>getAddon(ID).addDye((Pocket) this, entity, dyeColor);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type.addon;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import dev.architectury.registry.registries.Registrar;
|
||||
import dev.architectury.registry.registries.RegistrarManager;
|
||||
import dev.architectury.registry.registries.RegistrySupplier;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.SimpleRegistry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.REsourceLocation;
|
||||
|
||||
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
|
||||
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
import org.dimdev.dimdoors.world.pocket.type.addon.blockbreak.BlockBreakContainer;
|
||||
|
||||
public interface PocketAddon {
|
||||
Registrar<PocketAddonType<? extends PocketAddon>> REGISTRY = RegistrarManager.get(DimensionalDoors.MOD_ID).<PocketAddonType<? extends PocketAddon>>builder(DimensionalDoors.id("pocket_applicable_addon_type")).build();
|
||||
|
||||
static PocketAddon deserialize(CompoundTag nbt) {
|
||||
ResourceLocation id = ResourceLocation.tryParse(nbt.getString("type")); // TODO: NONE PocketAddon type;
|
||||
return REGISTRY.get(id).fromNbt(nbt);
|
||||
}
|
||||
|
||||
static PocketBuilderAddon<?> deserializeBuilder(CompoundTag nbt) {
|
||||
ResourceLocation id = ResourceLocation.tryParse(nbt.getString("type")); // TODO: NONE PocketAddon type;
|
||||
return REGISTRY.get(id).builderAddonInstance().fromNbt(nbt);
|
||||
}
|
||||
|
||||
static CompoundTag serialize(PocketAddon addon) {
|
||||
return addon.toNbt(new CompoundTag());
|
||||
}
|
||||
|
||||
|
||||
default boolean applicable(Pocket pocket) {
|
||||
return true;
|
||||
}
|
||||
|
||||
PocketAddon fromNbt(CompoundTag nbt);
|
||||
|
||||
default CompoundTag toNbt(CompoundTag nbt) {
|
||||
return this.getType().toNbt(nbt);
|
||||
}
|
||||
|
||||
PocketAddonType<? extends PocketAddon> getType();
|
||||
|
||||
ResourceLocation getId();
|
||||
|
||||
default void addAddon(Map<ResourceLocation, PocketAddon> addons) {
|
||||
addons.put(getId(), this);
|
||||
}
|
||||
|
||||
interface PocketBuilderExtension<T extends Pocket.PocketBuilder<T, ?>> {
|
||||
public <C extends PocketBuilderAddon<?>> C getAddon(ResourceLocation id);
|
||||
|
||||
T getSelf();
|
||||
}
|
||||
|
||||
interface PocketBuilderAddon<T extends PocketAddon> {
|
||||
default boolean applicable(Pocket.PocketBuilder<?, ?> builder) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// makes it possible for addons themselves to control how they are added
|
||||
default void addAddon(Map<ResourceLocation, PocketBuilderAddon<?>> addons) {
|
||||
addons.put(getId(), this);
|
||||
}
|
||||
|
||||
void apply(Pocket pocket);
|
||||
|
||||
ResourceLocation getId();
|
||||
|
||||
PocketBuilderAddon<T> fromNbt(CompoundTag nbt);
|
||||
|
||||
default CompoundTag toNbt(CompoundTag nbt) {
|
||||
return this.getType().toNbt(nbt);
|
||||
}
|
||||
|
||||
PocketAddonType<T> getType();
|
||||
}
|
||||
|
||||
interface PocketAddonType<T extends PocketAddon> {
|
||||
RegistrySupplier<PocketAddonType<DyeableAddon>> DYEABLE_ADDON = register(DyeableAddon.ID, DyeableAddon::new, DyeableAddon.DyeableBuilderAddon::new);
|
||||
RegistrySupplier<PocketAddonType<PreventBlockModificationAddon>> PREVENT_BLOCK_MODIFICATION_ADDON = register(PreventBlockModificationAddon.ID, PreventBlockModificationAddon::new, PreventBlockModificationAddon.PreventBlockModificationBuilderAddon::new);
|
||||
RegistrySupplier<PocketAddonType<BlockBreakContainer>> BLOCK_BREAK_CONTAINER = register(BlockBreakContainer.ID, BlockBreakContainer::new, null);
|
||||
RegistrySupplier<PocketAddonType<SkyAddon>> SKY_ADDON = register(SkyAddon.ID, SkyAddon::new, SkyAddon.SkyBuilderAddon::new);
|
||||
|
||||
T fromNbt(CompoundTag nbt);
|
||||
|
||||
CompoundTag toNbt(CompoundTag nbt);
|
||||
|
||||
T instance();
|
||||
|
||||
PocketBuilderAddon<T> builderAddonInstance();
|
||||
|
||||
ResourceLocation identifier();
|
||||
|
||||
static void register() {
|
||||
DimensionalDoors.apiSubscribers.forEach(d -> d.registerPocketAddonTypes(REGISTRY));
|
||||
}
|
||||
|
||||
static <U extends PocketAddon> RegistrySupplier<PocketAddonType<U>> register(ResourceLocation id, Supplier<U> factory, Supplier<PocketBuilderAddon<U>> addonSupplier) {
|
||||
return REGISTRY.register(id, () -> new PocketAddonType<U>() {
|
||||
@Override
|
||||
public U fromNbt(CompoundTag nbt) {
|
||||
return (U) factory.get().fromNbt(nbt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toNbt(CompoundTag nbt) {
|
||||
nbt.putString("type", id.toString());
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public U instance() {
|
||||
return factory.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketBuilderAddon<U> builderAddonInstance() {
|
||||
if (addonSupplier == null) return null;
|
||||
return addonSupplier.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation identifier() {
|
||||
return id;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type.addon;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
|
||||
import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
|
||||
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.api.event.UseItemOnBlockCallback;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
|
||||
public class PreventBlockModificationAddon implements AutoSyncedAddon, AttackBlockCallback, PlayerBlockBreakEvents.Before, UseItemOnBlockCallback {
|
||||
public static ResourceLocation ID = DimensionalDoors.id("prevent_block_modification");
|
||||
|
||||
//AttackBlockCallback
|
||||
@Override
|
||||
public ActionResult interact(PlayerEntity player, World world, Hand hand, BlockPos pos, Direction direction) {
|
||||
if (player.isCreative()) return ActionResult.PASS;
|
||||
return ActionResult.FAIL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean beforeBlockBreak(World world, PlayerEntity player, BlockPos pos, BlockState state, BlockEntity blockEntity) {
|
||||
if (player.isCreative()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult useItemOnBlock(PlayerEntity player, World world, Hand hand, BlockHitResult hitResult) {
|
||||
if (player.isCreative()) return ActionResult.PASS;
|
||||
if (player.getStackInHand(hand).getItem() instanceof BlockItem) {
|
||||
BlockPos blockPos = hitResult.getBlockPos();
|
||||
BlockState blockState = world.getBlockState(blockPos);
|
||||
ActionResult result = blockState.onUse(world, player, hand, hitResult);
|
||||
if (result.isAccepted()) return result;
|
||||
|
||||
return ActionResult.FAIL;
|
||||
}
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AutoSyncedAddon read(PacketByteBuf buf) throws IOException {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketByteBuf write(PacketByteBuf buf) throws IOException {
|
||||
return buf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketAddon fromNbt(NbtCompound nbt) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketAddonType<? extends PocketAddon> getType() {
|
||||
return PocketAddonType.PREVENT_BLOCK_MODIFICATION_ADDON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public static class PreventBlockModificationBuilderAddon implements PocketBuilderAddon<PreventBlockModificationAddon> {
|
||||
|
||||
@Override
|
||||
public void apply(Pocket pocket) {
|
||||
pocket.addAddon(new PreventBlockModificationAddon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketBuilderAddon<PreventBlockModificationAddon> fromNbt(NbtCompound nbt) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketAddonType<PreventBlockModificationAddon> getType() {
|
||||
return PocketAddonType.PREVENT_BLOCK_MODIFICATION_ADDON;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type.addon;
|
||||
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SkyAddon implements AutoSyncedAddon {
|
||||
public static ResourceLocation ID = DimensionalDoors.id("sky");
|
||||
|
||||
private ResourceKey<Level> world;
|
||||
|
||||
public boolean setWorld(ResourceKey<Level> world) {
|
||||
this.world = world;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketAddon fromNbt(CompoundTag nbt) {
|
||||
this.world = ResourceKey.create(Registries.DIMENSION, ResourceLocation.tryParse(nbt.getString("world")));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toNbt(CompoundTag nbt) {
|
||||
AutoSyncedAddon.super.toNbt(nbt);
|
||||
|
||||
nbt.putString("world", this.world.location().toString());
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketAddonType<? extends PocketAddon> getType() {
|
||||
return PocketAddonType.SKY_ADDON.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public ResourceKey<Level> getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AutoSyncedAddon read(FriendlyByteBuf buf) throws IOException {
|
||||
this.world = ResourceKey.create(Registries.DIMENSION, buf.readResourceLocation());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FriendlyByteBuf write(FriendlyByteBuf buf) throws IOException {
|
||||
buf.writeResourceLocation(world.location());
|
||||
return buf;
|
||||
}
|
||||
|
||||
public interface SkyPocketBuilder<T extends Pocket.PocketBuilder<T, ?>> extends PocketBuilderExtension<T> {
|
||||
default T world(ResourceKey<Level> world) {
|
||||
|
||||
this.<SkyBuilderAddon>getAddon(ID).world = world;
|
||||
|
||||
return getSelf();
|
||||
}
|
||||
}
|
||||
|
||||
public static class SkyBuilderAddon implements PocketBuilderAddon<SkyAddon> {
|
||||
|
||||
private ResourceKey<Level> world = Level.OVERWORLD;
|
||||
|
||||
@Override
|
||||
public void apply(Pocket pocket) {
|
||||
SkyAddon addon = new SkyAddon();
|
||||
addon.world = world;
|
||||
pocket.addAddon(addon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketBuilderAddon<SkyAddon> fromNbt(CompoundTag nbt) {
|
||||
this.world = ResourceKey.create(Registries.DIMENSION, ResourceLocation.tryParse(nbt.getString("world")));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toNbt(CompoundTag nbt) {
|
||||
PocketBuilderAddon.super.toNbt(nbt);
|
||||
|
||||
nbt.putString("world", world.location().toString());
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketAddonType<SkyAddon> getType() {
|
||||
return PocketAddonType.SKY_ADDON.get();
|
||||
}
|
||||
}
|
||||
|
||||
public interface SkyPocket extends AddonProvider {
|
||||
default boolean sky(ResourceKey<Level> world) {
|
||||
ensureIsPocket();
|
||||
if (!this.hasAddon(ID)) {
|
||||
SkyAddon addon = new SkyAddon();
|
||||
this.addAddon(addon);
|
||||
return addon.setWorld(world);
|
||||
}
|
||||
return this.<SkyAddon>getAddon(ID).setWorld(world);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type.addon.blockbreak;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.dimdev.dimdoors.DimensionalDoors;
|
||||
import org.dimdev.dimdoors.world.pocket.type.addon.AutoSyncedAddonContainer;
|
||||
import org.dimdev.dimdoors.world.pocket.type.addon.PocketAddon;
|
||||
|
||||
// TODO
|
||||
public class BlockBreakContainer extends AutoSyncedAddonContainer<TryBlockBreakEventAddon> {
|
||||
public static ResourceLocation ID = DimensionalDoors.id("block_break_container");
|
||||
|
||||
@Override
|
||||
public PocketAddonType<? extends PocketAddon> getType() {
|
||||
return PocketAddonType.BLOCK_BREAK_CONTAINER.get();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type.addon.blockbreak;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.dimdev.dimdoors.world.pocket.type.addon.AutoSyncedAddon;
|
||||
import org.dimdev.dimdoors.world.pocket.type.addon.ContainedAddon;
|
||||
import org.dimdev.dimdoors.world.pocket.type.addon.PocketAddon;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
// TODO
|
||||
public class BlockBreakRegexBlacklistAddon implements AutoSyncedAddon, ContainedAddon { //TODO
|
||||
@Override
|
||||
public AutoSyncedAddon read(FriendlyByteBuf buf) throws IOException {
|
||||
this.fromNbt(buf.readNbt());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FriendlyByteBuf write(FriendlyByteBuf buf) throws IOException {
|
||||
buf.writeNbt(this.toNbt(new CompoundTag()));
|
||||
return buf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getContainerId() {
|
||||
return BlockBreakContainer.ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketAddon fromNbt(CompoundTag nbt) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PocketAddonType<? extends PocketAddon> getType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package org.dimdev.dimdoors.world.pocket.type.addon.blockbreak;
|
||||
|
||||
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
|
||||
import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
|
||||
|
||||
import org.dimdev.dimdoors.world.pocket.type.addon.AutoSyncedAddon;
|
||||
import org.dimdev.dimdoors.world.pocket.type.addon.ContainedAddon;
|
||||
|
||||
// TODO
|
||||
public interface TryBlockBreakEventAddon extends AttackBlockCallback, PlayerBlockBreakEvents.Before, ContainedAddon, AutoSyncedAddon {
|
||||
}
|
|
@ -1,35 +1,35 @@
|
|||
accessWidener v1 named
|
||||
|
||||
# Because its package private
|
||||
accessible class net/minecraft/client/render/RenderLayer$MultiPhase
|
||||
accessible class net/minecraft/client/render/RenderLayer$MultiPhaseParameters
|
||||
accessible class net/minecraft/client/render/RenderPhase$ShaderProgram
|
||||
accessible class net/minecraft/client/render/RenderPhase$Textures
|
||||
accessible method net/minecraft/entity/Entity setRotation (FF)V
|
||||
#accessible class net/minecraft/client/render/RenderLayer$MultiPhase
|
||||
#accessible class net/minecraft/client/render/RenderLayer$MultiPhaseParameters
|
||||
#accessible class net/minecraft/client/render/RenderPhase$ShaderProgram
|
||||
#accessible class net/minecraft/client/render/RenderPhase$Textures
|
||||
#accessible method net/minecraft/entity/Entity setRotation (FF)V
|
||||
|
||||
# for MutableBlockEntityType
|
||||
extendable class net/minecraft/block/entity/BlockEntityType$BlockEntityFactory
|
||||
#extendable class net/minecraft/block/entity/BlockEntityType$BlockEntityFactory
|
||||
|
||||
# for HackyFluidState
|
||||
extendable class net/minecraft/world/level/material/FluidState
|
||||
accessible field net/minecraft/world/level/block/state/StateHolder propertiesCodec Lcom/mojang/serialization/MapCodec;#Lnet/minecraft/state/State;codec:Lcom/mojang/serialization/MapCodec;
|
||||
|
||||
# for lazy pocket gen/ getting all currently loaded chunks
|
||||
accessible method net/minecraft/server/world/ThreadedAnvilChunkStorage entryIterator ()Ljava/lang/Iterable;
|
||||
#accessible method net/minecraft/server/world/ThreadedAnvilChunkStorage entryIterator ()Ljava/lang/Iterable;
|
||||
|
||||
accessible method net/minecraft/client/render/WorldRenderer renderEndSky (Lnet/minecraft/client/util/math/MatrixStack;)V
|
||||
#accessible method net/minecraft/client/render/WorldRenderer renderEndSky (Lnet/minecraft/client/util/math/MatrixStack;)V
|
||||
|
||||
#accessible method net/minecraft/world/biome/Biome getCategory ()Lnet/minecraft/world/biome/Biome$Category;
|
||||
|
||||
accessible field net/minecraft/block/Block LOGGER Lorg/slf4j/Logger;
|
||||
#accessible field net/minecraft/block/Block LOGGER Lorg/slf4j/Logger;
|
||||
|
||||
accessible method net/minecraft/world/gen/feature/OrePlacedFeatures modifiersWithCount (ILnet/minecraft/world/gen/placementmodifier/PlacementModifier;)Ljava/util/List;
|
||||
#accessible method net/minecraft/world/gen/feature/OrePlacedFeatures modifiersWithCount (ILnet/minecraft/world/gen/placementmodifier/PlacementModifier;)Ljava/util/List;
|
||||
|
||||
accessible class net/minecraft/data/models/BlockModelGenerators$BlockFamilyProvider
|
||||
#accessible class net/minecraft/data/models/BlockModelGenerators$BlockFamilyProvider
|
||||
|
||||
accessible method net/minecraft/world/level/block/entity/BlockEntity saveMetadata (Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/nbt/CompoundTag;
|
||||
#accessible method net/minecraft/world/level/block/entity/BlockEntity saveMetadata (Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/nbt/CompoundTag;
|
||||
|
||||
accessible method net/minecraft/commands/arguments/blocks/BlockStateParser parse (Z)Lnet/minecraft/commands/arguments/blocks/BlockStateParser;
|
||||
#accessible method net/minecraft/commands/arguments/blocks/BlockStateParser parse (Z)Lnet/minecraft/commands/arguments/blocks/BlockStateParser;
|
||||
|
||||
accessible method net/minecraft/world/item/crafting/ShapedRecipe shrink ([Ljava/lang/String;)[Ljava/lang/String;
|
||||
accessible method net/minecraft/world/item/crafting/ShapedRecipe keyFromJson (Lcom/google/gson/JsonObject;)Ljava/util/Map;
|
||||
|
|
Loading…
Reference in a new issue