diff --git a/build.gradle b/build.gradle index f3408db..fd2fa92 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,6 @@ plugins { id "fabric-loom" version "1.1-SNAPSHOT" id "io.github.juuxel.loom-quiltflower" version "1.8.0" - id "io.github.p03w.machete" version "1.2.0" } archivesBaseName = project.archives_base_name diff --git a/gradle.properties b/gradle.properties index 7c9cb0f..daf7f52 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ org.gradle.parallel = true # Mod Properties maven_group = ru.pinkgoosik archives_base_name = skylands -mod_version = 0.3.4 +mod_version = 0.3.5 # Dependencies | Check these on https://fabricmc.net/develop minecraft_version = 1.19.4 diff --git a/src/main/java/skylands/api/SkylandsAPI.java b/src/main/java/skylands/api/SkylandsAPI.java index f4ab6fb..4da98df 100644 --- a/src/main/java/skylands/api/SkylandsAPI.java +++ b/src/main/java/skylands/api/SkylandsAPI.java @@ -1,10 +1,13 @@ package skylands.api; +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.registry.RegistryKey; import net.minecraft.world.World; +import skylands.SkylandsMod; import skylands.logic.Island; import skylands.logic.Skylands; -import skylands.util.Worlds; import java.util.Optional; import java.util.UUID; @@ -12,6 +15,33 @@ public class SkylandsAPI { static Skylands skylands = Skylands.getInstance(); + public static final Event ON_HUB_VISIT = EventFactory.createArrayBacked(HubVisitEvent.class, callbacks -> (player, world) -> { + for (HubVisitEvent callback : callbacks) { + callback.invoke(player, world); + } + }); + @FunctionalInterface public interface HubVisitEvent {void invoke(PlayerEntity player, World world);} + + public static final Event ON_ISLAND_VISIT = EventFactory.createArrayBacked(GenericIslandEvent.class, callbacks -> (player, world, island) -> { + for (GenericIslandEvent callback : callbacks) { + callback.invoke(player, world, island); + } + }); + + public static final Event ON_ISLAND_FIRST_LOAD = EventFactory.createArrayBacked(GenericIslandEvent.class, callbacks -> (player, world, island) -> { + for (GenericIslandEvent callback : callbacks) { + callback.invoke(player, world, island); + } + }); + @FunctionalInterface public interface GenericIslandEvent {void invoke(PlayerEntity player, World world, Island island);} + + public static final Event ON_NETHER_FIRST_LOAD = EventFactory.createArrayBacked(NetherFirstLoad.class, callbacks -> (world, island) -> { + for (NetherFirstLoad callback : callbacks) { + callback.onLoad(world, island); + } + }); + @FunctionalInterface public interface NetherFirstLoad {void onLoad(World world, Island island);} + public static Optional getIsland(PlayerEntity player) { return skylands.islands.get(player); } @@ -24,8 +54,25 @@ public static Optional getIsland(UUID playerUuid) { return skylands.islands.get(playerUuid); } + public static boolean isIsland(World world) { + return isIsland(world.getRegistryKey()); + } + + public static boolean isIsland(RegistryKey registryKey) { + var namespace = registryKey.getValue().getNamespace(); + return namespace.equals(SkylandsMod.MOD_ID) || namespace.equals("nether") || namespace.equals("end"); + } + public static Optional getIsland(World world) { - return Worlds.getIsland(world); + if (isIsland(world)) { + try { + return Skylands.instance.islands.get(UUID.fromString(world.getRegistryKey().getValue().getPath())); + } + catch (Exception e) { + return Optional.empty(); + } + } + return Optional.empty(); } } diff --git a/src/main/java/skylands/command/AcceptCommand.java b/src/main/java/skylands/command/AcceptCommand.java index 220e549..b4ce720 100644 --- a/src/main/java/skylands/command/AcceptCommand.java +++ b/src/main/java/skylands/command/AcceptCommand.java @@ -5,7 +5,7 @@ import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; -import skylands.data.Components; +import skylands.data.SkylandsComponents; import skylands.logic.Skylands; import skylands.util.Players; import skylands.util.Texts; @@ -38,7 +38,7 @@ static void run(ServerPlayerEntity player, String ownerName) { if(!invite.get().accepted) { invite.get().accept(player); player.sendMessage(Texts.prefixed("message.skylands.accept.success", map -> map.put("%owner%", ownerName))); - Components.PLAYER_DATA.get(player).addIsland(ownerName); + SkylandsComponents.PLAYER_DATA.get(player).addIsland(ownerName); } } else { diff --git a/src/main/java/skylands/command/HomeCommand.java b/src/main/java/skylands/command/HomeCommand.java index 4e9c18f..0a865fa 100644 --- a/src/main/java/skylands/command/HomeCommand.java +++ b/src/main/java/skylands/command/HomeCommand.java @@ -6,7 +6,7 @@ import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import skylands.SkylandsMod; -import skylands.data.Components; +import skylands.data.SkylandsComponents; import skylands.logic.Skylands; import skylands.util.Texts; @@ -28,7 +28,7 @@ static void init(CommandDispatcher dispatcher) { var player = context.getSource().getPlayer(); if(player != null) { - var islands = Components.PLAYER_DATA.get(player).getIslands(); + var islands = SkylandsComponents.PLAYER_DATA.get(player).getIslands(); String remains = builder.getRemaining(); @@ -50,7 +50,7 @@ static void init(CommandDispatcher dispatcher) { })))); } - static void run(ServerPlayerEntity player) { + public static void run(ServerPlayerEntity player) { Skylands.instance.islands.get(player).ifPresentOrElse(island -> { if(player.getWorld().getRegistryKey().getValue().equals(SkylandsMod.id(player.getUuid().toString()))) { player.sendMessage(Texts.prefixed("message.skylands.home.fail")); @@ -62,7 +62,7 @@ static void run(ServerPlayerEntity player) { }, () -> player.sendMessage(Texts.prefixed("message.skylands.home.no_island"))); } - static void run(ServerPlayerEntity visitor, String islandOwner) { + public static void run(ServerPlayerEntity visitor, String islandOwner) { Skylands.instance.islands.get(islandOwner).ifPresentOrElse(island -> { if(visitor.getWorld().getRegistryKey().getValue().equals(SkylandsMod.id(island.owner.uuid.toString()))) { visitor.sendMessage(Texts.prefixed("message.skylands.visit_home.fail", map -> map.put("%owner%", islandOwner))); @@ -71,16 +71,16 @@ static void run(ServerPlayerEntity visitor, String islandOwner) { if(island.isMember(visitor)) { visitor.sendMessage(Texts.prefixed("message.skylands.visit_home.success", map -> map.put("%owner%", islandOwner))); island.visitAsMember(visitor); - Components.PLAYER_DATA.get(visitor).addIsland(islandOwner); + SkylandsComponents.PLAYER_DATA.get(visitor).addIsland(islandOwner); } else { visitor.sendMessage(Texts.prefixed("message.skylands.visit_home.not_member")); - Components.PLAYER_DATA.get(visitor).removeIsland(islandOwner); + SkylandsComponents.PLAYER_DATA.get(visitor).removeIsland(islandOwner); } } }, () -> { visitor.sendMessage(Texts.prefixed("message.skylands.visit_home.no_island")); - Components.PLAYER_DATA.get(visitor).removeIsland(islandOwner); + SkylandsComponents.PLAYER_DATA.get(visitor).removeIsland(islandOwner); }); } } diff --git a/src/main/java/skylands/command/HubCommands.java b/src/main/java/skylands/command/HubCommands.java index 95fa415..6c0c925 100644 --- a/src/main/java/skylands/command/HubCommands.java +++ b/src/main/java/skylands/command/HubCommands.java @@ -39,7 +39,7 @@ static void init(CommandDispatcher dispatcher) { }))); } - static void visit(ServerPlayerEntity player, MinecraftServer server) { + public static void visit(ServerPlayerEntity player, MinecraftServer server) { player.sendMessage(Texts.prefixed("message.skylands.hub_visit")); Skylands.instance.hub.visit(player); } diff --git a/src/main/java/skylands/command/VisitCommand.java b/src/main/java/skylands/command/VisitCommand.java index 253352d..1bb52a7 100644 --- a/src/main/java/skylands/command/VisitCommand.java +++ b/src/main/java/skylands/command/VisitCommand.java @@ -26,7 +26,7 @@ static void init(CommandDispatcher dispatcher) { })))); } - static void run(ServerPlayerEntity visitor, ServerPlayerEntity owner) { + public static void run(ServerPlayerEntity visitor, ServerPlayerEntity owner) { String ownerName = owner.getName().getString(); Skylands.instance.islands.get(owner).ifPresentOrElse(island -> { diff --git a/src/main/java/skylands/data/AbstractPlayerData.java b/src/main/java/skylands/data/AbstractPlayerData.java deleted file mode 100644 index 8d3b3da..0000000 --- a/src/main/java/skylands/data/AbstractPlayerData.java +++ /dev/null @@ -1,11 +0,0 @@ -package skylands.data; - -import dev.onyxstudios.cca.api.v3.component.ComponentV3; - -import java.util.ArrayList; - -public interface AbstractPlayerData extends ComponentV3 { - - ArrayList getIslands(); - void setIslands(ArrayList islands); -} diff --git a/src/main/java/skylands/data/AbstractWorldData.java b/src/main/java/skylands/data/AbstractWorldData.java deleted file mode 100644 index 86346a8..0000000 --- a/src/main/java/skylands/data/AbstractWorldData.java +++ /dev/null @@ -1,6 +0,0 @@ -package skylands.data; - -import dev.onyxstudios.cca.api.v3.component.ComponentV3; - -public interface AbstractWorldData extends ComponentV3 { -} diff --git a/src/main/java/skylands/data/PlayerComponent.java b/src/main/java/skylands/data/PlayerComponent.java index 1c5e792..0e1daf5 100644 --- a/src/main/java/skylands/data/PlayerComponent.java +++ b/src/main/java/skylands/data/PlayerComponent.java @@ -1,11 +1,15 @@ package skylands.data; +import dev.onyxstudios.cca.api.v3.component.ComponentV3; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtCompound; +import skylands.logic.Skylands; +import skylands.util.Worlds; import java.util.ArrayList; +import java.util.UUID; -public class PlayerComponent implements AbstractPlayerData { +public class PlayerComponent implements ComponentV3 { public PlayerEntity player; @@ -15,12 +19,10 @@ public PlayerComponent(PlayerEntity player) { this.player = player; } - @Override public ArrayList getIslands() { return islands; } - @Override public void setIslands(ArrayList islands) { this.islands = islands; } @@ -43,6 +45,13 @@ public void readFromNbt(NbtCompound tag) { String owner = islandsNbt.getString(String.valueOf(i)); this.islands.add(owner); } + + if(!tag.getString("lastIsland").isEmpty()) { + Skylands.instance.islands.get(UUID.fromString(tag.getString("lastIsland"))).ifPresent(island -> { + island.getWorld(); + if(island.hasNether) island.getNether(); + }); + } } @Override @@ -54,5 +63,9 @@ public void writeToNbt(NbtCompound tag) { islandsNbt.putString(Integer.toString(i), owner); } tag.put("islands", islandsNbt); + + Worlds.getIsland(player.getWorld()).ifPresent(island -> { + tag.putString("lastIsland", island.owner.uuid.toString()); + }); } } diff --git a/src/main/java/skylands/data/Components.java b/src/main/java/skylands/data/SkylandsComponents.java similarity index 92% rename from src/main/java/skylands/data/Components.java rename to src/main/java/skylands/data/SkylandsComponents.java index 1051196..1be7524 100644 --- a/src/main/java/skylands/data/Components.java +++ b/src/main/java/skylands/data/SkylandsComponents.java @@ -9,7 +9,7 @@ import dev.onyxstudios.cca.api.v3.world.WorldComponentInitializer; import skylands.SkylandsMod; -public class Components implements WorldComponentInitializer, EntityComponentInitializer { +public class SkylandsComponents implements WorldComponentInitializer, EntityComponentInitializer { public static final ComponentKey WORLD_DATA = ComponentRegistryV3.INSTANCE.getOrCreate(SkylandsMod.id("world_data"), WorldComponent.class); public static final ComponentKey PLAYER_DATA = ComponentRegistryV3.INSTANCE.getOrCreate(SkylandsMod.id("player_data"), PlayerComponent.class); diff --git a/src/main/java/skylands/data/WorldComponent.java b/src/main/java/skylands/data/WorldComponent.java index d9ccdbc..1e2a383 100644 --- a/src/main/java/skylands/data/WorldComponent.java +++ b/src/main/java/skylands/data/WorldComponent.java @@ -1,11 +1,12 @@ package skylands.data; +import dev.onyxstudios.cca.api.v3.component.ComponentV3; import net.minecraft.nbt.NbtCompound; import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; import skylands.logic.Skylands; -public class WorldComponent implements AbstractWorldData { +public class WorldComponent implements ComponentV3 { public World world; public WorldComponent(World world) { diff --git a/src/main/java/skylands/logic/Hub.java b/src/main/java/skylands/logic/Hub.java index 88d3fbc..f326829 100644 --- a/src/main/java/skylands/logic/Hub.java +++ b/src/main/java/skylands/logic/Hub.java @@ -3,6 +3,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.math.Vec3d; +import skylands.api.SkylandsAPI; import java.util.Set; @@ -29,6 +30,8 @@ public void writeToNbt(NbtCompound nbt) { } public void visit(PlayerEntity player) { - player.teleport(Skylands.instance.server.getOverworld(), pos.getX(), pos.getY(), pos.getZ(), Set.of(), 0, 0); + var world = Skylands.getServer().getOverworld(); + player.teleport(world, pos.getX(), pos.getY(), pos.getZ(), Set.of(), 0, 0); + SkylandsAPI.ON_HUB_VISIT.invoker().invoke(player, world); } } diff --git a/src/main/java/skylands/logic/Island.java b/src/main/java/skylands/logic/Island.java index 5b1a5b9..2ec4788 100644 --- a/src/main/java/skylands/logic/Island.java +++ b/src/main/java/skylands/logic/Island.java @@ -20,6 +20,7 @@ import net.minecraft.world.gen.chunk.FlatChunkGenerator; import net.minecraft.world.gen.chunk.FlatChunkGeneratorConfig; import skylands.SkylandsMod; +import skylands.api.SkylandsAPI; import skylands.util.Players; import skylands.util.Texts; import xyz.nucleoid.fantasy.Fantasy; @@ -240,34 +241,40 @@ public ServerWorld getWorld() { return handler.asWorld(); } - public void visitAsMember(PlayerEntity player) { + public void visit(PlayerEntity player, Vec3d pos) { ServerWorld world = this.getWorld(); - player.teleport(world, this.spawnPos.getX(), this.spawnPos.getY(), this.spawnPos.getZ(), Set.of(), 0, 0); + player.teleport(world, pos.getX(), pos.getY(), pos.getZ(), Set.of(), 0, 0); + + if(!isMember(player)) { + Players.get(this.owner.name).ifPresent(owner -> { + if(!player.getUuid().equals(owner.getUuid())) { + owner.sendMessage(Texts.prefixed("message.skylands.island_visit.visit", map -> map.put("%visitor%", player.getName().getString()))); + } + }); + } + + SkylandsAPI.ON_ISLAND_VISIT.invoker().invoke(player, world, this); + if (this.freshCreated) { - this.onFirstLoad(); + this.onFirstLoad(player); this.freshCreated = false; } } + public void visitAsMember(PlayerEntity player) { + this.visit(player, this.spawnPos); + } + public void visitAsVisitor(PlayerEntity player) { - ServerWorld world = this.getWorld(); - player.teleport(world, this.visitsPos.getX(), this.visitsPos.getY(), this.visitsPos.getZ(), Set.of(), 0, 0); - if (this.freshCreated) { - this.onFirstLoad(); - this.freshCreated = false; - } - Players.get(this.owner.name).ifPresent(owner -> { - if(!player.getUuid().equals(owner.getUuid())) { - owner.sendMessage(Texts.prefixed("message.skylands.island_visit.visit", map -> map.put("%visitor%", player.getName().getString()))); - } - }); + this.visit(player, this.visitsPos); } - public void onFirstLoad() { + public void onFirstLoad(PlayerEntity player) { ServerWorld world = this.getWorld(); StructureTemplate structure = server.getStructureTemplateManager().getTemplateOrBlank(SkylandsMod.id("start_island")); StructurePlacementData data = new StructurePlacementData().setMirror(BlockMirror.NONE).setIgnoreEntities(true); structure.place(world, new BlockPos(-7, 65, -7), new BlockPos(0, 0, 0), data, world.getRandom(), Block.NOTIFY_ALL); + SkylandsAPI.ON_ISLAND_FIRST_LOAD.invoker().invoke(player, world, this); } void onFirstNetherLoad(ServerWorld world) { @@ -278,6 +285,7 @@ void onFirstNetherLoad(ServerWorld world) { StructureTemplate structure = server.getStructureTemplateManager().getTemplateOrBlank(SkylandsMod.id("nether_island")); StructurePlacementData data = new StructurePlacementData().setMirror(BlockMirror.NONE).setIgnoreEntities(true); structure.place(world, new BlockPos(-7, 65, -7), new BlockPos(0, 0, 0), data, world.getRandom(), Block.NOTIFY_ALL); + SkylandsAPI.ON_NETHER_FIRST_LOAD.invoker().onLoad(world, this); this.hasNether = true; } diff --git a/src/main/java/skylands/logic/Skylands.java b/src/main/java/skylands/logic/Skylands.java index 185273e..efd3566 100644 --- a/src/main/java/skylands/logic/Skylands.java +++ b/src/main/java/skylands/logic/Skylands.java @@ -48,6 +48,10 @@ public void writeToNbt(NbtCompound nbt) { nbt.put("skylands", skylandsNbt); } + public static MinecraftServer getServer() { + return getInstance().server; + } + public static Skylands getInstance() { return Skylands.instance; } diff --git a/src/main/java/skylands/mixin/entity/ServerPlayerEntityMixin.java b/src/main/java/skylands/mixin/entity/ServerPlayerEntityMixin.java index a977d8f..0e5425d 100644 --- a/src/main/java/skylands/mixin/entity/ServerPlayerEntityMixin.java +++ b/src/main/java/skylands/mixin/entity/ServerPlayerEntityMixin.java @@ -30,7 +30,7 @@ void tick(CallbackInfo ci) { ServerPlayerEntity player = ServerPlayerEntity.class.cast(this); if(!WorldProtection.canModify(world, player)) { - if(player.getPos().getY() < -74) { + if(player.getPos().getY() < world.getDimension().minY() - 10) { Worlds.getIsland(world).ifPresentOrElse(island -> { var pos = island.spawnPos; player.teleport(island.getWorld(), pos.getX(), pos.getY(), pos.getZ(), Set.of(), 0, 0); diff --git a/src/main/resources/data/skylands/lang/en_us.json b/src/main/resources/data/skylands/lang/en_us.json index 598e5b2..b5055e8 100644 --- a/src/main/resources/data/skylands/lang/en_us.json +++ b/src/main/resources/data/skylands/lang/en_us.json @@ -105,20 +105,20 @@ "message.skylands.world_protection.boat_open": "You can't interact with entities out here!", "message.skylands.world_protection.armor_stand_use": "You can't interact with entities out here!", - "message.skylands.help.0": "- /sl hub -> Teleport to the Hub.", - "message.skylands.help.1": "- /sl create -> Creates an Island.", - "message.skylands.help.2": "- /sl home -> Teleport to your Island.", - "message.skylands.help.3": "- /sl visit -> Visit someone's Island.", - "message.skylands.help.4": "- /sl home -> Teleport to an Island you are member of.", - "message.skylands.help.5": "- /sl members invite -> Invite player to your Island.", - "message.skylands.help.6": "- /sl members remove -> Remove player from your Island.", - "message.skylands.help.7": "- /sl accept -> Accept Island join invite request.", - "message.skylands.help.8": "- /sl kick -> Kick player from your Island.", - "message.skylands.help.9": "- /sl ban -> Ban player from visiting your Island.", - "message.skylands.help.10": "- /sl unban -> Unban player to allow visiting your Island.", - "message.skylands.help.11": "- /sl delete -> Deletes your Island.", - "message.skylands.help.12": "- /sl settings set-spawn-pos -> Changes home position.", - "message.skylands.help.13": "- /sl settings set-visits-pos -> Changes visits position.", - "message.skylands.help.14": "- /sl settings toggle-visits -> Enables/disables ability to visit your Island.", - "message.skylands.help.15": "- /sl help -> Sends this list." + "message.skylands.help.0": "- /sl hub → Teleport to the Hub.", + "message.skylands.help.1": "- /sl create → Creates an Island.", + "message.skylands.help.2": "- /sl home → Teleport to your Island.", + "message.skylands.help.3": "- /sl visit → Visit someone's Island.", + "message.skylands.help.4": "- /sl home → Teleport to an Island you are member of.", + "message.skylands.help.5": "- /sl members invite → Invite player to your Island.", + "message.skylands.help.6": "- /sl members remove → Remove player from your Island.", + "message.skylands.help.7": "- /sl accept → Accept Island join invite request.", + "message.skylands.help.8": "- /sl kick → Kick player from your Island.", + "message.skylands.help.9": "- /sl ban → Ban player from visiting your Island.", + "message.skylands.help.10": "- /sl unban → Unban player to allow visiting your Island.", + "message.skylands.help.11": "- /sl delete → Deletes your Island.", + "message.skylands.help.12": "- /sl settings set-spawn-pos → Changes home position.", + "message.skylands.help.13": "- /sl settings set-visits-pos → Changes visits position.", + "message.skylands.help.14": "- /sl settings toggle-visits → Enables/disables ability to visit your Island.", + "message.skylands.help.15": "- /sl help → Sends this list." } diff --git a/src/main/resources/data/skylands/structures/start_island.nbt b/src/main/resources/data/skylands/structures/start_island.nbt index a6bc324..3efb903 100644 Binary files a/src/main/resources/data/skylands/structures/start_island.nbt and b/src/main/resources/data/skylands/structures/start_island.nbt differ diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 8e41c3a..35d86b5 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -23,7 +23,7 @@ "skylands.SkylandsMod" ], "cardinal-components": [ - "skylands.data.Components" + "skylands.data.SkylandsComponents" ] }, "accessWidener": "skylands.accesswidener",