diff --git a/src/datagen/java/org/dimdev/dimdoors/datagen/AdvancementTab.java b/src/datagen/java/org/dimdev/dimdoors/datagen/AdvancementTab.java index db6d1b4a..1ca6c4e4 100644 --- a/src/datagen/java/org/dimdev/dimdoors/datagen/AdvancementTab.java +++ b/src/datagen/java/org/dimdev/dimdoors/datagen/AdvancementTab.java @@ -48,21 +48,21 @@ public class AdvancementTab implements Consumer> { .criterion("inventory_changed", InventoryChangedCriterion.Conditions.items(Items.ENDER_PEARL)) .build(advancementConsumer, "dimdoors:dimdoors/root"); - Advancement.Task.create() - .display(makeDisplay(ModItems.IRON_DIMENSIONAL_DOOR, "public_pocket")) - .criterion("changed_dimension", ChangedDimensionCriterion.Conditions.to(ModDimensions.PUBLIC)) - .parent(root) - .build(advancementConsumer, "dimdoors:dimdoors/public_pocket"); - Advancement.Task.create() - .display(makeDisplay(ModItems.QUARTZ_DIMENSIONAL_DOOR, "private_pocket")) - .criterion("changed_dimension", ChangedDimensionCriterion.Conditions.to(ModDimensions.PERSONAL)) - .parent(root) - .build(advancementConsumer, "dimdoors:dimdoors/private_pocket"); - Advancement.Task.create() - .display(makeDisplay(ModItems.GOLD_DIMENSIONAL_DOOR, "dungeon")) - .criterion("changed_dimension", ChangedDimensionCriterion.Conditions.to(ModDimensions.DUNGEON)) - .parent(root) - .build(advancementConsumer, "dimdoors:dimdoors/dungeon"); +// Advancement.Task.create() +// .display(makeDisplay(ModItems.IRON_DIMENSIONAL_DOOR, "public_pocket")) +// .criterion("changed_dimension", ChangedDimensionCriterion.Conditions.to(ModDimensions.PUBLIC)) +// .parent(root) +// .build(advancementConsumer, "dimdoors:dimdoors/public_pocket"); +// Advancement.Task.create() +// .display(makeDisplay(ModItems.QUARTZ_DIMENSIONAL_DOOR, "private_pocket")) +// .criterion("changed_dimension", ChangedDimensionCriterion.Conditions.to(ModDimensions.PERSONAL)) +// .parent(root) +// .build(advancementConsumer, "dimdoors:dimdoors/private_pocket"); +// Advancement.Task.create() +// .display(makeDisplay(ModItems.GOLD_DIMENSIONAL_DOOR, "dungeon")) +// .criterion("changed_dimension", ChangedDimensionCriterion.Conditions.to(ModDimensions.DUNGEON)) +// .parent(root) +// .build(advancementConsumer, "dimdoors:dimdoors/dungeon"); Advancement limbo = Advancement.Task.create() .display(makeDisplay(ModItems.UNRAVELLED_FABRIC, "limbo")) .criterion("changed_dimension", ChangedDimensionCriterion.Conditions.to(ModDimensions.LIMBO)) diff --git a/src/main/java/org/dimdev/dimdoors/DimensionalDoorsClientInitializer.java b/src/main/java/org/dimdev/dimdoors/DimensionalDoorsClientInitializer.java index 64c198a6..789529e5 100644 --- a/src/main/java/org/dimdev/dimdoors/DimensionalDoorsClientInitializer.java +++ b/src/main/java/org/dimdev/dimdoors/DimensionalDoorsClientInitializer.java @@ -6,6 +6,7 @@ import org.dimdev.dimdoors.block.entity.ModBlockEntityTypes; import org.dimdev.dimdoors.client.ModSkyRendering; import org.dimdev.dimdoors.entity.ModEntityTypes; import org.dimdev.dimdoors.entity.MonolithEntity; +import org.dimdev.dimdoors.entity.ai.MonolithAggroGoal; import org.dimdev.dimdoors.fluid.ModFluids; import org.dimdev.dimdoors.network.ExtendedClientPlayNetworkHandler; import org.dimdev.dimdoors.particle.ModParticleTypes; @@ -26,7 +27,7 @@ public class DimensionalDoorsClientInitializer implements ClientModInitializer { ModBlocks.initClient(); ModParticleTypes.initClient(); - ClientPlayNetworking.registerGlobalReceiver(DimensionalDoorsInitializer.MONOLITH_PARTICLE_PACKET, (client, networkHandler, buf, sender) -> MonolithEntity.spawnParticles(buf, client)); + ClientPlayNetworking.registerGlobalReceiver(MonolithAggroGoal.MONOLITH_PARTICLE_PACKET, (client, networkHandler, buf, sender) -> MonolithEntity.spawnParticles(buf, client)); registerListeners(); } diff --git a/src/main/java/org/dimdev/dimdoors/DimensionalDoorsInitializer.java b/src/main/java/org/dimdev/dimdoors/DimensionalDoorsInitializer.java index 6869d24d..8d9e0619 100644 --- a/src/main/java/org/dimdev/dimdoors/DimensionalDoorsInitializer.java +++ b/src/main/java/org/dimdev/dimdoors/DimensionalDoorsInitializer.java @@ -1,20 +1,9 @@ package org.dimdev.dimdoors; +import java.nio.file.Path; + import me.sargunvohra.mcmods.autoconfig1u.AutoConfig; import me.sargunvohra.mcmods.autoconfig1u.ConfigHolder; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; -import net.fabricmc.fabric.api.event.player.AttackBlockCallback; -import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents; -import net.fabricmc.fabric.api.event.player.UseBlockCallback; -import net.fabricmc.fabric.api.event.player.UseItemCallback; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; - -import me.sargunvohra.mcmods.autoconfig1u.serializer.JanksonConfigSerializer; - -import net.fabricmc.fabric.api.resource.ResourcePackActivationType; -import net.fabricmc.loader.api.FabricLoader; -import net.fabricmc.loader.api.ModContainer; -import net.minecraft.resource.ResourceType; import org.dimdev.dimdoors.block.ModBlocks; import org.dimdev.dimdoors.block.entity.ModBlockEntityTypes; import org.dimdev.dimdoors.command.ModCommands; @@ -25,16 +14,21 @@ import org.dimdev.dimdoors.fluid.ModFluids; import org.dimdev.dimdoors.item.ModItems; import org.dimdev.dimdoors.listener.AttackBlockCallbackListener; import org.dimdev.dimdoors.listener.ChunkLoadListener; -import org.dimdev.dimdoors.listener.pocket.*; +import org.dimdev.dimdoors.listener.pocket.PlayerBlockBreakEventBeforeListener; +import org.dimdev.dimdoors.listener.pocket.PocketAttackBlockCallbackListener; +import org.dimdev.dimdoors.listener.pocket.UseBlockCallbackListener; +import org.dimdev.dimdoors.listener.pocket.UseItemCallbackListener; +import org.dimdev.dimdoors.listener.pocket.UseItemOnBlockCallbackListener; import org.dimdev.dimdoors.network.ExtendedServerPlayNetworkHandler; import org.dimdev.dimdoors.particle.ModParticleTypes; import org.dimdev.dimdoors.pockets.PocketLoader; import org.dimdev.dimdoors.pockets.generator.PocketGenerator; -import org.dimdev.dimdoors.pockets.virtual.VirtualSingularPocket; import org.dimdev.dimdoors.pockets.modifier.Modifier; +import org.dimdev.dimdoors.pockets.virtual.VirtualSingularPocket; import org.dimdev.dimdoors.rift.targets.Targets; import org.dimdev.dimdoors.rift.targets.VirtualTarget; import org.dimdev.dimdoors.sound.ModSoundEvents; +import org.dimdev.dimdoors.util.SubRootJanksonConfigSerializer; import org.dimdev.dimdoors.world.ModBiomes; import org.dimdev.dimdoors.world.ModDimensions; import org.dimdev.dimdoors.world.feature.ModFeatures; @@ -42,6 +36,7 @@ import org.dimdev.dimdoors.world.pocket.type.AbstractPocket; import org.dimdev.dimdoors.world.pocket.type.addon.PocketAddon; import org.jetbrains.annotations.NotNull; +import net.minecraft.resource.ResourceType; import net.minecraft.server.MinecraftServer; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Identifier; @@ -49,14 +44,23 @@ import net.minecraft.util.registry.RegistryKey; import net.minecraft.world.World; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.player.AttackBlockCallback; +import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents; +import net.fabricmc.fabric.api.event.player.UseBlockCallback; +import net.fabricmc.fabric.api.event.player.UseItemCallback; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.fabric.api.resource.ResourceManagerHelper; +import net.fabricmc.fabric.api.resource.ResourcePackActivationType; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; public class DimensionalDoorsInitializer implements ModInitializer { - public static final Identifier MONOLITH_PARTICLE_PACKET = new Identifier("dimdoors", "monolith_particle_packet"); - public static final ConfigHolder CONFIG_MANAGER = AutoConfig.register(ModConfig.class, JanksonConfigSerializer::new); + public static final ConfigHolder CONFIG_MANAGER = AutoConfig.register(ModConfig.class, SubRootJanksonConfigSerializer::new); private static MinecraftServer server; private static ModContainer dimDoorsMod; + private static Path configRoot; @NotNull public static MinecraftServer getServer() { @@ -78,10 +82,15 @@ public class DimensionalDoorsInitializer implements ModInitializer { return dimDoorsMod; } + public static Path getConfigRoot() { + return configRoot; + } + @Override public void onInitialize() { dimDoorsMod = FabricLoader.getInstance().getModContainer("dimdoors").orElseThrow(RuntimeException::new); - ServerLifecycleEvents.SERVER_STARTING.register((minecraftServer) -> { + configRoot = FabricLoader.getInstance().getConfigDir().resolve("dimdoors"); + ServerLifecycleEvents.SERVER_STARTING.register((minecraftServer) -> { server = minecraftServer; }); diff --git a/src/main/java/org/dimdev/dimdoors/block/ModBlocks.java b/src/main/java/org/dimdev/dimdoors/block/ModBlocks.java index 3073e12f..50dbe064 100644 --- a/src/main/java/org/dimdev/dimdoors/block/ModBlocks.java +++ b/src/main/java/org/dimdev/dimdoors/block/ModBlocks.java @@ -6,6 +6,7 @@ import java.util.Map; import com.google.common.collect.Maps; import net.minecraft.block.Block; +import net.minecraft.block.Blocks; import net.minecraft.block.MapColor; import net.minecraft.block.Material; import net.minecraft.client.render.RenderLayer; @@ -25,11 +26,11 @@ public final class ModBlocks { public static final Block GOLD_DOOR = register("dimdoors:gold_door", new DoorBlock(FabricBlockSettings.of(Material.METAL, MapColor.GOLD).strength(5.0F).breakByHand(false).breakByTool(FabricToolTags.PICKAXES).nonOpaque())); public static final Block QUARTZ_DOOR = register("dimdoors:quartz_door", new DoorBlock(FabricBlockSettings.of(Material.STONE, MapColor.OFF_WHITE).strength(5.0F).breakByHand(false).breakByTool(FabricToolTags.PICKAXES).nonOpaque())); - public static final Block OAK_DIMENSIONAL_DOOR = register("dimdoors:oak_dimensional_door", new DimensionalDoorBlock(FabricBlockSettings.of(Material.WOOD, MapColor.OAK_TAN).strength(3.0F).breakByTool(FabricToolTags.AXES).breakByHand(true).nonOpaque().luminance(state -> 10))); - public static final Block IRON_DIMENSIONAL_DOOR = register("dimdoors:iron_dimensional_door", new DimensionalDoorBlock(FabricBlockSettings.of(Material.METAL, MapColor.IRON_GRAY).strength(5.0F).breakByHand(false).breakByTool(FabricToolTags.PICKAXES).nonOpaque().luminance(state -> 10))); - public static final Block GOLD_DIMENSIONAL_DOOR = register("dimdoors:gold_dimensional_door", new DimensionalDoorBlock(FabricBlockSettings.of(Material.METAL, MapColor.GOLD).strength(5.0F).breakByHand(false).breakByTool(FabricToolTags.PICKAXES).nonOpaque().luminance(state -> 10))); - public static final Block QUARTZ_DIMENSIONAL_DOOR = register("dimdoors:quartz_dimensional_door", new DimensionalDoorBlock(FabricBlockSettings.of(Material.STONE, MapColor.OFF_WHITE).strength(5.0F).breakByHand(false).breakByTool(FabricToolTags.PICKAXES).nonOpaque().luminance(state -> 10))); - public static final Block OAK_DIMENSIONAL_TRAPDOOR = register("dimdoors:wood_dimensional_trapdoor", new DimensionalTrapdoorBlock(FabricBlockSettings.of(Material.WOOD, MapColor.OAK_TAN).strength(3.0F).breakByTool(FabricToolTags.AXES).breakByHand(true).nonOpaque())); + public static final Block OAK_DIMENSIONAL_DOOR = register("dimdoors:oak_dimensional_door", new DimensionalDoorBlock(FabricBlockSettings.copyOf(Blocks.OAK_DOOR).luminance(state -> 10))); + public static final Block IRON_DIMENSIONAL_DOOR = register("dimdoors:iron_dimensional_door", new DimensionalDoorBlock(FabricBlockSettings.copyOf(Blocks.IRON_DOOR).luminance(state -> 10))); + public static final Block GOLD_DIMENSIONAL_DOOR = register("dimdoors:gold_dimensional_door", new DimensionalDoorBlock(FabricBlockSettings.copyOf(GOLD_DOOR).luminance(state -> 10))); + public static final Block QUARTZ_DIMENSIONAL_DOOR = register("dimdoors:quartz_dimensional_door", new DimensionalDoorBlock(FabricBlockSettings.copy(QUARTZ_DOOR).luminance(state -> 10))); + public static final Block OAK_DIMENSIONAL_TRAPDOOR = register("dimdoors:wood_dimensional_trapdoor", new DimensionalTrapdoorBlock(FabricBlockSettings.copyOf(Blocks.OAK_TRAPDOOR).luminance(state -> 10))); public static final Block DIMENSIONAL_PORTAL = register("dimdoors:dimensional_portal", new DimensionalPortalBlock(FabricBlockSettings.of(Material.AIR).collidable(false).strength(-1.0F, 3600000.0F).nonOpaque().dropsNothing().luminance(10))); public static final Block DETACHED_RIFT = register("dimdoors:detached_rift", new DetachedRiftBlock(FabricBlockSettings.of(Material.AIR).strength(-1.0F, 3600000.0F).noCollision().nonOpaque())); diff --git a/src/main/java/org/dimdev/dimdoors/block/door/RiftDataList.java b/src/main/java/org/dimdev/dimdoors/block/door/RiftDataList.java new file mode 100644 index 00000000..cfbabaab --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/block/door/RiftDataList.java @@ -0,0 +1,64 @@ +package org.dimdev.dimdoors.block.door; + +import java.util.LinkedList; +import java.util.Optional; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.serialization.JsonOps; +import org.dimdev.dimdoors.block.door.condition.Condition; +import org.dimdev.dimdoors.block.entity.EntranceRiftBlockEntity; +import org.dimdev.dimdoors.rift.registry.LinkProperties; +import org.dimdev.dimdoors.rift.targets.VirtualTarget; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.util.Pair; + +public class RiftDataList { + private final LinkedList> riftDataConditions; + + public static RiftDataList fromJson(JsonArray jsonArray) { + LinkedList> riftDataConditions = new LinkedList<>(); + for (JsonElement json : jsonArray) { + JsonObject jsonObject = json.getAsJsonObject(); + OptRiftData riftData = OptRiftData.fromJson(jsonObject.getAsJsonObject("data")); + Condition condition = Condition.fromJson(jsonObject.getAsJsonObject("data")); + } + return new RiftDataList(riftDataConditions); + } + + public RiftDataList(LinkedList> riftDataConditions) { + this.riftDataConditions = riftDataConditions; + } + + public OptRiftData getRiftData(EntranceRiftBlockEntity rift) { + return riftDataConditions.stream().filter(pair -> pair.getRight().matches(rift)).findFirst().orElseThrow(() -> new RuntimeException("Could not find any matching rift data")).getLeft(); + } + + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + public static class OptRiftData { + private final Optional destination; + private final Optional linkProperties; + + public static OptRiftData fromJson(JsonObject json) { + Optional destination = Optional.ofNullable(json.get("destination")).map(JsonElement::getAsJsonObject).map(j -> JsonOps.INSTANCE.convertTo(NbtOps.INSTANCE, j)).map(CompoundTag.class::cast).map(VirtualTarget::fromTag); + Optional linkProperties = Optional.ofNullable(json.get("destination")).map(JsonElement::getAsJsonObject).map(j -> JsonOps.INSTANCE.convertTo(NbtOps.INSTANCE, j)).map(CompoundTag.class::cast).map(LinkProperties::fromTag); + return new OptRiftData(destination, linkProperties); + } + + public OptRiftData(Optional destination, Optional linkProperties) { + this.destination = destination; + this.linkProperties = linkProperties; + } + + public Optional getProperties() { + return linkProperties; + } + + public Optional getDestination() { + return destination; + } + } +} diff --git a/src/main/java/org/dimdev/dimdoors/block/door/UnbakedDoorData.java b/src/main/java/org/dimdev/dimdoors/block/door/UnbakedDoorData.java new file mode 100644 index 00000000..a490ee72 --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/block/door/UnbakedDoorData.java @@ -0,0 +1,138 @@ +package org.dimdev.dimdoors.block.door; + +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.OptionalInt; +import java.util.function.Consumer; + +import com.google.common.collect.ImmutableMap; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.dimdev.dimdoors.block.DimensionalDoorBlock; +import org.dimdev.dimdoors.block.entity.EntranceRiftBlockEntity; +import org.dimdev.dimdoors.item.DimensionalDoorItem; +import org.dimdev.dimdoors.item.ItemExtensions; +import org.dimdev.dimdoors.item.ModItems; +import org.dimdev.dimdoors.util.OptionalBool; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.util.Identifier; +import net.minecraft.util.Pair; +import net.minecraft.util.Rarity; +import net.minecraft.util.Util; +import net.minecraft.util.registry.Registry; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +public final class UnbakedDoorData implements AutoCloseable { + private String id; + private UnbakedItemSettings itemSettings; + private UnbakedBlockSettings blockSettings; + private RiftDataList riftDataList; + private boolean closed = false; + + public static UnbakedDoorData fromJson(JsonObject json) { + String id = json.get("id").getAsString(); + UnbakedItemSettings itemSettings = UnbakedItemSettings.fromJson(json.getAsJsonObject("itemSettings")); + UnbakedBlockSettings blockSettings = UnbakedBlockSettings.fromJson(json.getAsJsonObject("blockSettings")); + RiftDataList riftDataList = RiftDataList.fromJson(json.getAsJsonArray("riftData")); + return new UnbakedDoorData(id, itemSettings, blockSettings, riftDataList); + } + + public UnbakedDoorData(String id, UnbakedItemSettings itemSettings, UnbakedBlockSettings blockSettings, RiftDataList riftDataList) { + this.id = id; + this.itemSettings = itemSettings; + this.blockSettings = blockSettings; + this.riftDataList = riftDataList; + } + + public Pair construct() { + if (closed) { + throw new UnsupportedOperationException("Already Closed"); + } + + Item.Settings itemSettings; + if (this.itemSettings.parent.isPresent()) { + itemSettings = ItemExtensions.getSettings(Registry.ITEM.get(new Identifier(this.itemSettings.parent.get()))); + } else { + itemSettings = new Item.Settings().group(ModItems.DIMENSIONAL_DOORS); + } + this.itemSettings.maxCount.ifPresent(itemSettings::maxCount); + this.itemSettings.maxDamage.ifPresent(itemSettings::maxDamageIfAbsent); + this.itemSettings.rarity.ifPresent(itemSettings::rarity); + this.itemSettings.fireproof.ifPresentAndTrue(itemSettings::fireproof); + + FabricBlockSettings blockSettings = FabricBlockSettings.copyOf(Registry.BLOCK.get(new Identifier(this.blockSettings.parent))); + this.blockSettings.luminance.ifPresent(blockSettings::luminance); + Block doorBlock = new DimensionalDoorBlock(blockSettings); + Item doorItem = new DimensionalDoorItem(doorBlock, itemSettings, createSetupFunction()); + return new Pair<>(doorItem, doorBlock); + } + + private Consumer createSetupFunction() { + return rift -> { + RiftDataList.OptRiftData riftData = this.riftDataList.getRiftData(rift); + riftData.getDestination().ifPresent(rift::setDestination); + riftData.getProperties().ifPresent(rift::setProperties); + }; + } + + @Override + public void close() throws Exception { + this.id = null; + this.blockSettings = null; + this.itemSettings = null; + this.riftDataList = null; + this.closed = true; + } + + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private static final class UnbakedItemSettings { + private static final Map RARITIES = Util.make(ImmutableMap.builder(), b -> { + for (Rarity rarity : Rarity.values()) { + b.put(rarity.name().toLowerCase(), rarity); + } + }).build(); + private final Optional parent; + private final OptionalInt maxCount; + private final OptionalInt maxDamage; + private final Optional rarity; + private final OptionalBool fireproof; + + public static UnbakedItemSettings fromJson(JsonObject json) { + Optional parent = Optional.ofNullable(json.get("parent")).map(JsonElement::getAsString); + OptionalInt maxCount = Optional.ofNullable(json.get("maxCount")).map(JsonElement::getAsInt).map(OptionalInt::of).orElse(OptionalInt.empty()); + OptionalInt maxDamage = Optional.ofNullable(json.get("maxDamage")).map(JsonElement::getAsInt).map(OptionalInt::of).orElse(OptionalInt.empty()); + Optional rarity = Optional.ofNullable(json.get("rarity")).map(JsonElement::getAsString).map(String::toLowerCase).map(RARITIES::get).map(Objects::requireNonNull); + OptionalBool fireproof = Optional.ofNullable(json.get("fireproof")).map(JsonElement::getAsBoolean).map(OptionalBool::of).orElse(OptionalBool.empty()); + return new UnbakedItemSettings(parent, maxCount, maxDamage, rarity, fireproof); + } + + private UnbakedItemSettings(Optional parent, OptionalInt maxCount, OptionalInt maxDamage, Optional rarity, OptionalBool fireproof) { + this.parent = parent; + this.maxCount = maxCount; + this.maxDamage = maxDamage; + this.rarity = rarity; + this.fireproof = fireproof; + } + } + + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private static final class UnbakedBlockSettings { + private final String parent; + private final OptionalInt luminance; + + public static UnbakedBlockSettings fromJson(JsonObject json) { + String parent = Optional.ofNullable(json.get("parent")).map(JsonElement::getAsString).orElseThrow(() -> new RuntimeException("Missing parent block")); + OptionalInt luminance = Optional.ofNullable(json.get("maxCount")).map(JsonElement::getAsInt).map(OptionalInt::of).orElse(OptionalInt.empty()); + return new UnbakedBlockSettings(parent, luminance); + } + + private UnbakedBlockSettings(String parent, OptionalInt luminance) { + this.parent = parent; + this.luminance = luminance; + } + } +} diff --git a/src/main/java/org/dimdev/dimdoors/block/door/condition/AllCondition.java b/src/main/java/org/dimdev/dimdoors/block/door/condition/AllCondition.java new file mode 100644 index 00000000..72d30e4d --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/block/door/condition/AllCondition.java @@ -0,0 +1,31 @@ +package org.dimdev.dimdoors.block.door.condition; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.dimdev.dimdoors.block.entity.EntranceRiftBlockEntity; + +public class AllCondition extends MultipleCondition { + public AllCondition(List conditions) { + super(conditions); + } + + public static AllCondition fromJson(JsonObject json) { + JsonArray conditions = json.getAsJsonArray("conditions"); + return new AllCondition(StreamSupport.stream(conditions.spliterator(), false).map(JsonElement::getAsJsonObject).map(Condition::fromJson).collect(Collectors.toList())); + } + + @Override + public ConditionType getType() { + return ConditionType.ALL; + } + + @Override + public boolean matches(EntranceRiftBlockEntity rift) { + return this.conditions.stream().allMatch(c -> c.matches(rift)); + } +} diff --git a/src/main/java/org/dimdev/dimdoors/block/door/condition/AnyCondition.java b/src/main/java/org/dimdev/dimdoors/block/door/condition/AnyCondition.java new file mode 100644 index 00000000..34fc57f3 --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/block/door/condition/AnyCondition.java @@ -0,0 +1,31 @@ +package org.dimdev.dimdoors.block.door.condition; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.dimdev.dimdoors.block.entity.EntranceRiftBlockEntity; + +public class AnyCondition extends MultipleCondition { + public AnyCondition(List conditions) { + super(conditions); + } + + public static AnyCondition fromJson(JsonObject json) { + JsonArray conditions = json.getAsJsonArray("conditions"); + return new AnyCondition(StreamSupport.stream(conditions.spliterator(), false).map(JsonElement::getAsJsonObject).map(Condition::fromJson).collect(Collectors.toList())); + } + + @Override + public ConditionType getType() { + return ConditionType.ANY; + } + + @Override + public boolean matches(EntranceRiftBlockEntity rift) { + return this.conditions.stream().anyMatch(c -> c.matches(rift)); + } +} diff --git a/src/main/java/org/dimdev/dimdoors/block/door/condition/Condition.java b/src/main/java/org/dimdev/dimdoors/block/door/condition/Condition.java new file mode 100644 index 00000000..fbbd07a1 --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/block/door/condition/Condition.java @@ -0,0 +1,65 @@ +package org.dimdev.dimdoors.block.door.condition; + +import java.util.Objects; +import java.util.function.Function; + +import com.google.gson.JsonObject; +import com.mojang.serialization.Lifecycle; +import org.dimdev.dimdoors.block.entity.EntranceRiftBlockEntity; + +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.util.registry.SimpleRegistry; + +import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder; + +public interface Condition { + Registry> REGISTRY = FabricRegistryBuilder., SimpleRegistry>>from(new SimpleRegistry<>(RegistryKey.ofRegistry(new Identifier("dimdoors", "rift_data_condition")), Lifecycle.stable())).buildAndRegister(); + + boolean matches(EntranceRiftBlockEntity rift); + + default JsonObject toJson(JsonObject json) { + json.addProperty("type", "dimdoors:" + getType().getId()); + this.toJsonInner(json); + return json; + } + + void toJsonInner(JsonObject json); + + ConditionType getType(); + + static Condition fromJson(JsonObject json) { + Identifier type = new Identifier(json.getAsJsonPrimitive("type").getAsString()); + return Objects.requireNonNull(REGISTRY.get(type)).fromJson(json); + } + + interface ConditionType { + ConditionType ALL = register("all", AllCondition::fromJson); + ConditionType ANY = register("any", AnyCondition::fromJson); + ConditionType INVERSE = register("inverse", InverseCondition::fromJson); + ConditionType WORLD_MATCH = register("world_match", WorldMatchCondition::fromJson); + + T fromJson(JsonObject json); + + JsonObject toJson(T t, JsonObject json); + + default String getId() { + return REGISTRY.getId(this).toString(); + } + + static ConditionType register(String name, Function fromJson) { + return Registry.register(REGISTRY, new Identifier("dimdoors", name), new ConditionType() { + @Override + public T fromJson(JsonObject json) { + return fromJson.apply(json); + } + + @Override + public JsonObject toJson(T t, JsonObject json) { + return t.toJson(json); + } + }); + } + } +} diff --git a/src/main/java/org/dimdev/dimdoors/block/door/condition/InverseCondition.java b/src/main/java/org/dimdev/dimdoors/block/door/condition/InverseCondition.java new file mode 100644 index 00000000..704f1293 --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/block/door/condition/InverseCondition.java @@ -0,0 +1,31 @@ +package org.dimdev.dimdoors.block.door.condition; + +import com.google.gson.JsonObject; +import org.dimdev.dimdoors.block.entity.EntranceRiftBlockEntity; + +public class InverseCondition implements Condition { + private final Condition condition; + + public InverseCondition(Condition condition) { + this.condition = condition; + } + + @Override + public void toJsonInner(JsonObject json) { + json.add("condition", condition.toJson(new JsonObject())); + } + + @Override + public ConditionType getType() { + return ConditionType.INVERSE; + } + + public static InverseCondition fromJson(JsonObject json) { + return new InverseCondition(Condition.fromJson(json.getAsJsonObject("condition"))); + } + + @Override + public boolean matches(EntranceRiftBlockEntity rift) { + return !this.condition.matches(rift); + } +} diff --git a/src/main/java/org/dimdev/dimdoors/block/door/condition/MultipleCondition.java b/src/main/java/org/dimdev/dimdoors/block/door/condition/MultipleCondition.java new file mode 100644 index 00000000..963c0135 --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/block/door/condition/MultipleCondition.java @@ -0,0 +1,21 @@ +package org.dimdev.dimdoors.block.door.condition; + +import java.util.List; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +public abstract class MultipleCondition implements Condition { + protected final List conditions; + + protected MultipleCondition(List conditions) { + this.conditions = conditions; + } + + @Override + public void toJsonInner(JsonObject json) { + JsonArray conditionsJson = new JsonArray(); + conditions.forEach(c -> conditionsJson.add(c.toJson( new JsonObject()))); + json.add("conditions", conditionsJson); + } +} diff --git a/src/main/java/org/dimdev/dimdoors/block/door/condition/WorldMatchCondition.java b/src/main/java/org/dimdev/dimdoors/block/door/condition/WorldMatchCondition.java new file mode 100644 index 00000000..694d4f00 --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/block/door/condition/WorldMatchCondition.java @@ -0,0 +1,38 @@ +package org.dimdev.dimdoors.block.door.condition; + +import com.google.gson.JsonObject; +import org.dimdev.dimdoors.block.entity.EntranceRiftBlockEntity; + +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.World; + +public class WorldMatchCondition implements Condition { + private final RegistryKey world; + + public WorldMatchCondition(RegistryKey world) { + this.world = world; + } + + public static WorldMatchCondition fromJson(JsonObject json) { + RegistryKey key = RegistryKey.of(Registry.DIMENSION, new Identifier(json.getAsJsonPrimitive("world").getAsString())); + return new WorldMatchCondition(key); + } + + @Override + public boolean matches(EntranceRiftBlockEntity rift) { + //noinspection ConstantConditions + return rift.getWorld().getRegistryKey() == this.world; + } + + @Override + public void toJsonInner(JsonObject json) { + json.addProperty("world", world.getValue().toString()); + } + + @Override + public ConditionType getType() { + return ConditionType.WORLD_MATCH; + } +} diff --git a/src/main/java/org/dimdev/dimdoors/block/entity/RiftBlockEntity.java b/src/main/java/org/dimdev/dimdoors/block/entity/RiftBlockEntity.java index 223b74e6..d6fd8975 100644 --- a/src/main/java/org/dimdev/dimdoors/block/entity/RiftBlockEntity.java +++ b/src/main/java/org/dimdev/dimdoors/block/entity/RiftBlockEntity.java @@ -49,8 +49,8 @@ public abstract class RiftBlockEntity extends BlockEntity implements BlockEntity } @Override - public void fromTag(CompoundTag nbt) { - super.fromTag(nbt); + public void readNbt(CompoundTag nbt) { + super.readNbt(nbt); this.deserialize(nbt); } @@ -59,8 +59,8 @@ public abstract class RiftBlockEntity extends BlockEntity implements BlockEntity } @Override - public CompoundTag toTag(CompoundTag tag) { - super.toTag(tag); + public CompoundTag writeNbt(CompoundTag tag) { + super.writeNbt(tag); return this.serialize(tag); } diff --git a/src/main/java/org/dimdev/dimdoors/entity/ai/MonolithAggroGoal.java b/src/main/java/org/dimdev/dimdoors/entity/ai/MonolithAggroGoal.java index 947f2eea..6014ccee 100644 --- a/src/main/java/org/dimdev/dimdoors/entity/ai/MonolithAggroGoal.java +++ b/src/main/java/org/dimdev/dimdoors/entity/ai/MonolithAggroGoal.java @@ -8,9 +8,6 @@ import org.dimdev.dimdoors.DimensionalDoorsInitializer; import org.dimdev.dimdoors.entity.MonolithEntity; import org.dimdev.dimdoors.item.ModItems; import org.dimdev.dimdoors.sound.ModSoundEvents; -import org.dimdev.dimdoors.util.Location; -import org.dimdev.dimdoors.util.TeleportUtil; -import org.dimdev.dimdoors.world.ModDimensions; import net.minecraft.entity.ai.TargetPredicate; import net.minecraft.entity.ai.goal.Goal; @@ -18,16 +15,17 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.PacketByteBuf; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.sound.SoundCategory; +import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; -import net.fabricmc.fabric.api.network.ServerSidePacketRegistry; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import static net.minecraft.predicate.entity.EntityPredicates.EXCEPT_SPECTATOR; import static org.dimdev.dimdoors.entity.MonolithEntity.MAX_AGGRO; public class MonolithAggroGoal extends Goal { - protected final MonolithEntity mob; + public static final Identifier MONOLITH_PARTICLE_PACKET = new Identifier("dimdoors", "monolith_particle_packet"); + protected final MonolithEntity mob; protected PlayerEntity target; protected final float range; protected final TargetPredicate targetPredicate; @@ -96,7 +94,7 @@ public class MonolithAggroGoal extends Goal { PacketByteBuf data = new PacketByteBuf(Unpooled.buffer()); data.writeInt(this.mob.getAggro()); - ServerPlayNetworking.send((ServerPlayerEntity) this.target, DimensionalDoorsInitializer.MONOLITH_PARTICLE_PACKET, data); + ServerPlayNetworking.send((ServerPlayerEntity) this.target, MONOLITH_PARTICLE_PACKET, data); } // Teleport the target player if various conditions are met diff --git a/src/main/java/org/dimdev/dimdoors/item/ItemExtensions.java b/src/main/java/org/dimdev/dimdoors/item/ItemExtensions.java new file mode 100644 index 00000000..da1d90f6 --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/item/ItemExtensions.java @@ -0,0 +1,16 @@ +package org.dimdev.dimdoors.item; + +import net.minecraft.item.Item; + +public interface ItemExtensions { + Item.Settings dimdoors_getSettings(); + + static Item.Settings getSettings(Item item) { + Item.Settings settings = ((ItemExtensions) item).dimdoors_getSettings(); + return ((SettingsExtensions) settings).clone(); + } + + interface SettingsExtensions extends Cloneable { + Item.Settings clone(); + } +} diff --git a/src/main/java/org/dimdev/dimdoors/item/ModItems.java b/src/main/java/org/dimdev/dimdoors/item/ModItems.java index 9d4f58ea..83557828 100644 --- a/src/main/java/org/dimdev/dimdoors/item/ModItems.java +++ b/src/main/java/org/dimdev/dimdoors/item/ModItems.java @@ -41,7 +41,7 @@ public final class ModItems { public static final ItemGroup DIMENSIONAL_DOORS = FabricItemGroupBuilder .create(new Identifier("dimdoors", "dimensional_doors")) - .icon(() -> new ItemStack(ModItems.IRON_DIMENSIONAL_DOOR)) + .icon(() -> new ItemStack(ModItems.RIFT_BLADE)) .build(); @RegistryObject("quartz_door") diff --git a/src/main/java/org/dimdev/dimdoors/mixin/ItemMixin.java b/src/main/java/org/dimdev/dimdoors/mixin/ItemMixin.java new file mode 100644 index 00000000..c00f98bf --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/mixin/ItemMixin.java @@ -0,0 +1,38 @@ +package org.dimdev.dimdoors.mixin; + +import org.dimdev.dimdoors.item.ItemExtensions; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.item.Item; + +@Mixin(Item.class) +public class ItemMixin implements ItemExtensions { + @Unique + private Item.Settings settings; + + @Inject(method = "", at = @At("TAIL")) + public void cacheSettings(Item.Settings settings, CallbackInfo ci) { + this.settings = settings; + } + + @Override + public Item.Settings dimdoors_getSettings() { + return settings; + } + + @Mixin(Item.Settings.class) + public static class SettingsMixin implements ItemExtensions.SettingsExtensions { + @Override + public Item.Settings clone() { + try { + return (Item.Settings) super.clone(); + } catch (CloneNotSupportedException e) { + throw new AssertionError(e); // Cant happen, we are Cloneable + } + } + } +} diff --git a/src/main/java/org/dimdev/dimdoors/rift/targets/PrivatePocketExitTarget.java b/src/main/java/org/dimdev/dimdoors/rift/targets/PrivatePocketExitTarget.java index 2b0df6d5..98fbb183 100644 --- a/src/main/java/org/dimdev/dimdoors/rift/targets/PrivatePocketExitTarget.java +++ b/src/main/java/org/dimdev/dimdoors/rift/targets/PrivatePocketExitTarget.java @@ -16,8 +16,6 @@ import org.dimdev.dimdoors.world.pocket.PocketDirectory; import net.minecraft.entity.Entity; import net.minecraft.text.TranslatableText; -//import net.fabricmc.fabric.api.dimension.v1.FabricDimensions; - public class PrivatePocketExitTarget extends VirtualTarget implements EntityTarget { public static final RGBA COLOR = new RGBA(0, 1, 0, 1); diff --git a/src/main/java/org/dimdev/dimdoors/util/OptionalBool.java b/src/main/java/org/dimdev/dimdoors/util/OptionalBool.java new file mode 100644 index 00000000..bbb9ce5b --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/util/OptionalBool.java @@ -0,0 +1,79 @@ +package org.dimdev.dimdoors.util; + +import java.util.NoSuchElementException; +import java.util.function.IntConsumer; +import java.util.function.IntSupplier; +import java.util.function.Supplier; +import java.util.stream.IntStream; + +import it.unimi.dsi.fastutil.booleans.BooleanConsumer; + +public final class OptionalBool { + private static final OptionalBool EMPTY = new OptionalBool(); + private final boolean present; + private final boolean value; + + private OptionalBool() { + this.present = false; + this.value = false; + } + + public static OptionalBool empty() { + return EMPTY; + } + + private OptionalBool(boolean value) { + this.present = true; + this.value = value; + } + + public static OptionalBool of(boolean value) { + return new OptionalBool(value); + } + + public boolean getAsBool() { + if (!present) { + throw new NoSuchElementException("No value present"); + } + return value; + } + + public boolean isPresent() { + return present; + } + + public void ifPresent(BooleanConsumer action) { + if (present) { + action.accept(value); + } + } + + public void ifPresentAndTrue(Runnable action) { + if (present && value) action.run(); + } + + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (!(obj instanceof OptionalBool)) { + return false; + } + + OptionalBool other = (OptionalBool) obj; + return (present && other.present) ? value == other.value : present == other.present; + } + + @Override + public int hashCode() { + return present ? Boolean.hashCode(value) : 0; + } + + @Override + public String toString() { + return present ? String.format("OptionalBool[%s]", value) : "OptionalBool.empty"; + } +} diff --git a/src/main/java/org/dimdev/dimdoors/util/SubRootJanksonConfigSerializer.java b/src/main/java/org/dimdev/dimdoors/util/SubRootJanksonConfigSerializer.java new file mode 100644 index 00000000..648aac85 --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/util/SubRootJanksonConfigSerializer.java @@ -0,0 +1,60 @@ +package org.dimdev.dimdoors.util; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import blue.endless.jankson.Jankson; +import me.sargunvohra.mcmods.autoconfig1u.ConfigData; +import me.sargunvohra.mcmods.autoconfig1u.annotation.Config; +import me.sargunvohra.mcmods.autoconfig1u.serializer.ConfigSerializer; +import me.sargunvohra.mcmods.autoconfig1u.util.Utils; +import org.dimdev.dimdoors.DimensionalDoorsInitializer; + +public class SubRootJanksonConfigSerializer implements ConfigSerializer { + private static final Jankson JANKSON = Jankson.builder().build(); + private final Config definition; + private final Class configClass; + + public SubRootJanksonConfigSerializer(Config definition, Class configClass) { + this.definition = definition; + this.configClass = configClass; + } + + private Path getConfigPath() { + return DimensionalDoorsInitializer.getConfigRoot().resolve(definition.name() + "-config.json5"); + } + + @Override + public void serialize(T config) throws SerializationException { + Path configPath = getConfigPath(); + try { + Files.createDirectories(configPath.getParent()); + BufferedWriter writer = Files.newBufferedWriter(configPath); + writer.write(JANKSON.toJson(config).toJson(true, true)); + writer.close(); + } catch (IOException e) { + throw new SerializationException(e); + } + } + + @Override + public T deserialize() throws SerializationException { + Path configPath = getConfigPath(); + if (Files.exists(configPath)) { + try { + return JANKSON.fromJson(JANKSON.load(getConfigPath().toFile()), configClass); + } catch (Throwable e) { + throw new SerializationException(e); + } + } else { + return createDefault(); + } + } + + @Override + public T createDefault() { + return Utils.constructUnsafely(configClass); + } +} diff --git a/src/main/java/org/dimdev/dimdoors/world/limbo/LimboDecay.java b/src/main/java/org/dimdev/dimdoors/world/limbo/LimboDecay.java index d639372d..752297c2 100644 --- a/src/main/java/org/dimdev/dimdoors/world/limbo/LimboDecay.java +++ b/src/main/java/org/dimdev/dimdoors/world/limbo/LimboDecay.java @@ -29,8 +29,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.registry.Registry; import net.minecraft.world.World; -import net.fabricmc.loader.api.FabricLoader; - import static net.minecraft.block.Blocks.ACACIA_LOG; import static net.minecraft.block.Blocks.ACACIA_PLANKS; import static net.minecraft.block.Blocks.ACACIA_WOOD; @@ -106,7 +104,7 @@ public final class LimboDecay { private static final Map DECAY_SEQUENCE = new HashMap<>(); private static final Map DEFAULT_VALUES; private static final Gson GSON = new GsonBuilder().setLenient().setPrettyPrinting().create(); - private static final Path CONFIG_PATH = FabricLoader.getInstance().getConfigDir().resolve("dimdoors_limbo_decay.json"); + private static final Path CONFIG_PATH = DimensionalDoorsInitializer.getConfigRoot().resolve("limbo_decay.json"); public static void init() { try { diff --git a/src/main/resources/dimdoors.mixins.json b/src/main/resources/dimdoors.mixins.json index 9771e7c7..b46fc422 100644 --- a/src/main/resources/dimdoors.mixins.json +++ b/src/main/resources/dimdoors.mixins.json @@ -5,6 +5,8 @@ "mixins": [ "DefaultBiomeFeaturesMixin", "ExtendedServerPlayNetworkhandlerMixin", + "ItemMixin", + "ItemMixin$SettingsMixin", "PlayerEntityMixin", "RecipesProviderAccessor", "RegistryKeyMixin",