diff --git a/src/main/java/thedarkcolour/exdeorum/event/EventHandler.java b/src/main/java/thedarkcolour/exdeorum/event/EventHandler.java index 0a7fed77..a241d977 100644 --- a/src/main/java/thedarkcolour/exdeorum/event/EventHandler.java +++ b/src/main/java/thedarkcolour/exdeorum/event/EventHandler.java @@ -21,6 +21,7 @@ package thedarkcolour.exdeorum.event; import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.data.worldgen.features.TreeFeatures; @@ -35,7 +36,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.GameRules; -import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.Heightmap; @@ -45,7 +46,12 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.ClientChatEvent; import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; +import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.event.AddReloadListenerEvent; +import net.minecraftforge.event.AttachCapabilitiesEvent; import net.minecraftforge.event.OnDatapackSyncEvent; import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.entity.player.PlayerEvent; @@ -59,12 +65,15 @@ import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.InterModEnqueueEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.loading.FMLEnvironment; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import thedarkcolour.exdeorum.ExDeorum; import thedarkcolour.exdeorum.blockentity.helper.ItemHelper; import thedarkcolour.exdeorum.client.CompostColors; import thedarkcolour.exdeorum.compat.ModIds; import thedarkcolour.exdeorum.compat.top.ExDeorumTopCompat; import thedarkcolour.exdeorum.config.EConfig; +import thedarkcolour.exdeorum.island.SkyblockCapability; import thedarkcolour.exdeorum.item.WateringCanItem; import thedarkcolour.exdeorum.material.AbstractCrucibleMaterial; import thedarkcolour.exdeorum.material.BarrelMaterial; @@ -94,6 +103,8 @@ public final class EventHandler { modBus.addListener(EventHandler::onCommonSetup); fmlBus.addListener(EventHandler::serverShutdown); fmlBus.addListener(EventHandler::serverTick); + modBus.addListener(EventHandler::registerCapabilities); + fmlBus.addGenericListener(Level.class, EventHandler::attachCapabilities); if (ExDeorum.DEBUG) { fmlBus.addListener(EventHandler::handleDebugCommands); @@ -264,4 +275,16 @@ public final class EventHandler { VisualUpdateTracker.syncVisualUpdates(); } } + + private static void registerCapabilities(RegisterCapabilitiesEvent event) { + event.register(SkyblockCapability.class); + } + + private static void attachCapabilities(AttachCapabilitiesEvent event) { + Level level = event.getObject(); + + if (!level.isClientSide && level.dimension() == Level.OVERWORLD) { + event.addCapability(SkyblockCapability.ID, new SkyblockCapability()); + } + } } diff --git a/src/main/java/thedarkcolour/exdeorum/island/SkyblockCapability.java b/src/main/java/thedarkcolour/exdeorum/island/SkyblockCapability.java new file mode 100644 index 00000000..9f9b98e5 --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/island/SkyblockCapability.java @@ -0,0 +1,71 @@ +/* + * Ex Deorum + * Copyright (c) 2024 thedarkcolour + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package thedarkcolour.exdeorum.island; + +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; +import net.minecraftforge.common.capabilities.ICapabilitySerializable; +import net.minecraftforge.common.util.LazyOptional; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import thedarkcolour.exdeorum.ExDeorum; + +import java.util.ArrayList; +import java.util.List; + +public class SkyblockCapability implements ICapabilitySerializable { + public static final ResourceLocation ID = new ResourceLocation(ExDeorum.ID, "island_manager"); + public static final Capability CAPABILITY = CapabilityManager.get(new CapabilityToken<>() {}); + + private final LazyOptional holder = LazyOptional.of(() -> this); + private final List islands = new ArrayList<>(); + + @Override + public CompoundTag serializeNBT() { + CompoundTag nbt = new CompoundTag(); + ListTag listTag = new ListTag(); + + for (var island : this.islands) { + listTag.add(island.serializeNbt()); + } + nbt.put("islands", listTag); + + return nbt; + } + + @Override + public void deserializeNBT(CompoundTag nbt) { + this.islands.clear(); + + for (var islandNbt : nbt.getList("islands", Tag.TAG_COMPOUND)) { + this.islands.add(new SkyblockIsland((CompoundTag) islandNbt)); + } + } + + @Override + public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + return cap == SkyblockCapability.CAPABILITY ? this.holder.cast() : LazyOptional.empty(); + } +} diff --git a/src/main/java/thedarkcolour/exdeorum/island/SkyblockCommand.java b/src/main/java/thedarkcolour/exdeorum/island/SkyblockCommand.java new file mode 100644 index 00000000..08a55ebf --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/island/SkyblockCommand.java @@ -0,0 +1,58 @@ +/* + * Ex Deorum + * Copyright (c) 2024 thedarkcolour + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package thedarkcolour.exdeorum.island; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import net.minecraft.commands.CommandBuildContext; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; + +import static net.minecraft.commands.Commands.argument; + +public class SkyblockCommand { + public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { + dispatcher.register(Commands.literal("exdeorum_islands") + .then(admin("create")) + .then(admin("delete")) + .then(admin("list")) + .then(admin("config")) + .then(admin("info")) + .then(admin("tp")) + .then(player("tpr")) + .then(player("rename") + .then(argument("new-name", StringArgumentType.string()) + // admins can rename other islands, players can only rename their own island + .then(argument("old-name", StringArgumentType.string()) + .requires(source -> source.hasPermission(Commands.LEVEL_GAMEMASTERS)) + ) + ) + ) + ); + } + + private static LiteralArgumentBuilder admin(String name) { + return Commands.literal(name).requires(source -> source.hasPermission(Commands.LEVEL_GAMEMASTERS)); + } + + private static LiteralArgumentBuilder player(String name) { + return Commands.literal(name); + } +} diff --git a/src/main/java/thedarkcolour/exdeorum/island/SkyblockIsland.java b/src/main/java/thedarkcolour/exdeorum/island/SkyblockIsland.java new file mode 100644 index 00000000..05354568 --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/island/SkyblockIsland.java @@ -0,0 +1,71 @@ +/* + * Ex Deorum + * Copyright (c) 2024 thedarkcolour + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package thedarkcolour.exdeorum.island; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.nbt.Tag; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class SkyblockIsland { + public final int id; + @Nullable + public final UUID creator; + public final BlockPos origin; + public final List owners = new ArrayList<>(); + public String name; + + public SkyblockIsland(int id, @Nullable UUID creator, BlockPos origin, String name) { + this.id = id; + this.creator = creator; + this.origin = origin; + this.name = name; + } + + public SkyblockIsland(CompoundTag nbt) { + this.id = nbt.getInt("id"); + this.creator = nbt.contains("creator") ? nbt.getUUID("creator") : null; + this.origin = NbtUtils.readBlockPos(nbt.getCompound("origin")); + this.name = nbt.getString("name"); + + for (var ownerNbt : nbt.getList("owners", Tag.TAG_INT_ARRAY)) { + this.owners.add(NbtUtils.loadUUID(ownerNbt)); + } + } + + public CompoundTag serializeNbt() { + CompoundTag data = new CompoundTag(); + data.putInt("id", this.id); + if (this.creator != null) { + data.putUUID("creator", this.creator); + } + data.put("origin", NbtUtils.writeBlockPos(this.origin)); + + return data; + } + + public boolean isUnassigned() { + return this.owners.isEmpty(); + } +}