diff --git a/build.gradle b/build.gradle index 1241071..ee5b522 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ plugins { - id 'fabric-loom' version '0.2.6-SNAPSHOT' + id 'fabric-loom' version '0.2.7-SNAPSHOT' id 'maven-publish' + id 'com.github.johnrengelman.shadow' version '5.1.0' } sourceCompatibility = JavaVersion.VERSION_1_8 @@ -14,21 +15,39 @@ minecraft { } repositories { mavenLocal() + maven { url 'https://repo.spongepowered.org/maven'} maven { url 'https://jitpack.io' } maven { url 'http://server.bbkr.space:8081/artifactory/libs-release' } } + +shadowJar { + classifier = "shadow" + configurations = [project.configurations.shadow] +} + +tasks.jar.archiveClassifier = "compile" + +task remapJar(type: net.fabricmc.loom.task.RemapJarTask, overwrite: true) { + from zipTree(shadowJar.archiveFile) dependsOn shadowJar +} + dependencies { //to change the versions see the gradle.properties file minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" modCompile "net.fabricmc:fabric-loader:${project.loader_version}" - modImplementation "com.github.giantnuker:TinyConfig:${project.tiny_config_version}" - modImplementation /*"io.github.indicode.fabric:thimble-permissions:0.0.9"//*/"com.github.giantnuker:Thimble-Permissions:${project.thimble_permissions_version}" - modImplementation "com.github.giantnuker:OfflineInfo:${project.offline_info_version}" + compile "org.spongepowered:configurate-hocon:${project.configurate_version}" + shadow "org.spongepowered:configurate-hocon:${project.configurate_version}" + + //modImplementation "com.github.giantnuker:TinyConfig:${project.tiny_config_version}" + //modImplementation /*"io.github.indicode.fabric:thimble-permissions:0.0.9"//*/"com.github.giantnuker:Thimble-Permissions:${project.thimble_permissions_version}" + //modImplementation "com.github.giantnuker:OfflineInfo:${project.offline_info_version}" - include "com.github.giantnuker:TinyConfig:${project.tiny_config_version}" - //include "com.github.indi-code:Thimble-Permissions:${project.thimble_permissions_version}" + //include "com.github.giantnuker:TinyConfig:${project.tiny_config_version}" + implementation 'org.jetbrains:annotations:15.0' + modImplementation "com.github.OnBlock:Thimble-Permissions:${project.thimble_permissions_version}" + implementation "net.luckperms:api:${project.luckperms_version}" // Fabric API. This is technically optional, but you probably want it anyway. //modCompile "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" diff --git a/gradle.properties b/gradle.properties index 12e432e..890c4c4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,19 +2,20 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties - # check these on https://fabricmc.net/use -minecraft_version=20w10a -yarn_mappings=20w10a+build.6 -loader_version=0.7.8+build.186 +minecraft_version=20w21a +yarn_mappings=20w21a+build.15 +loader_version=0.7.10+build.191 # Mod Properties - mod_version = 1.3.8 - maven_group = io.github.indicode.fabric.itsmine - archives_base_name = itsmine +mod_version = 1.9.5-20W21A +maven_group = io.github.indicode.fabric.itsmine +archives_base_name = itsmine -# Dependencies - # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api - #fabric_version=0.3.2+build.218-1.14 + +configurate_version = 3.6.1 + + + +thimble_permissions_version=0.2.4-20W17A tiny_config_version = 1.1.2 -thimble_permissions_version=26b2bbfb06 -offline_info_version=1a3a7fc98b +luckperms_version=5.0 diff --git a/src/main/java/io/github/indicode/fabric/itsmine/Claim.java b/src/main/java/io/github/indicode/fabric/itsmine/Claim.java deleted file mode 100644 index b1e376b..0000000 --- a/src/main/java/io/github/indicode/fabric/itsmine/Claim.java +++ /dev/null @@ -1,484 +0,0 @@ -package io.github.indicode.fabric.itsmine; - -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.arguments.BoolArgumentType; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.context.CommandContext; -import io.github.indicode.fabric.permissions.Thimble; -import net.minecraft.nbt.*; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.dimension.DimensionType; - -import java.util.*; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -/** - * @author Indigo Amann - */ -public class Claim { - public String name; - public BlockPos min, max; - public DimensionType dimension; - public List children = new ArrayList<>(); - public ClaimSettings settings = new ClaimSettings(); - public PermissionManager permissionManager = new PermissionManager(); - public UUID claimBlockOwner = null; - public Claim() { - - } - public Claim(CompoundTag tag) { - fromTag(tag); - } - public Claim(String name, UUID claimBlockOwner, BlockPos min, BlockPos max, DimensionType dimension) { - this.claimBlockOwner = claimBlockOwner; - this.min = min; - this.max = max; - this.name = name; - this.dimension = dimension; - } - public boolean includesPosition(BlockPos pos) { - return pos.getX() >= min.getX() && pos.getY() >= min.getY() && pos.getZ() >= min.getZ() && - pos.getX() <= max.getX() && pos.getY() <= max.getY() && pos.getZ() <= max.getZ(); - } - public boolean intersects(Claim claim) { - return intersects(claim, true); - } - public boolean intersects(Claim claim, boolean checkOther) { - if (claim == null) return false; - if (!claim.dimension.equals(dimension)) return false; - BlockPos a = min, - b = max, - c = new BlockPos(max.getX(), min.getY(), min.getZ()), - d = new BlockPos(min.getX(), max.getY(), min.getZ()), - e = new BlockPos(min.getX(), min.getY(), max.getZ()), - f = new BlockPos(max.getX(), max.getY(), min.getZ()), - g = new BlockPos(max.getX(), min.getY(), max.getZ()), - h = new BlockPos(min.getX(), max.getY(), max.getZ()); - if ( - claim.includesPosition(a) || - claim.includesPosition(b) || - claim.includesPosition(c) || - claim.includesPosition(d) || - claim.includesPosition(e) || - claim.includesPosition(f) || - claim.includesPosition(g) || - claim.includesPosition(h) - ) return true; - else return checkOther && claim.intersects(this, false); - } - public Claim getZoneCovering(BlockPos pos) { - if (includesPosition(pos)) { - for (Claim child : children) { - Claim value = child.getZoneCovering(pos); - if (value != null) return value; - } - return this; - } else return null; - } - /*public ClaimSettings getSettingsAt(BlockPos pos) { - Claim at = getZoneCovering(pos); - if (at != null) { - return at.settings; - } else return settings; - } - public ClaimPermissions getPermissionsAt(UUID player, BlockPos pos) { - Claim at = getZoneCovering(pos); - if (at != null) { - return at.getPlayerPermissions(player); - } else return settings; - }*/ - public boolean hasPermission(UUID player, Permission permission) { - return ClaimManager.INSTANCE.ignoringClaims.contains(player) || permissionManager.hasPermission(player, permission); - } - //public boolean hasPermissionAt(UUID player, ClaimPermissions.Permission permission, BlockPos pos) { - // return player.equals(owner) || ClaimManager.INSTANCE.ignoringClaims.contains(player) || getPermissionsAt(player, pos).hasPermission(permission); - //} - public void addSubzone(Claim claim) { - if (claim != null && claim.dimension == dimension && includesPosition(claim.min) && includesPosition(claim.max)) { - children.add(claim); - } else throw new IllegalArgumentException("Subzone must be inside the original claim, in the same dimension, and not null"); - } - public void expand(BlockPos min, BlockPos max) { - this.min = this.min.add(min); - this.max = this.max.add(max); - } - public BlockPos getSize() { - return max.subtract(min); - } - public void expand(BlockPos modifier) { - if (modifier.getX() > 0) max = max.add(modifier.getX(), 0, 0); - else min = min.add(modifier.getX(), 0, 0); - if (modifier.getY() > 0) max = max.add(0, modifier.getY(), 0); - else min = min.add(0, modifier.getY(), 0); - if (modifier.getZ() > 0) max = max.add(0, 0, modifier.getZ()); - else min = min.add(0, 0, modifier.getZ()); - } - public boolean shrink(BlockPos modifier) { - if (modifier.getX() < 0) { - if (min.getX() - modifier.getX() > max.getX()) return false; - min = min.add(-modifier.getX(), 0, 0); - } else { - if (max.getX() - modifier.getX() < min.getX()) return false; - max = max.add(-modifier.getX(), 0, 0); - } - if (modifier.getY() < 0) { - if (min.getY() - modifier.getY() > max.getY()) return false; - min = min.add(0, -modifier.getY(), 0); - } else { - if (max.getY() - modifier.getY() < min.getY()) return false; - max = max.add(0, -modifier.getY(), 0); - } - if (modifier.getZ() < 0) { - if (min.getZ() - modifier.getZ() > max.getZ()) return false; - min = min.add(0, 0, -modifier.getZ()); - } else { - if (max.getZ() - modifier.getZ() < min.getZ()) return false; - max = max.add(0, 0, -modifier.getZ()); - } - return true; - } - public void expand(Direction direction, int distance) { - expand(new BlockPos(direction.getOffsetX() * distance, direction.getOffsetY() * distance, direction.getOffsetZ() * distance)); - } - public boolean shrink(Direction direction, int distance) { - return shrink(new BlockPos(direction.getOffsetX() * distance, direction.getOffsetY() * distance, direction.getOffsetZ() * distance)); - } - public int getArea() { - return getSize().getX() * (Config.claims2d ? 1 : getSize().getY()) * getSize().getZ(); - } - public CompoundTag toTag() { - CompoundTag tag = new CompoundTag(); - { - CompoundTag pos = new CompoundTag(); - pos.putInt("minX", min.getX()); - pos.putInt("minY", min.getY()); - pos.putInt("minZ", min.getZ()); - pos.putInt("maxX", max.getX()); - pos.putInt("maxY", max.getY()); - pos.putInt("maxZ", max.getZ()); - pos.putString("dimension", DimensionType.getId(dimension).toString()); - tag.put("position", pos); - } - { - ListTag subzoneList = new ListTag(); - children.forEach(it -> subzoneList.add(it.toTag())); - tag.put("subzones", subzoneList); - } - { - tag.put("settings", settings.toTag()); - tag.put("permissions", permissionManager.toNBT()); - if (claimBlockOwner != null) tag.putUuid("top_owner", claimBlockOwner); - } - tag.putString("name", name); - return tag; - } - public void fromTag(CompoundTag tag) { - { - CompoundTag pos = tag.getCompound("position"); - int minX = pos.getInt("minX"); - int minY = pos.getInt("minY"); - int minZ = pos.getInt("minZ"); - int maxX = pos.getInt("maxX"); - int maxY = pos.getInt("maxY"); - int maxZ = pos.getInt("maxZ"); - if (maxY == 0) maxY = 255; - this.min = new BlockPos(minX, minY, minZ); - this.max = new BlockPos(maxX, maxY, maxZ); - this.dimension = DimensionType.byId(new Identifier(pos.getString("dimension"))); - } - { - children = new ArrayList<>(); - ListTag subzoneList = (ListTag) tag.get("subzones"); - if (subzoneList != null) { - subzoneList.forEach(it -> children.add(new Claim((CompoundTag) it))); - } - } - { - this.settings = new ClaimSettings(tag.getCompound("settings")); - permissionManager = new PermissionManager(); - permissionManager.fromNBT(tag.getCompound("permissions")); - if (tag.containsUuid("top_owner")) claimBlockOwner = tag.getUuid("top_owner"); - } - name = tag.getString("name"); - } - - public boolean is2d() { - return min.getY() == 0 && max.getY() == 255; - } - - public enum Permission { - //Admin - DELETE_CLAIM("delete_claim", "Delete Claim"), - MODIFY_SIZE("modify_size", "Modify Claim Size"), - CHANGE_FLAGS("modify_flags", "Change Claim Flags"), - CHANGE_PERMISSIONS("modify_permissions", "Change Permissions"), - //Normal - SPAWN_PROTECT("spawn_protect", "Spawn Protection Bypass"), - PLACE_BREAK("place_break", "Place/Break Blocks"), - ACTIVATE_BLOCKS("block_interact", "Right click Blocks"), - USE_ITEMS_ON_BLOCKS("use_block_modifier_items", "Use Block Modifying items"), - PRESS_BUTTONS("press_buttons", "Press Buttons"), - USE_LEVERS("use_levers", "Use Levers"), - OPEN_DOORS("open_doors", "Use Doors"), - ENTITY_INTERACT("entity_interact", "Entity Interaction"), - ENTITY_DAMAGE("entity_damage", "Hurt Entities"), - FLY("fly", "Fly"); - String id, name; - Permission(String id, String name) { - this.id = id; - this.name = name; - } - public static Permission byId(String id) { - for (Permission permission: values()) { - if (permission.id.equals(id)) return permission; - } - return null; - } - } - public static class PermissionManager { - public ClaimPermissionMap defaults = new DefaultPermissionMap(); - protected Map playerPermissions = new HashMap<>(); - protected Map groupPermissions = new HashMap<>(); - public boolean isPermissionSet(UUID player, Permission permission) { - return playerPermissions.get(player) != null && playerPermissions.get(player).isPermissionSet(permission); - } - public boolean hasPermission(UUID player, Permission permission) { - if (isPermissionSet(player, permission)) return playerPermissions.get(player).hasPermission(permission); - for (Map.Entry entry : groupPermissions.entrySet()) { - if (Thimble.PERMISSIONS.hasPermission(entry.getKey(), player) && entry.getValue().hasPermission(permission)) return true; - } - return defaults.hasPermission(permission); - } - public void setPermission(UUID player, Permission permission, boolean enabled) { - if (!playerPermissions.containsKey(player)) playerPermissions.put(player, new DefaultPermissionMap()); - playerPermissions.get(player).setPermission(permission, enabled); - } - public void clearPermission(UUID player, Permission permission) { - if (!playerPermissions.containsKey(player)) playerPermissions.put(player, new DefaultPermissionMap()); - playerPermissions.get(player).clearPermission(permission); - } - public void resetPermissions(UUID player) { - playerPermissions.remove(player); - } - public boolean isPermissionSet(String group, Permission permission) { - return groupPermissions.get(group) != null && groupPermissions.get(group).isPermissionSet(permission); - } - public boolean hasPermission(String group, Permission permission) { - if (isPermissionSet(group, permission)) return groupPermissions.get(group).hasPermission(permission); - return defaults.hasPermission(permission); - } - public void setPermission(String group, Permission permission, boolean enabled) { - if (!groupPermissions.containsKey(group)) groupPermissions.put(group, new DefaultPermissionMap()); - groupPermissions.get(group).setPermission(permission, enabled); - } - public void clearPermission(String group, Permission permission) { - if (!groupPermissions.containsKey(group)) groupPermissions.put(group, new DefaultPermissionMap()); - groupPermissions.get(group).clearPermission(permission); - } - public void resetPermissions(String group) { - groupPermissions.remove(group); - } - public CompoundTag toNBT() { - CompoundTag tag = new CompoundTag(); - tag.put("defaults", defaults.toRegisteredNBT()); - { - CompoundTag players = new CompoundTag(); - if (playerPermissions != null) playerPermissions.forEach((player, map) -> {if (player != null && map != null) players.put(player.toString(), map.toRegisteredNBT());}); - tag.put("players", players); - } - { - CompoundTag groups = new CompoundTag(); - groupPermissions.forEach((group, map) -> groups.put(group, map.toRegisteredNBT())); - tag.put("groups", groups); - } - return tag; - } - public void fromNBT(CompoundTag tag) { - defaults = ClaimPermissionMap.fromRegisteredNBT(tag.getCompound("defaults")); - { - CompoundTag players = tag.getCompound("players"); - playerPermissions.clear(); - players.getKeys().forEach(player -> playerPermissions.put(UUID.fromString(player), ClaimPermissionMap.fromRegisteredNBT(players.getCompound(player)))); - } - { - CompoundTag groups = tag.getCompound("groups"); - groupPermissions.clear(); - groups.getKeys().forEach(group -> groupPermissions.put(group, ClaimPermissionMap.fromRegisteredNBT(groups.getCompound(group)))); - } - } - } - public static abstract class ClaimPermissionMap { - protected static HashMap> mapTypes = new HashMap<>(); - protected static HashMap, String> reverseMapTypes = new HashMap<>(); - static { - mapTypes.put("default", DefaultPermissionMap.class); - reverseMapTypes.put(DefaultPermissionMap.class, "default"); - mapTypes.put("inverted", InvertedPermissionMap.class); - reverseMapTypes.put(InvertedPermissionMap.class, "inverted"); - } - public abstract boolean isPermissionSet(Permission permission); - public abstract boolean hasPermission(Permission permission); - public abstract void setPermission(Permission permission, boolean has); - public abstract void clearPermission(Permission permission); - public abstract void fromNBT(CompoundTag tag); - public abstract CompoundTag toNBT(); - public CompoundTag toRegisteredNBT() { - CompoundTag tag = toNBT(); - tag.putString("type", reverseMapTypes.get(this.getClass())); - return tag; - } - public static ClaimPermissionMap fromRegisteredNBT(CompoundTag tag) { - String type = tag.getString("type"); - tag.remove("type"); - Class clazz = mapTypes.get(type); - if (clazz == null) return new DefaultPermissionMap(); - try { - ClaimPermissionMap map = clazz.newInstance(); - map.fromNBT(tag); - return map; - } catch (InstantiationException | IllegalAccessException e) { - e.printStackTrace(); - } - return null; - } - } - public static class DefaultPermissionMap extends ClaimPermissionMap { - private HashMap permissions = new HashMap<>(); - @Override - public boolean isPermissionSet(Permission permission) { - return permissions.containsKey(permission); - } - - @Override - public boolean hasPermission(Permission permission) { - return isPermissionSet(permission) && permissions.get(permission); - } - - @Override - public void setPermission(Permission permission, boolean has) { - permissions.put(permission, has); - } - - @Override - public void clearPermission(Permission permission) { - permissions.remove(permission); - } - - @Override - public void fromNBT(CompoundTag tag) { - permissions.clear(); - for (String permissionString : tag.getKeys()) { - Permission permission = Permission.byId(permissionString); - if (permission == null) continue; - boolean allowed = tag.getBoolean(permissionString); - permissions.put(permission, allowed); - } - } - - @Override - public CompoundTag toNBT() { - CompoundTag tag = new CompoundTag(); - permissions.forEach((permission, allowed) -> { - if (allowed != null) tag.putBoolean(permission.id, allowed); - }); - return tag; - } - } - public static class InvertedPermissionMap extends ClaimPermissionMap { - - private HashMap permissions = new HashMap<>(); - @Override - public boolean isPermissionSet(Permission permission) { - return true; - } - - @Override - public boolean hasPermission(Permission permission) { - return !permissions.containsKey(permission) || permissions.get(permission); - } - - @Override - public void setPermission(Permission permission, boolean has) { - permissions.put(permission, has); - } - - @Override - public void clearPermission(Permission permission) { - permissions.remove(permission); - } - - @Override - public void fromNBT(CompoundTag tag) { - permissions.clear(); - for (String permissionString : tag.getKeys()) { - Permission permission = Permission.byId(permissionString); - if (permission == null) continue; - boolean allowed = tag.getBoolean(permissionString); - permissions.put(permission, allowed); - } - } - - @Override - public CompoundTag toNBT() { - CompoundTag tag = new CompoundTag(); - permissions.forEach((permission, allowed) -> { - if (allowed != null) tag.putBoolean(permission.id, allowed); - }); - return tag; - } - } - public static class ClaimSettings{ - public enum Setting { - FLIGHT_ALLOWED("fly_enabled", "Flying Enabled", true), - EXPLOSIONS("explosion_destruction", "Explosions Destroy Blocks", false), - FLUID_CROSSES_BORDERS("fluid_crosses_borders", "Fluid Crosses Borders", false), - FIRE_CROSSES_BORDERS("fire_crosses_borders", "Fire Crosses Borders", false), - PISTON_FROM_INSIDE("pistons_inside_border", "Pistons Cross border from Inside", true), - PISTON_FROM_OUTSIDE("pistons_outside_border", "Pistons Cross border from Outside", false), - MOB_SPAWNING("mob_spawn", "Natural mob spawning", true); - - String id, name; - boolean defaultValue; - Setting(String id, String name, boolean defaultValue) { - this.id = id; - this.name = name; - this.defaultValue = defaultValue; - } - public static ClaimSettings.Setting byId(String id) { - for (ClaimSettings.Setting permission: values()) { - if (permission.id.equals(id)) return permission; - } - return null; - } - } - public Map settings = new HashMap<>(); - public ClaimSettings(CompoundTag tag) { - fromTag(tag); - } - public ClaimSettings() { - } - public boolean getSetting(Setting setting) { - return settings.getOrDefault(setting, setting.defaultValue); - } - public CompoundTag toTag() { - CompoundTag tag = new CompoundTag(); - this.settings.forEach((setting, data) -> { - tag.putBoolean(setting.id, data); - }); - return tag; - } - public void fromTag(CompoundTag tag) { - settings.clear(); - tag.getKeys().forEach(key -> { - Setting setting = Setting.byId(key); - if (setting == null) return; - this.settings.put(setting, tag.getBoolean(key)); - }); - } - } -} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/ClaimCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/ClaimCommand.java deleted file mode 100644 index fe8b142..0000000 --- a/src/main/java/io/github/indicode/fabric/itsmine/ClaimCommand.java +++ /dev/null @@ -1,994 +0,0 @@ -package io.github.indicode.fabric.itsmine; - -import com.mojang.authlib.GameProfile; -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.arguments.BoolArgumentType; -import com.mojang.brigadier.arguments.IntegerArgumentType; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.builder.ArgumentBuilder; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.suggestion.SuggestionProvider; -import io.github.indicode.fabric.itsmine.mixin.BlockUpdatePacketMixin; -import io.github.indicode.fabric.permissions.Thimble; -import io.github.indicode.fabric.permissions.command.PermissionCommand; -import io.github.voidpointerdev.minecraft.offlineinfo.OfflineInfo; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.command.CommandException; -import net.minecraft.command.EntitySelector; -import net.minecraft.command.arguments.BlockPosArgumentType; -import net.minecraft.command.arguments.EntityArgumentType; -import net.minecraft.command.arguments.PosArgument; -import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.command.CommandManager; -import net.minecraft.server.command.CommandSource; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.ClickEvent; -import net.minecraft.text.HoverEvent; -import net.minecraft.text.LiteralText; -import net.minecraft.text.Style; -import net.minecraft.util.Formatting; -import net.minecraft.util.Pair; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; - -import java.util.*; -import java.util.concurrent.atomic.AtomicReference; - -/** - * @author Indigo Amann - */ -public class ClaimCommand { - public static final SuggestionProvider DIRECTION_SUGGESTION_BUILDER = (source, builder) -> { - for (Direction direction: Direction.values()) { - builder.suggest(direction.getName()); - }; - return builder.buildFuture(); - }; - public static final SuggestionProvider CLAIM_PROVIDER = (source, builder) -> { - List claims = ClaimManager.INSTANCE.getPlayerClaims(source.getSource().getPlayer().getGameProfile().getId()); - List names = new ArrayList<>(); - for (Claim claim : claims) { - names.add(claim.name); - } - CommandSource.suggestMatching(names, builder); - return builder.buildFuture(); - }; - public static void register(CommandDispatcher dispatcher) { - LiteralArgumentBuilder command = CommandManager.literal("claim"); - { - LiteralArgumentBuilder create = CommandManager.literal("create"); - RequiredArgumentBuilder name = CommandManager.argument("name", StringArgumentType.word()); - - name.executes(context -> { - ServerPlayerEntity player = context.getSource().getPlayer(); - Pair selectedPositions = ClaimManager.INSTANCE.stickPositions.get(player); - if (selectedPositions == null) { - context.getSource().sendFeedback(new LiteralText("You need to specify block positions or select them with a stick.").formatted(Formatting.RED), false); - } else if (selectedPositions.getLeft() == null) { - context.getSource().sendFeedback(new LiteralText("You need to specify block positions or select position #1(Right Click) with a stick.").formatted(Formatting.RED), false); - } else if (selectedPositions.getRight() == null) { - context.getSource().sendFeedback(new LiteralText("You need to specify block positions or select position #2(Left Click) with a stick.").formatted(Formatting.RED), false); - } else { - String cname = StringArgumentType.getString(context, "name"); - if (createClaim(cname, context.getSource(), selectedPositions.getLeft(), selectedPositions.getRight(), false) > 0) { - ClaimManager.INSTANCE.stickPositions.remove(player); - } - } - return 0; - }); - - ArgumentBuilder min = CommandManager.argument("min", BlockPosArgumentType.blockPos()); - RequiredArgumentBuilder max = CommandManager.argument("max", BlockPosArgumentType.blockPos()); - max.executes(context -> createClaim( - StringArgumentType.getString(context, "name"), - context.getSource(), - BlockPosArgumentType.getBlockPos(context, "min"), - BlockPosArgumentType.getBlockPos(context, "max"), - false - )); - min.then(max); - name.then(min); - create.then(name); - command.then(create); - } - { - LiteralArgumentBuilder stick = CommandManager.literal("stick"); - stick.executes(context -> { - Pair posPair = ClaimManager.INSTANCE.stickPositions.get(context.getSource().getPlayer()); - context.getSource().sendFeedback(new LiteralText(posPair == null ? "You can now use a stick to create claims. Run this command again to disable" : "Claim stick disabled. Run this command again to enable").formatted(Formatting.DARK_PURPLE), false); - if (posPair == null) { - ClaimManager.INSTANCE.stickPositions.put(context.getSource().getPlayer(), new Pair<>(null, null)); - } else { - ClaimManager.INSTANCE.stickPositions.remove(context.getSource().getPlayer()); - } - return 0; - }); - command.then(stick); - } - { - LiteralArgumentBuilder show = CommandManager.literal("show"); - show.executes(context -> showClaim(context.getSource(), ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getSenseCenterPos(), context.getSource().getWorld().dimension.getType()), false)); - RequiredArgumentBuilder name = CommandManager.argument("name", StringArgumentType.word()); - name.suggests(CLAIM_PROVIDER); - name.executes(context -> showClaim(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "name")), false)); - show.then(name); - command.then(show); - } - { - LiteralArgumentBuilder hide = CommandManager.literal("hide"); - hide.executes(context -> showClaim(context.getSource(), null, true)); - command.then(hide); - } - { - LiteralArgumentBuilder check = CommandManager.literal("check_blocks"); - RequiredArgumentBuilder other = CommandManager.argument("player", EntityArgumentType.player()); - other.requires(source -> Thimble.hasPermissionOrOp(source, "itsmine.checkothers", 2)); - other.executes(ctx -> checkPlayer(ctx.getSource(), EntityArgumentType.getPlayer(ctx, "player").getGameProfile().getId())); - check.then(other); - check.executes(ctx -> checkPlayer(ctx.getSource(), ctx.getSource().getPlayer().getGameProfile().getId())); - command.then(check); - } - { - LiteralArgumentBuilder delete = CommandManager.literal("destroy"); - RequiredArgumentBuilder claim = CommandManager.argument("claim", StringArgumentType.word()); - claim.suggests(CLAIM_PROVIDER); - LiteralArgumentBuilder confirm = CommandManager.literal("confirm"); - confirm.executes(context -> delete(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")), false)); - claim.executes(context -> requestDelete(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")), false)); - claim.then(confirm); - delete.then(claim); - delete.executes(context -> requestDelete(context.getSource(), ClaimManager.INSTANCE.getClaimAt(new BlockPos(context.getSource().getPosition()), context.getSource().getWorld().getDimension().getType()), false)); - command.then(delete); - } - { - { - LiteralArgumentBuilder expand = CommandManager.literal("expand"); - RequiredArgumentBuilder amount = CommandManager.argument("distance", IntegerArgumentType.integer(1, Integer.MAX_VALUE)); - RequiredArgumentBuilder direction = CommandManager.argument("direction", StringArgumentType.word()); - direction.suggests(DIRECTION_SUGGESTION_BUILDER); - - direction.executes(context -> expand( - ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getSenseCenterPos(), context.getSource().getWorld().getDimension().getType()), - IntegerArgumentType.getInteger(context, "distance"), - directionByName(StringArgumentType.getString(context, "direction")), - context.getSource(), - false - )); - - amount.executes(context -> expand( - ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getSenseCenterPos(), context.getSource().getWorld().getDimension().getType()), - IntegerArgumentType.getInteger(context, "distance"), - Direction.getEntityFacingOrder(context.getSource().getPlayer())[0], - context.getSource(), - false - )); - - amount.then(direction); - expand.then(amount); - command.then(expand); - } - { - LiteralArgumentBuilder shrink = CommandManager.literal("shrink"); - RequiredArgumentBuilder amount = CommandManager.argument("distance", IntegerArgumentType.integer(1, Integer.MAX_VALUE)); - RequiredArgumentBuilder direction = CommandManager.argument("direction", StringArgumentType.word()); - direction.suggests(DIRECTION_SUGGESTION_BUILDER); - - direction.executes(context -> expand( - ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getSenseCenterPos(), context.getSource().getWorld().getDimension().getType()), - -IntegerArgumentType.getInteger(context, "distance"), - directionByName(StringArgumentType.getString(context, "direction")), - context.getSource(), - false - )); - - amount.executes(context -> expand( - ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getSenseCenterPos(), context.getSource().getWorld().getDimension().getType()), - -IntegerArgumentType.getInteger(context, "distance"), - Direction.getEntityFacingOrder(context.getSource().getPlayer())[0], - context.getSource(), - false - )); - - amount.then(direction); - shrink.then(amount); - command.then(shrink); - } - } - { - LiteralArgumentBuilder delete = CommandManager.literal("destroy"); - RequiredArgumentBuilder claim = CommandManager.argument("claim", StringArgumentType.word()); - claim.suggests(CLAIM_PROVIDER); - LiteralArgumentBuilder confirm = CommandManager.literal("confirm"); - confirm.executes(context -> delete(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")), false)); - claim.executes(context -> requestDelete(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")), false)); - claim.then(confirm); - delete.then(claim); - delete.executes(context -> requestDelete(context.getSource(), ClaimManager.INSTANCE.getClaimAt(new BlockPos(context.getSource().getPosition()), context.getSource().getWorld().getDimension().getType()), false)); - command.then(delete); - } - { - LiteralArgumentBuilder transfer = CommandManager.literal("transfer"); - RequiredArgumentBuilder claim = CommandManager.argument("claim", StringArgumentType.word()); - claim.suggests(CLAIM_PROVIDER); - RequiredArgumentBuilder player = CommandManager.argument("player", EntityArgumentType.player()); - LiteralArgumentBuilder confirm = CommandManager.literal("confirm"); - confirm.executes(context -> transfer(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")), EntityArgumentType.getPlayer(context, "player"), false)); - player.executes(context -> requestTransfer(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")), EntityArgumentType.getPlayer(context, "player"), false)); - player.then(confirm); - claim.then(player); - transfer.then(claim); - transfer.executes(context -> requestTransfer(context.getSource(), ClaimManager.INSTANCE.getClaimAt(new BlockPos(context.getSource().getPosition()), context.getSource().getWorld().getDimension().getType()), EntityArgumentType.getPlayer(context, "player"), false)); - command.then(transfer); - } - { - LiteralArgumentBuilder transfer = CommandManager.literal("accept_transfer"); - RequiredArgumentBuilder claim = CommandManager.argument("claim", StringArgumentType.word()); - claim.suggests(CLAIM_PROVIDER); - claim.executes(context -> acceptTransfer(context.getSource())); - transfer.then(claim); - command.then(transfer); - } - { - LiteralArgumentBuilder info = CommandManager.literal("info"); - RequiredArgumentBuilder claim = CommandManager.argument("claim", StringArgumentType.word()); - claim.suggests(CLAIM_PROVIDER); - info.executes(context -> info( - context.getSource(), - ClaimManager.INSTANCE.getClaimAt(new BlockPos(context.getSource().getPosition()), context.getSource().getWorld().getDimension().getType()) - )); - claim.executes(context -> info( - context.getSource(), - ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")) - )); - info.then(claim); - command.then(info); - } - { - LiteralArgumentBuilder list = CommandManager.literal("list"); - RequiredArgumentBuilder player = CommandManager.argument("player", StringArgumentType.word()); - player.requires(source -> Thimble.hasPermissionOrOp(source, "itsmine.check_others", 2)); - player.suggests(OfflineInfo.ONLINE_PROVIDER); - list.executes(context -> list(context.getSource(), null)); - player.executes(context -> list(context.getSource(), StringArgumentType.getString(context, "player"))); - list.then(player); - command.then(list); - } - createExceptionCommand(command, false); - { - LiteralArgumentBuilder settings = CommandManager.literal("flags"); - RequiredArgumentBuilder claim = CommandManager.argument("claim", StringArgumentType.word()); - claim.suggests(CLAIM_PROVIDER); - for (Claim.ClaimSettings.Setting setting: Claim.ClaimSettings.Setting.values()) { - LiteralArgumentBuilder arg = CommandManager.literal(setting.id); - arg.executes(context -> { - Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")); - if (claim1 == null) { - context.getSource().sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); - return 0; - } - if (!claim1.permissionManager.hasPermission(context.getSource().getPlayer().getGameProfile().getId(), Claim.Permission.CHANGE_FLAGS)) { - context.getSource().sendFeedback(new LiteralText("You cannot change flags in this claim").formatted(Formatting.RED), false); - return 0; - } - context.getSource().sendFeedback(new LiteralText(setting.name + " is equal to " + claim1.settings.settings.get(setting)).formatted(Formatting.YELLOW), false); - return 0; - }); - RequiredArgumentBuilder setter = CommandManager.argument("value", BoolArgumentType.bool()); - setter.executes(context -> { - Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")); - if (claim1 == null) { - context.getSource().sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); - return 0; - } - if (!claim1.permissionManager.hasPermission(context.getSource().getPlayer().getGameProfile().getId(), Claim.Permission.CHANGE_FLAGS)) { - context.getSource().sendFeedback(new LiteralText("You cannot change flags in this claim").formatted(Formatting.RED), false); - return 0; - } - claim1.settings.settings.put(setting, BoolArgumentType.getBool(context, "value")); - context.getSource().sendFeedback(new LiteralText(setting.name + " is now equal to " + BoolArgumentType.getBool(context, "value")).formatted(Formatting.GREEN), false); - return 0; - }); - arg.then(setter); - claim.then(arg); - } - for (Claim.Permission value : Claim.Permission.values()) { - LiteralArgumentBuilder permNode = CommandManager.literal(value.id); - RequiredArgumentBuilder allow = CommandManager.argument("allow", BoolArgumentType.bool()); - allow.executes(context -> { - Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")); - if (claim1 == null) { - context.getSource().sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); - return 0; - } - if (!claim1.permissionManager.hasPermission(context.getSource().getPlayer().getGameProfile().getId(), Claim.Permission.CHANGE_FLAGS)) { - context.getSource().sendFeedback(new LiteralText("You cannot change flags in this claim").formatted(Formatting.RED), false); - return 0; - } - boolean permission = BoolArgumentType.getBool(context, "allow"); - claim1.permissionManager.defaults.setPermission(value, permission); - context.getSource().sendFeedback(new LiteralText("Players" + (permission ? " now" : " no longer") + " have the permission " + value.name).formatted(Formatting.YELLOW), false); - return 0; - }); - permNode.executes(context -> { - Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")); - if (claim1 == null) { - context.getSource().sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); - return 0; - } - if (!claim1.permissionManager.hasPermission(context.getSource().getPlayer().getGameProfile().getId(), Claim.Permission.CHANGE_FLAGS)) { - context.getSource().sendFeedback(new LiteralText("You cannot change flags in this claim").formatted(Formatting.RED), false); - return 0; - } - boolean permission = claim1.permissionManager.defaults.hasPermission(value); - context.getSource().sendFeedback(new LiteralText("Players" + (permission ? " do" : " does not") + " have the permission " + value.name).formatted(Formatting.YELLOW), false); - return 0; - }); - permNode.then(allow); - claim.then(permNode); - } - settings.then(claim); - command.then(settings); - } - { - LiteralArgumentBuilder admin = CommandManager.literal("admin"); - //admin.requires(source -> Thimble.hasPermissionChildOrOp(source, "itsmine.admin", 4)); - { - LiteralArgumentBuilder add = CommandManager.literal("add_blocks"); - add.requires(source -> Thimble.hasPermissionOrOp(source, "itsmine.admin.modify_balance", 2)); - RequiredArgumentBuilder player = CommandManager.argument("player", EntityArgumentType.players()); - RequiredArgumentBuilder amount = CommandManager.argument("amount", IntegerArgumentType.integer()); - amount.executes(context -> { - ClaimManager.INSTANCE.addClaimBlocks(EntityArgumentType.getPlayers(context, "player"), IntegerArgumentType.getInteger(context, "amount")); - context.getSource().sendFeedback(new LiteralText("Gave " + IntegerArgumentType.getInteger(context, "amount") + " claim blocks").formatted(Formatting.GREEN), true); - return 0; - }); - player.then(amount); - add.then(player); - admin.then(add); - } - { - LiteralArgumentBuilder remove = CommandManager.literal("remove_blocks"); - remove.requires(source -> Thimble.hasPermissionOrOp(source, "itsmine.admin.modify_balance", 2)); - RequiredArgumentBuilder player = CommandManager.argument("player", EntityArgumentType.players()); - RequiredArgumentBuilder amount = CommandManager.argument("amount", IntegerArgumentType.integer()); - amount.executes(context -> { - ClaimManager.INSTANCE.addClaimBlocks(EntityArgumentType.getPlayers(context, "player"), -IntegerArgumentType.getInteger(context, "amount")); - context.getSource().sendFeedback(new LiteralText("Took " + IntegerArgumentType.getInteger(context, "amount") + " claim blocks").formatted(Formatting.GREEN), true); - return 0; - }); - player.then(amount); - remove.then(player); - admin.then(remove); - } - { - LiteralArgumentBuilder set = CommandManager.literal("set_blocks"); - set.requires(source -> Thimble.hasPermissionOrOp(source, "itsmine.admin.modify_balance", 2)); - RequiredArgumentBuilder player = CommandManager.argument("player", EntityArgumentType.players()); - RequiredArgumentBuilder amount = CommandManager.argument("amount", IntegerArgumentType.integer()); - amount.executes(context -> { - ClaimManager.INSTANCE.setClaimBlocks(EntityArgumentType.getPlayers(context, "player"), IntegerArgumentType.getInteger(context, "amount")); - context.getSource().sendFeedback(new LiteralText("Set claim block amount to " + IntegerArgumentType.getInteger(context, "amount")).formatted(Formatting.GREEN), true); - return 0; - }); - player.then(amount); - set.then(player); - admin.then(set); - } - { - LiteralArgumentBuilder delete = CommandManager.literal("destroy"); - delete.requires(source -> Thimble.hasPermissionOrOp(source, "itsmine.admin.modify", 4)); - RequiredArgumentBuilder claim = CommandManager.argument("claim", StringArgumentType.word()); - claim.suggests(CLAIM_PROVIDER); - LiteralArgumentBuilder confirm = CommandManager.literal("confirm"); - confirm.executes(context -> delete(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")), true)); - claim.executes(context -> requestDelete(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")), true)); - claim.then(confirm); - delete.then(claim); - delete.executes(context -> requestDelete(context.getSource(), ClaimManager.INSTANCE.getClaimAt(new BlockPos(context.getSource().getPosition()), context.getSource().getWorld().getDimension().getType()), true)); - admin.then(delete); - } - { - LiteralArgumentBuilder create = CommandManager.literal("create"); - create.requires(source -> Thimble.hasPermissionOrOp(source, "itsmine.admin.infinite_claim", 4)); - ArgumentBuilder name = CommandManager.argument("name", StringArgumentType.word()); - ArgumentBuilder min = CommandManager.argument("min", BlockPosArgumentType.blockPos()); - RequiredArgumentBuilder max = CommandManager.argument("max", BlockPosArgumentType.blockPos()); - max.executes(context -> createClaim( - StringArgumentType.getString(context, "name"), - context.getSource(), - BlockPosArgumentType.getBlockPos(context, "min"), - BlockPosArgumentType.getBlockPos(context, "max"), - true - )); - min.then(max); - name.then(min); - create.then(name); - admin.then(create); - } - { - LiteralArgumentBuilder ignore = CommandManager.literal("ignore_claims"); - ignore.requires(source -> Thimble.hasPermissionOrOp(source, "itsmine.admin.ignore_claims", 4)); - ignore.executes(context -> { - UUID id = context.getSource().getPlayer().getGameProfile().getId(); - boolean isIgnoring = ClaimManager.INSTANCE.ignoringClaims.contains(id); - if (isIgnoring) ClaimManager.INSTANCE.ignoringClaims.remove(id); - else ClaimManager.INSTANCE.ignoringClaims.add(id); - context.getSource().sendFeedback(new LiteralText("You are " + (isIgnoring ? "no longer" : "now") + " ignoring claims.").formatted(Formatting.GREEN), false); - return 0; - }); - admin.then(ignore); - } - { - { - LiteralArgumentBuilder expand = CommandManager.literal("expand"); - expand.requires(source -> Thimble.hasPermissionOrOp(source, "itsmine.admin.infinite_claim", 4) && Thimble.hasPermissionOrOp(source, "itsmine.admin.modify", 4)); - RequiredArgumentBuilder amount = CommandManager.argument("distance", IntegerArgumentType.integer(1, Integer.MAX_VALUE)); - RequiredArgumentBuilder direction = CommandManager.argument("direction", StringArgumentType.word()); - direction.suggests(DIRECTION_SUGGESTION_BUILDER); - - direction.executes(context -> expand( - ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getSenseCenterPos(), context.getSource().getWorld().getDimension().getType()), - IntegerArgumentType.getInteger(context, "distance"), - directionByName(StringArgumentType.getString(context, "direction")), - context.getSource(), - true - )); - - amount.executes(context -> expand( - ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getSenseCenterPos(), context.getSource().getWorld().getDimension().getType()), - IntegerArgumentType.getInteger(context, "distance"), - Direction.getEntityFacingOrder(context.getSource().getPlayer())[0], - context.getSource(), - true - )); - - amount.then(direction); - expand.then(amount); - admin.then(expand); - } - { - LiteralArgumentBuilder shrink = CommandManager.literal("shrink"); - shrink.requires(source -> Thimble.hasPermissionOrOp(source, "itsmine.admin.infinite_claim", 4) && Thimble.hasPermissionOrOp(source, "itsmine.admin.modify", 4)); - RequiredArgumentBuilder amount = CommandManager.argument("distance", IntegerArgumentType.integer(1, Integer.MAX_VALUE)); - RequiredArgumentBuilder direction = CommandManager.argument("direction", StringArgumentType.word()); - direction.suggests(DIRECTION_SUGGESTION_BUILDER); - - direction.executes(context -> expand( - ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getSenseCenterPos(), context.getSource().getWorld().getDimension().getType()), - -IntegerArgumentType.getInteger(context, "distance"), - directionByName(StringArgumentType.getString(context, "direction")), - context.getSource(), - true - )); - - amount.executes(context -> expand( - ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getSenseCenterPos(), context.getSource().getWorld().getDimension().getType()), - -IntegerArgumentType.getInteger(context, "distance"), - Direction.getEntityFacingOrder(context.getSource().getPlayer())[0], - context.getSource(), - true - )); - - amount.then(direction); - shrink.then(amount); - admin.then(shrink); - } - } - createExceptionCommand(admin, true); - command.then(admin); - } - dispatcher.register(command); - } - - private static void createExceptionCommand(LiteralArgumentBuilder command, boolean admin) { - LiteralArgumentBuilder exceptions = CommandManager.literal("permissions"); - if (admin) exceptions.requires(source -> Thimble.hasPermissionOrOp(source, "claim.admin.modify_permissions", 2)); - RequiredArgumentBuilder claim = CommandManager.argument("claim", StringArgumentType.word()); - claim.suggests(CLAIM_PROVIDER); - LiteralArgumentBuilder playerLiteral = CommandManager.literal("player"); - { - RequiredArgumentBuilder player = CommandManager.argument("player", EntityArgumentType.player()); - LiteralArgumentBuilder remove = CommandManager.literal("remove"); - remove.executes(context -> { - Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")); - if (verifyPermission(claim1, Claim.Permission.CHANGE_PERMISSIONS, context, admin)) { - ServerPlayerEntity player1 = EntityArgumentType.getPlayer(context, "player"); - claim1.permissionManager.resetPermissions(player1.getGameProfile().getId()); - context.getSource().sendFeedback(new LiteralText(player1.getGameProfile().getName() + " no longer has an exception in the claim").formatted(Formatting.YELLOW), false); - } - return 0; - }); - player.then(remove); - LiteralArgumentBuilder all = CommandManager.literal("*"); - RequiredArgumentBuilder allstate = CommandManager.argument("allow", BoolArgumentType.bool()); - allstate.executes(context -> { - Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")); - if (verifyPermission(claim1, Claim.Permission.CHANGE_PERMISSIONS, context, admin)) { - ServerPlayerEntity player1 = EntityArgumentType.getPlayer(context, "player"); - boolean permission = BoolArgumentType.getBool(context, "allow"); - claim1.permissionManager.playerPermissions.put(player1.getGameProfile().getId(), permission ? new Claim.InvertedPermissionMap() : new Claim.DefaultPermissionMap()); - context.getSource().sendFeedback(new LiteralText(player1.getGameProfile().getName() + (permission ? " now" : " no longer") + " has all the permissions").formatted(Formatting.YELLOW), false); - } - return 0; - }); - all.then(allstate); - player.then(all); - for (Claim.Permission value : Claim.Permission.values()) { - LiteralArgumentBuilder permNode = CommandManager.literal(value.id); - RequiredArgumentBuilder allow = CommandManager.argument("allow", BoolArgumentType.bool()); - allow.executes(context -> { - Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")); - if (verifyPermission(claim1, Claim.Permission.CHANGE_PERMISSIONS, context, admin)) { - ServerPlayerEntity player1 = EntityArgumentType.getPlayer(context, "player"); - boolean permission = BoolArgumentType.getBool(context, "allow"); - modifyException(claim1, player1, value, permission); - context.getSource().sendFeedback(new LiteralText(player1.getGameProfile().getName() + (permission ? " now" : " no longer") + " has the permission " + value.name).formatted(Formatting.YELLOW), false); - } - return 0; - }); - permNode.executes(context -> { - Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")); - if (verifyPermission(claim1, Claim.Permission.CHANGE_PERMISSIONS, context, admin)) { - ServerPlayerEntity player1 = EntityArgumentType.getPlayer(context, "player"); - boolean permission = hasPermission(claim1, player1, value); - context.getSource().sendFeedback(new LiteralText(player1.getGameProfile().getName() + (permission ? " has" : " does not have") + " the permission " + value.name).formatted(Formatting.YELLOW), false); - } - return 0; - }); - permNode.then(allow); - player.then(permNode); - } - playerLiteral.then(player); - } - LiteralArgumentBuilder groupLiteral = CommandManager.literal("group"); - groupLiteral.requires(sender -> Thimble.hasPermissionOrOp(sender, "itsmine.specify_groups", 2)); - { - RequiredArgumentBuilder group = CommandManager.argument("group", StringArgumentType.word()); - group.suggests(PermissionCommand.SUGGESTIONS_BUILDER); - LiteralArgumentBuilder remove = CommandManager.literal("remove"); - remove.executes(context -> { - Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")); - if (verifyPermission(claim1, Claim.Permission.CHANGE_PERMISSIONS, context, admin)) { - String group1 = StringArgumentType.getString(context, "group"); - verifyGroup(group1); - claim1.permissionManager.resetPermissions(group1); - context.getSource().sendFeedback(new LiteralText("Members of " + group1 + " no longer have that exception in the claim").formatted(Formatting.YELLOW), false); - } - return 0; - }); - group.then(remove); - for (Claim.Permission value : Claim.Permission.values()) { - LiteralArgumentBuilder permNode = CommandManager.literal(value.id); - RequiredArgumentBuilder allow = CommandManager.argument("allow", BoolArgumentType.bool()); - allow.executes(context -> { - Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")); - if (verifyPermission(claim1, Claim.Permission.CHANGE_PERMISSIONS, context, admin)) { - String group1 = StringArgumentType.getString(context, "group"); - verifyGroup(group1); - boolean permission = BoolArgumentType.getBool(context, "allow"); - modifyException(claim1, group1, value, permission); - context.getSource().sendFeedback(new LiteralText("Members of " + group1 + (permission ? " now" : " no longer") + " has the permission " + value.name).formatted(Formatting.YELLOW), false); - } - return 0; - }); - permNode.executes(context -> { - Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(StringArgumentType.getString(context, "claim")); - if (verifyPermission(claim1, Claim.Permission.CHANGE_PERMISSIONS, context, admin)) { - String group1 = StringArgumentType.getString(context, "group"); - verifyGroup(group1); - boolean permission = hasPermission(claim1, group1, value); - context.getSource().sendFeedback(new LiteralText("Members of " + group1 + (permission ? " now" : " do not") + " have the permission " + value.name).formatted(Formatting.YELLOW), false); - } - return 0; - }); - permNode.then(allow); - group.then(permNode); - } - groupLiteral.then(group); - } - claim.then(playerLiteral); - claim.then(groupLiteral); - exceptions.then(claim); - command.then(exceptions); - } - private static boolean verifyPermission(Claim claim, Claim.Permission permission, CommandContext context, boolean admin) throws CommandSyntaxException { - if (verifyExists(claim, context)) { - if (claim.permissionManager.hasPermission(context.getSource().getPlayer().getGameProfile().getId(), permission)) { - return true; - } else { - context.getSource().sendFeedback(new LiteralText(admin ? "You are modifying a claim using admin privileges" : "You cannot modify exceptions for this claim").formatted(admin ? Formatting.DARK_RED : Formatting.RED), false); - return admin; - } - } else { - return false; - } - } - private static boolean verifyExists(Claim claim, CommandContext context) { - if (claim == null) { - context.getSource().sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); - return false; - } else { - return true; - } - } - private static void verifyGroup(String permission) { - if (Thimble.PERMISSIONS.permissionExists(permission)) { - throw new CommandException(new LiteralText("Nonexistant permission group").formatted(Formatting.RED)); - } - } - - - private static int showClaim(ServerCommandSource source, Claim claim, boolean reset) throws CommandSyntaxException { - ServerPlayerEntity player = source.getPlayer(); - if (!reset && ((ClaimShower)player).getShownClaim() != null && !(!Config.claims2d &&((ClaimShower)player).getShownClaim() != claim)) showClaim(source, ((ClaimShower)player).getShownClaim(), true); - if (reset && ((ClaimShower)player).getShownClaim() != null) claim = ((ClaimShower)player).getShownClaim(); - if (claim != null) { - if (!claim.dimension.equals(source.getWorld().getDimension().getType())) { - if (claim == ((ClaimShower)player).getShownClaim()) ((ClaimShower)player).setShownClaim(null); // just so we dont have extra packets on this - source.sendFeedback(new LiteralText("That claim is not in this dimension").formatted(Formatting.RED), false); - return 0; - } - source.sendFeedback(new LiteralText((!reset ? "Showing" : "Hiding") + " claim: " + claim.name).formatted(Formatting.GREEN), false); - silentHideShow(player, claim, reset, true); - - } else { - source.sendFeedback(new LiteralText("That is not a valid claim").formatted(Formatting.RED), false); - } - return 0; - } - private static void silentHideShow(ServerPlayerEntity player, Claim claim, boolean hide, boolean updateStatus) { - BlockState block = hide ? null : Blocks.LAPIS_BLOCK.getDefaultState(); - int showRange = 5; - int closeShowRange = 8; - BlockPos pos = hide ? ((ClaimShower)player).getLastShowPos() : player.getSenseCenterPos(); - ((ClaimShower)player).setLastShowPos(pos); - for (int x = claim.min.getX(); x <= claim.min.getX() + showRange; x++) { - sendBlockPacket(player, new BlockPos(x, claim.min.getY(), claim.min.getZ()), block); - sendBlockPacket(player, new BlockPos(x, claim.max.getY(), claim.min.getZ()), block); - sendBlockPacket(player, new BlockPos(x, claim.min.getY(), claim.max.getZ()), block); - sendBlockPacket(player, new BlockPos(x, claim.max.getY(), claim.max.getZ()), block); - } - for (int x = claim.max.getX() - showRange; x <= claim.max.getX(); x++) { - sendBlockPacket(player, new BlockPos(x, claim.min.getY(), claim.min.getZ()), block); - sendBlockPacket(player, new BlockPos(x, claim.max.getY(), claim.min.getZ()), block); - sendBlockPacket(player, new BlockPos(x, claim.min.getY(), claim.max.getZ()), block); - sendBlockPacket(player, new BlockPos(x, claim.max.getY(), claim.max.getZ()), block); - } - if (claim.includesPosition(pos)) for (int x = pos.getX() - closeShowRange; x <= pos.getX() + closeShowRange; x++) { - if (x < claim.min.getX() || x > claim.max.getX()) continue; - sendBlockPacket(player, new BlockPos(x, pos.getY(), claim.min.getZ()), block); - sendBlockPacket(player, new BlockPos(x, pos.getY(), claim.max.getZ()), block); - } - for (int y = claim.min.getY(); y <= claim.min.getY() + showRange; y++) { - sendBlockPacket(player, new BlockPos(claim.min.getX(), y, claim.min.getZ()), block); - sendBlockPacket(player, new BlockPos(claim.max.getX(), y, claim.min.getZ()), block); - sendBlockPacket(player, new BlockPos(claim.min.getX(), y, claim.max.getZ()), block); - sendBlockPacket(player, new BlockPos(claim.max.getX(), y, claim.max.getZ()), block); - } - for (int y = claim.max.getY() - showRange; y <= claim.max.getY(); y++) { - sendBlockPacket(player, new BlockPos(claim.min.getX(), y, claim.min.getZ()), block); - sendBlockPacket(player, new BlockPos(claim.max.getX(), y, claim.min.getZ()), block); - sendBlockPacket(player, new BlockPos(claim.min.getX(), y, claim.max.getZ()), block); - sendBlockPacket(player, new BlockPos(claim.max.getX(), y, claim.max.getZ()), block); - } - if (claim.includesPosition(pos)) for (int y = pos.getY() - closeShowRange; y <= pos.getY() + closeShowRange; y++) { - if (y < claim.min.getY() || y > claim.max.getY()) continue; - sendBlockPacket(player, new BlockPos(pos.getX(), y, claim.min.getZ()), block); - sendBlockPacket(player, new BlockPos(claim.max.getX(), y, pos.getZ()), block); - sendBlockPacket(player, new BlockPos(claim.min.getX(), y, pos.getZ()), block); - sendBlockPacket(player, new BlockPos(pos.getX(), y, claim.max.getZ()), block); - } - for (int z = claim.min.getZ(); z <= claim.min.getZ() + showRange; z++) { - sendBlockPacket(player, new BlockPos(claim.min.getX(), claim.min.getY(), z), block); - sendBlockPacket(player, new BlockPos(claim.max.getX(), claim.min.getY(), z), block); - sendBlockPacket(player, new BlockPos(claim.min.getX(), claim.max.getY(), z), block); - sendBlockPacket(player, new BlockPos(claim.max.getX(), claim.max.getY(), z), block); - } - for (int z = claim.max.getZ() - showRange; z <= claim.max.getZ(); z++) { - sendBlockPacket(player, new BlockPos(claim.min.getX(), claim.min.getY(), z), block); - sendBlockPacket(player, new BlockPos(claim.max.getX(), claim.min.getY(), z), block); - sendBlockPacket(player, new BlockPos(claim.min.getX(), claim.max.getY(), z), block); - sendBlockPacket(player, new BlockPos(claim.max.getX(), claim.max.getY(), z), block); - } - if (claim.includesPosition(pos)) for (int z = pos.getZ() - closeShowRange; z <= pos.getZ() + closeShowRange; z++) { - if (z < claim.min.getZ() || z > claim.max.getZ()) continue; - sendBlockPacket(player, new BlockPos(claim.min.getX(), pos.getY(), z), block); - sendBlockPacket(player, new BlockPos(claim.max.getX(), pos.getY(), z), block); - } - if (updateStatus) { - if (!hide) ((ClaimShower) player).setShownClaim(claim); - else ((ClaimShower) player).setShownClaim(null); - } - } - private static void sendBlockPacket(ServerPlayerEntity player, BlockPos pos, BlockState state) { - BlockUpdateS2CPacket packet = new BlockUpdateS2CPacket(player.world, pos); - if (state != null) ((BlockUpdatePacketMixin)packet).setState(state); - player.networkHandler.sendPacket(packet); - } - private static int createClaim(String name, ServerCommandSource owner, BlockPos posA, BlockPos posB, boolean admin) throws CommandSyntaxException { - UUID ownerID = owner.getPlayer().getGameProfile().getId(); - int x, y = 0, z, mx, my = 255, mz; - if (posA.getX() > posB.getX()) { - x = posB.getX(); - mx = posA.getX(); - } else { - x = posA.getX(); - mx = posB.getX(); - } - if (!Config.claims2d) { - if (posA.getY() > posB.getY()) { - y = posB.getY(); - my = posA.getY(); - } else { - y = posA.getY(); - my = posB.getY(); - } - } - if (posA.getZ() > posB.getZ()) { - z = posB.getZ(); - mz = posA.getZ(); - } else { - z = posA.getZ(); - mz = posB.getZ(); - } - BlockPos min = new BlockPos(x, y, z); - BlockPos max = new BlockPos(mx, my, mz); - BlockPos sub = max.subtract(min); - sub = sub.add(1,Config.claims2d ? 0 : 1,1); - int subInt = sub.getX() * (Config.claims2d ? 1 : sub.getY()) * sub.getZ(); - - Claim claim = new Claim(name, admin ? null : ownerID, min, max, owner.getWorld().getDimension().getType()); - claim.permissionManager.playerPermissions.put(ownerID, new Claim.InvertedPermissionMap()); - if (!ClaimManager.INSTANCE.claimsByName.containsKey(name)) { - if (!ClaimManager.INSTANCE.wouldIntersect(claim)) { - // works because only the first statement is evaluated if true - if ((admin && Thimble.hasPermissionOrOp(owner, "itsmine.admin.infinite_blocks", 4)) || ClaimManager.INSTANCE.useClaimBlocks(ownerID, subInt)) { - ClaimManager.INSTANCE.addClaim(claim); - owner.sendFeedback(new LiteralText("").append(new LiteralText("Your claim was created").formatted(Formatting.GREEN)).append(new LiteralText("(Area: " + sub.getX() + "x" + sub.getY() + "x" + sub.getZ() + ")").setStyle(new Style() - .setColor(Formatting.GREEN).setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new LiteralText(subInt + " blocks").formatted(Formatting.YELLOW))))), false); - checkPlayer(owner, owner.getPlayer().getGameProfile().getId()); - showClaim(owner, claim, false); - if (admin) - owner.getMinecraftServer().sendMessage(new LiteralText(owner.getPlayer().getGameProfile().getName() + " Has created a new claim(" + claim.name + ") using the admin command.")); - return 1; - } else { - owner.sendFeedback(new LiteralText("You don't have enough claim blocks. You have " + ClaimManager.INSTANCE.getClaimBlocks(ownerID) + ", you need " + subInt + "(" + (subInt - ClaimManager.INSTANCE.getClaimBlocks(ownerID)) + " more)").formatted(Formatting.RED), false); - } - } else { - owner.sendFeedback(new LiteralText("Your claim would overlap with another claim").formatted(Formatting.RED), false); - } - } else { - owner.sendFeedback(new LiteralText("The name \"" + name + "\" is already taken.").formatted(Formatting.RED), false); - } - return 0; - } - private static int checkPlayer(ServerCommandSource ret, UUID player) throws CommandSyntaxException { - int blocks = ClaimManager.INSTANCE.getClaimBlocks(player); - ret.sendFeedback(new LiteralText((ret.getPlayer().getGameProfile().getId().equals(player) ? "You have " : "They have ") + ClaimManager.INSTANCE.getClaimBlocks(player) + " blocks left").setStyle(new Style() - .setColor(Formatting.YELLOW).setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new LiteralText("Area of " + ItsMine.blocksToAreaString(ClaimManager.INSTANCE.getClaimBlocks(player))).formatted(Formatting.YELLOW)))), false); - return 0; - } - private static int requestDelete(ServerCommandSource sender, Claim claim, boolean admin) throws CommandSyntaxException { - if (claim == null) { - sender.sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); - return 0; - } - if (!claim.permissionManager.hasPermission(sender.getPlayer().getGameProfile().getId(), Claim.Permission.DELETE_CLAIM)) { - if (admin && Thimble.hasPermissionOrOp(sender, "itsmine.admin.modify", 4)) { - sender.sendFeedback(new LiteralText("WARNING: This is not your claim...").formatted(Formatting.DARK_RED, Formatting.BOLD), false); - } else { - sender.sendFeedback(new LiteralText("You cannot delete that claim").formatted(Formatting.RED), false); - return 0; - } - } - sender.sendFeedback(new LiteralText("").append(new LiteralText("Are you sure you want to delete the claim \"" + claim.name + "\"? ").formatted(Formatting.GOLD)) - .append(new LiteralText("[I'M SURE]").setStyle(new Style() - .setColor(Formatting.DARK_RED) - .setBold(true) - .setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, (admin ? "/claim admin" : "/claim") + " destroy " + claim.name + " confirm")))), false); - return 0; - } - private static int delete(ServerCommandSource sender, Claim claim, boolean admin) throws CommandSyntaxException { - if (claim == null) { - sender.sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); - return 0; - } - if (!claim.permissionManager.hasPermission(sender.getPlayer().getGameProfile().getId(), Claim.Permission.DELETE_CLAIM)) { - if (admin && Thimble.hasPermissionOrOp(sender, "itsmine.admin.modify", 4)) { - sender.sendFeedback(new LiteralText("Deleting a claim belonging to somebody else").formatted(Formatting.DARK_RED, Formatting.BOLD), false); - } else { - sender.sendFeedback(new LiteralText("You cannot delete that claim").formatted(Formatting.RED), false); - return 0; - } - } - ClaimManager.INSTANCE.releaseBlocksToOwner(claim); - ClaimManager.INSTANCE.claimsByName.remove(claim.name); - sender.getWorld().getPlayers().forEach(playerEntity -> { - if (((ClaimShower)playerEntity).getShownClaim() != null && ((ClaimShower)playerEntity).getShownClaim().name.equals(claim.name)) silentHideShow(playerEntity, claim, true, true); - }); - sender.sendFeedback(new LiteralText("Deleted the claim \"" + claim.name + "\"").formatted(Formatting.GREEN), !claim.permissionManager.hasPermission(sender.getPlayer().getGameProfile().getId(), Claim.Permission.DELETE_CLAIM)); - return 0; - } - private static int requestTransfer(ServerCommandSource sender, Claim claim, ServerPlayerEntity player, boolean admin) throws CommandSyntaxException { - if (claim == null) { - sender.sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); - return 0; - } - if (!claim.claimBlockOwner.equals(sender.getPlayer().getGameProfile().getId())) { - if (admin && Thimble.hasPermissionOrOp(sender, "itsmine.admin.modify", 4)) { - sender.sendFeedback(new LiteralText("WARNING: This is not your claim...").formatted(Formatting.DARK_RED, Formatting.BOLD), false); - } else { - sender.sendFeedback(new LiteralText("You cannot transfer ownership that claim").formatted(Formatting.RED), false); - return 0; - } - } - sender.sendFeedback(new LiteralText("").append(new LiteralText("Are you sure you want to transfer ownership of \"" + claim.name + "\" to " + player.getGameProfile().getName() + "? ").formatted(Formatting.GOLD)) - .append(new LiteralText("[I'M SURE]").setStyle(new Style() - .setColor(Formatting.DARK_RED) - .setBold(true) - .setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, (admin ? "/claim admin" : "/claim") + " transfer " + claim.name + " " + player.getGameProfile().getName() + " confirm")))), false); - return 0; - } - private static Map pendingClaimTransfers = new HashMap<>(); - private static int transfer(ServerCommandSource sender, Claim claim, ServerPlayerEntity player, boolean admin) throws CommandSyntaxException { - if (claim == null) { - sender.sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); - return 0; - } - if (!claim.claimBlockOwner.equals(sender.getPlayer().getGameProfile().getId())) { - if (admin && Thimble.hasPermissionOrOp(sender, "itsmine.admin.modify", 4)) { - sender.sendFeedback(new LiteralText("Transfering ownership of a claim belonging to somebody else").formatted(Formatting.DARK_RED, Formatting.BOLD), false); - } else { - sender.sendFeedback(new LiteralText("You cannot transfer ownership that claim").formatted(Formatting.RED), false); - return 0; - } - } - sender.sendFeedback(new LiteralText("Transferring ownership of the claim \"" + claim.name + "\" to " + player.getGameProfile().getName() + " if they accept").formatted(Formatting.GREEN), claim.claimBlockOwner != player.getGameProfile().getId()); - player.sendMessage(new LiteralText("").append(new LiteralText("Do you want to accept ownership of the claim \"" + claim.name + "\" from " + OfflineInfo.getNameById(sender.getWorld().getServer().getUserCache(), claim.claimBlockOwner) + "? ").formatted(Formatting.GOLD)) - .append(new LiteralText("[ACCEPT OWNERSHIP]").setStyle(new Style() - .setColor(Formatting.GREEN) - .setBold(true) - .setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/claim accept_transfer " + claim.name))))); - pendingClaimTransfers.put(player.getGameProfile().getId(), claim.name); - return 0; - } - public static int acceptTransfer(ServerCommandSource sender) throws CommandSyntaxException { - Claim claim = ClaimManager.INSTANCE.claimsByName.get(pendingClaimTransfers.get(sender.getPlayer().getGameProfile().getId())); - if (claim == null) { - sender.sendFeedback(new LiteralText("You have no pending claim transfers").formatted(Formatting.RED), false); - return 0; - } - if (sender.getMinecraftServer().getPlayerManager().getPlayer(claim.claimBlockOwner) != null) { - sender.getMinecraftServer().getPlayerManager().getPlayer(claim.claimBlockOwner).sendMessage(new LiteralText("").append(new LiteralText(sender.getPlayer().getGameProfile().getName() + " has taken ownership of the claim \"" + claim.name + "\"").formatted(Formatting.YELLOW))); - } - Claim.ClaimPermissionMap op = claim.permissionManager.playerPermissions.get(claim.claimBlockOwner); - claim.permissionManager.playerPermissions.put(claim.claimBlockOwner, claim.permissionManager.playerPermissions.get(sender.getPlayer().getGameProfile().getId())); - claim.permissionManager.playerPermissions.put(sender.getPlayer().getGameProfile().getId(), op); - claim.claimBlockOwner = sender.getPlayer().getGameProfile().getId(); - return 0; - } - private static int showClaimInfo(ServerCommandSource sender, Claim claim) { - sender.sendFeedback(new LiteralText("Claim Name: " + claim.name), false); - //sender.sendFeedback(new LiteralText("Owner")); // how to do this... - return 0; - } - private static int modifyException(Claim claim, ServerPlayerEntity exception, Claim.Permission permission, boolean allowed) { - claim.permissionManager.setPermission(exception.getGameProfile().getId(), permission, allowed); - return 0; - } - private static int modifyException(Claim claim, String exception, Claim.Permission permission, boolean allowed) { - claim.permissionManager.setPermission(exception, permission, allowed); - return 0; - } - private static boolean hasPermission(Claim claim, ServerPlayerEntity exception, Claim.Permission permission) { - return claim.permissionManager.hasPermission(exception.getGameProfile().getId(), permission); - } - private static boolean hasPermission(Claim claim, String exception, Claim.Permission permission) { - return claim.permissionManager.hasPermission(exception, permission); - } - private static Direction directionByName(String name) { - for (Direction direction : Direction.values()) { - if (name.equals(direction.getName())) return direction; - } - return null; - } - private static int expand(Claim claim, int amount, Direction direction, ServerCommandSource source, boolean admin) throws CommandSyntaxException { - UUID ownerID = source.getPlayer().getGameProfile().getId(); - if (claim == null) { - source.sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); - return 0; - } - if (direction == null) { - source.sendFeedback(new LiteralText("That is not a valid direction").formatted(Formatting.RED), false); - return 0; - } - if (!claim.permissionManager.hasPermission(ownerID, Claim.Permission.MODIFY_SIZE)) { - source.sendFeedback(new LiteralText("You do not have border change permissions in that claim").formatted(Formatting.RED), false); - if (!admin) return 0; - } - int oldArea = claim.getArea(); - if (amount > 0) claim.expand(direction, amount); - else { - if (!claim.shrink(direction, amount)) { - source.sendFeedback(new LiteralText("You can't shrink your claim that far. It would pass its opposite wall.").formatted(Formatting.RED), false); - return 0; - } - } - if (ClaimManager.INSTANCE.wouldIntersect(claim)) { - if (amount < 0) claim.expand(direction, amount); - else claim.shrink(direction, amount); - source.sendFeedback(new LiteralText("Expansion would result in hitting another claim").formatted(Formatting.RED), false); - return 0; - } - int newArea = claim.getArea() - oldArea; - if (!admin && claim.claimBlockOwner != null && ClaimManager.INSTANCE.getClaimBlocks(ownerID) < newArea) { - if (amount < 0) claim.expand(direction, amount); - else claim.shrink(direction, amount); - source.sendFeedback(new LiteralText("You don't have enough claim blocks. You have " + ClaimManager.INSTANCE.getClaimBlocks(ownerID) + ", you need " + newArea + "(" + (newArea - ClaimManager.INSTANCE.getClaimBlocks(ownerID)) + " more)").formatted(Formatting.RED), false); - checkPlayer(source, ownerID); - return 0; - } else { - if (!admin && claim.claimBlockOwner != null) ClaimManager.INSTANCE.useClaimBlocks(ownerID, newArea); - source.sendFeedback(new LiteralText("Your claim was " + (amount > 0 ? "expanded" : "shrunk") + " by " + (amount < 0 ? -amount : amount) + " blocks " + direction.getName()).formatted(Formatting.GREEN), false); - checkPlayer(source, ownerID); - if (amount < 0) claim.expand(direction, amount); - else claim.shrink(direction, amount); - source.getWorld().getPlayers().forEach(playerEntity -> { - if (((ClaimShower)playerEntity).getShownClaim() != null && ((ClaimShower)playerEntity).getShownClaim().name.equals(claim.name)) silentHideShow(playerEntity, claim, true, false); - }); - if (amount > 0) claim.expand(direction, amount); - else claim.shrink(direction, -amount); - source.getWorld().getPlayers().forEach(playerEntity -> { - if (((ClaimShower)playerEntity).getShownClaim() != null && ((ClaimShower)playerEntity).getShownClaim().name.equals(claim.name)) silentHideShow(playerEntity, claim, false, false); - }); - } - return 0; - } - private static int info(ServerCommandSource source, Claim claim) { - if (claim == null) { - source.sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); - return 0; - } - source.sendFeedback(new LiteralText("").append(new LiteralText("Claim Name: ").formatted(Formatting.YELLOW)).append(new LiteralText(claim.name).formatted(Formatting.GOLD)), false); - GameProfile owner = claim.claimBlockOwner == null ? null : source.getMinecraftServer().getUserCache().getByUuid(claim.claimBlockOwner); - source.sendFeedback(new LiteralText("").append(new LiteralText("Claim Owner: ").formatted(Formatting.YELLOW)).append(new LiteralText(owner == null ? "No owner" : owner.getName()).formatted(Formatting.GOLD)), false); - BlockPos size = claim.getSize(); - source.sendFeedback(new LiteralText("").append(new LiteralText("Claim Size: ").formatted(Formatting.YELLOW)).append(new LiteralText(size.getX() + (claim.is2d() ? "x" : ("x" + size.getY() + "x")) + size.getZ()).formatted(Formatting.GOLD)), false); - source.sendFeedback(new LiteralText("").append(new LiteralText("Start position: ").formatted(Formatting.YELLOW)).append(new LiteralText("X:" + claim.min.getX() + (claim.is2d() ? "" : " Y:" + claim.min.getY()) + " Z:" + claim.min.getZ()).formatted(Formatting.GOLD)), false); - source.sendFeedback(new LiteralText("").append(new LiteralText("End position: ").formatted(Formatting.YELLOW)).append(new LiteralText("X:" + claim.max.getX() + (claim.is2d() ? "" : " Y:" + claim.max.getY()) + " Z:" + claim.max.getZ()).formatted(Formatting.GOLD)), false); - return 0; - } - private static int list(ServerCommandSource source, String player) { - source.sendFeedback(new LiteralText(player == null ? "Your Claims:" : player + "'s Claims:").formatted(Formatting.YELLOW), false); - try { - UUID id = player == null ? source.getPlayer().getGameProfile().getId() : OfflineInfo.getIdByName(source.getMinecraftServer().getUserCache(), player); - List claims = ClaimManager.INSTANCE.getPlayerClaims(id); - if (claims.isEmpty()) { - source.sendFeedback(new LiteralText("None").formatted(Formatting.YELLOW), false); - return 0; - } - LiteralText feedback = new LiteralText(""); - for (int i = 0; i < claims.size(); i++) { - feedback.append(new LiteralText(claims.get(i).name).setStyle( - new Style().setColor(Formatting.GOLD) - .setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/claim info " + claims.get(i).name)) - )); - if (i < claims.size() - 1) { - feedback.append(new LiteralText(", ").formatted(Formatting.YELLOW)); - } - } - source.sendFeedback(feedback, false); - } catch (CommandSyntaxException e) { - source.sendFeedback(new LiteralText("No player is specified").formatted(Formatting.RED), false); - } - return 0; - } -} \ No newline at end of file diff --git a/src/main/java/io/github/indicode/fabric/itsmine/ClaimManager.java b/src/main/java/io/github/indicode/fabric/itsmine/ClaimManager.java index 77a083a..038f6c7 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/ClaimManager.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/ClaimManager.java @@ -1,16 +1,16 @@ package io.github.indicode.fabric.itsmine; +import io.github.indicode.fabric.itsmine.claim.Claim; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.StringTag; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Pair; import net.minecraft.util.math.BlockPos; import net.minecraft.world.dimension.DimensionType; +import org.jetbrains.annotations.Nullable; -import javax.naming.Name; import java.util.*; /** @@ -21,8 +21,10 @@ public class ClaimManager { public static ClaimManager INSTANCE = null; private HashMap blocksLeft = new HashMap<>(); public List ignoringClaims = new ArrayList<>(); + public List flyers = new ArrayList<>(); + public static MinecraftServer server; public int getClaimBlocks(UUID id) { - return blocksLeft.getOrDefault(id, Config.claims2d ? Config.baseClaimBlocks2d : Config.baseClaimBlocks3d); + return blocksLeft.getOrDefault(id, ItsMineConfig.main().claims2d ? ItsMineConfig.main().claimBlock().default2D : ItsMineConfig.main().claimBlock().default3D); } public boolean useClaimBlocks(UUID player, int amount) { int blocks = getClaimBlocks(player) - amount; @@ -40,8 +42,13 @@ public void useBlocksUntil0(UUID player, int amount) { if (!useClaimBlocks(player, amount)) blocksLeft.put(player, 0); } public void setClaimBlocks(Collection players, int amount) { - players.forEach(player -> setClaimBlocks(player.getGameProfile().getId(), -amount)); + players.forEach(player -> setClaimBlocks(player.getGameProfile().getId(), amount)); } + + public Claim getClaim(String name){ + return claimsByName.get(name); + } + public void setClaimBlocks(UUID player, int amount) { blocksLeft.put(player, Math.max(amount, 0)); } @@ -56,22 +63,37 @@ public List getPlayerClaims(UUID id) { }); return list; } + public boolean addClaim(Claim claim) { if (claimsByName.containsKey(claim.name)) return false; - if (wouldIntersect(claim)) return false; + if (wouldIntersect(claim) && !claim.isChild) return false; claimsByName.put(claim.name, claim); return true; } public boolean wouldIntersect(Claim claim) { for (Claim value : claimsByName.values()) { - if(!claim.name.equals(value.name) && claim.intersects(value)) return true; + if(!value.isChild && !claim.name.equals(value.name) && (claim.intersects(value) || value.intersects(claim))) return true; + } + return false; + } + + public boolean wouldSubzoneIntersect(Claim claim) { + for (Claim value : claimsByName.values()) { + if(!claim.name.equals(value.name) && claim.intersects(value, true, true)){ + return true; + } + } return false; } public CompoundTag toNBT() { CompoundTag tag = new CompoundTag(); ListTag list = new ListTag(); - claimsByName.values().forEach(claim -> list.add(claim.toTag())); + claimsByName.values().forEach(claim -> { + if(!claim.isChild){ + list.add(claim.toTag()); + } + }); tag.put("claims", list); CompoundTag blocksLeftTag = new CompoundTag(); blocksLeft.forEach((id, amount) -> {if (id != null) blocksLeftTag.putInt(id.toString(), amount);}); @@ -82,27 +104,83 @@ public CompoundTag toNBT() { tvargetter.putString("id", id.toString()); ignoring.add(tvargetter.get("id")); }); + ListTag listTag = new ListTag(); + for (UUID flyer : flyers) { + CompoundTag tag1 = new CompoundTag(); + tag1.putUuidNew("uuid", flyer); + listTag.add(tag1); + } + tag.put("flyers", listTag); tag.put("ignoring", ignoring); return tag; } + +/* public Claim getMainClaimAt(BlockPos pos, DimensionType dimension){ + for (Claim claim : claimsByName.values()) { + if(claim.dimension.equals(dimension) && claim.includesPosition(pos)){ + return claim.getZoneCovering(pos); + } + } + return null; + } + + public Claim getSubzoneClaimAt(BlockPos pos, DimensionType dimension) { + for (Claim claim : claimsByName.values()) { + if (claim.dimension.equals(dimension) && claim.includesPosition(pos)) { + for(Claim subzone : claim.children){ + if(subzone.dimension.equals(dimension) && subzone.includesPosition(pos)){ + return subzone.getZoneCovering(pos); + } + } + return null; + } + } + return null; + } + */ + + @Nullable public Claim getClaimAt(BlockPos pos, DimensionType dimension) { for (Claim claim : claimsByName.values()) { - if (claim.dimension.equals(dimension) && claim.includesPosition(pos)) return claim.getZoneCovering(pos); + if (claim.dimension.equals(dimension)) { + if(claim.includesPosition(pos)) { + for(Claim subzone : claim.children) { + if(subzone.dimension.equals(dimension)) { + if(subzone.includesPosition(pos)){ + return subzone; + } + } + } + return claim; + } + } } return null; } + public void fromNBT(CompoundTag tag) { + System.out.println("fromNBT"); ListTag list = (ListTag) tag.get("claims"); + System.out.println(list.size()); claimsByName.clear(); list.forEach(it -> { Claim claim = new Claim(); claim.fromTag((CompoundTag) it); claimsByName.put(claim.name, claim); + for(Claim subzone : claim.children){ + claimsByName.put(subzone.name, subzone); + } }); CompoundTag blocksLeftTag = tag.getCompound("blocksLeft"); blocksLeft.clear(); blocksLeftTag.getKeys().forEach(key -> blocksLeft.put(UUID.fromString(key), blocksLeftTag.getInt(key))); ListTag ignoringTag = (ListTag) tag.get("ignoring"); ignoringTag.forEach(it -> ignoringClaims.add(UUID.fromString(it.asString()))); + ListTag listTag = tag.getList("flyers", 11); + flyers.clear(); + for (int i = 0; i < listTag.size(); i++) { + CompoundTag tag1 = listTag.getCompound(i); + flyers.add(tag1.getUuidNew("uuid")); + } } } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/ClaimPlayerEntity.java b/src/main/java/io/github/indicode/fabric/itsmine/ClaimPlayerEntity.java new file mode 100644 index 0000000..7ceb19d --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/ClaimPlayerEntity.java @@ -0,0 +1,9 @@ +package io.github.indicode.fabric.itsmine; + +public interface ClaimPlayerEntity { + void tickMessageCooldown(); + int getMessageCooldown(); + boolean shouldMessage(); + void setMessageCooldown(); + void setMessageCooldown(int cooldown); +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/ClaimShower.java b/src/main/java/io/github/indicode/fabric/itsmine/ClaimShower.java index a7da63d..760762d 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/ClaimShower.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/ClaimShower.java @@ -1,5 +1,6 @@ package io.github.indicode.fabric.itsmine; +import io.github.indicode.fabric.itsmine.claim.Claim; import net.minecraft.util.math.BlockPos; /** @@ -8,6 +9,8 @@ public interface ClaimShower { void setLastShowPos(BlockPos pos); void setShownClaim(Claim claim); + void setShowMode(String mode); Claim getShownClaim(); + String getMode(); BlockPos getLastShowPos(); } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/Config.java b/src/main/java/io/github/indicode/fabric/itsmine/Config.java index 4ac6730..b8f665b 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/Config.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/Config.java @@ -1,30 +1,61 @@ +/* package io.github.indicode.fabric.itsmine; -import blue.endless.jankson.JsonArray; -import blue.endless.jankson.JsonPrimitive; -import io.github.indicode.fabric.permissions.Thimble; -import io.github.indicode.fabric.tinyconfig.DefaultedJsonArray; import io.github.indicode.fabric.tinyconfig.ModConfig; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - +*/ /** * @author Indigo Amann - */ + *//* + public class Config { public static int baseClaimBlocks3d = 15625; public static int baseClaimBlocks2d = 2500; public static boolean claims2d = true; + public static int rent_maxseconds = 7776000; + public static int claim_max_entities_passive = 75; + public static String permissionManager = "luckperms"; + public static String prefix = "&8[&aClaims&8]&r "; + public static String msg_no_perm = "&c&lHey!&r&c Sorry but you don't have permission to do that"; + public static String msg_interact_entity = "&c&lHey!&r&c Sorry but you can't interact with Entities here!"; + public static String msg_interact_block = "&c&lHey!&r&c Sorry but you can't interact with Blocks here!"; + public static String msg_open_container = "&c&lHey!&r&c Sorry but you can't open containers here!"; + public static String msg_break_block = "&c&lHey!&r&c Sorry but you can't Break Blocks here!"; + public static String msg_place_block = "&c&lHey!&r&c Sorry but you can't Place Blocks here!"; + public static String msg_attack_entity = "&c&lHey!&r&c Sorry but you can't Attack Entities here!"; + public static String msg_enter_default = "&eNow entering claim &6%claim%"; + public static String msg_leave_default = "&eNow leaving claim &6%claim%"; + public static String msg_cant_enter = "&c&lHey!&r&c Sorry but you don't have permission to enter this claim!"; + public static String msg_cant_use = "&c&lHey!&r&c Sorry but you can't to use that here!"; + public static String msg_long_name = "&cThe name of the Claim must be less than 30 characters!"; + public static String msg_cant_do ="&c&lHey!&r&c Sorry but you can't do that!"; + + public static int event_msg_stay_ticks = -1; private static ModConfig modConfig = new ModConfig("itsmine"); - static void sync(boolean overwrite) { - modConfig.configure(overwrite, config -> { + static void sync() { + modConfig.configure(false, config -> { claims2d = config.getBool("2D claims", claims2d, "Claims extending from y 0 to y 256"); baseClaimBlocks2d = config.getInt("2D base claim blocks", baseClaimBlocks2d, "Area Filled: " + ItsMine.blocksToAreaString2d(baseClaimBlocks2d)); baseClaimBlocks3d = config.getInt("3D base claim blocks", baseClaimBlocks3d, "Area Filled: " + ItsMine.blocksToAreaString3d(baseClaimBlocks3d)); + rent_maxseconds = config.getInt("rent.maxdays", rent_maxseconds, "Maximum rent time in seconds (eg. 90d = 7776000)"); + claim_max_entities_passive = config.getInt("claim.max.passive", claim_max_entities_passive, "Maximum allowed passive entities per claim"); + permissionManager = config.getString("permissionManager", permissionManager, "Values: thimble, luckperms, vanilla"); + prefix = config.getString("msg.prefix", prefix); + msg_interact_entity = config.getString("msg.interact.entity", msg_interact_entity); + msg_interact_block = config.getString("msg.interact.block", msg_interact_block); + msg_open_container = config.getString("msg.open.container", msg_open_container); + msg_break_block = config.getString("msg.break.block", msg_break_block); + msg_place_block = config.getString("msg.place.block", msg_place_block); + msg_attack_entity = config.getString("msg.attack.entity", msg_attack_entity); + msg_enter_default = config.getString("msg.enter_claim", msg_enter_default, "Variables: %claim% %player%"); + msg_leave_default = config.getString("msg.leave_claim", msg_leave_default, "Variables: %claim% %player%"); + msg_cant_enter = config.getString("msg.cant_enter", msg_cant_enter); + msg_cant_use = config.getString("msg.cant_use", msg_cant_use); + msg_long_name = config.getString("msg.long_name", msg_long_name); + msg_cant_do = config.getString("msg.cant_do", msg_cant_do); + event_msg_stay_ticks = config.getInt("event.msg.stay_ticks", event_msg_stay_ticks, "Sets how many ticks an event message will stay on action bar, Default: -1"); }); } } +*/ diff --git a/src/main/java/io/github/indicode/fabric/itsmine/Functions.java b/src/main/java/io/github/indicode/fabric/itsmine/Functions.java index e276625..d8f546d 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/Functions.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/Functions.java @@ -1,21 +1,26 @@ package io.github.indicode.fabric.itsmine; +import io.github.indicode.fabric.itsmine.claim.Claim; import io.github.indicode.fabric.itsmine.mixin.BlockActionPacketMixin; import io.github.indicode.fabric.itsmine.mixin.BucketItemMixin; -import io.github.indicode.fabric.permissions.Thimble; -import net.minecraft.block.Blocks; +import io.github.indicode.fabric.itsmine.mixin.projectile.OwnedProjectile; +import io.github.indicode.fabric.itsmine.util.BlockUtil; +import net.minecraft.block.*; +import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.projectile.ProjectileEntity; +import net.minecraft.entity.projectile.thrown.ThrownEntity; import net.minecraft.fluid.Fluids; +import net.minecraft.item.BlockItem; import net.minecraft.item.BucketItem; +import net.minecraft.item.Item; import net.minecraft.network.Packet; -import net.minecraft.network.packet.s2c.play.BlockActionS2CPacket; +import net.minecraft.network.packet.s2c.play.BlockEventS2CPacket; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; -import net.minecraft.text.LiteralText; -import net.minecraft.util.Formatting; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.*; @@ -24,7 +29,7 @@ */ public class Functions { public static void doPistonUpdate(ServerWorld world, Packet packet) { - if (packet instanceof BlockActionS2CPacket) { + if (packet instanceof BlockEventS2CPacket) { BlockActionPacketMixin accessor = (BlockActionPacketMixin) packet; if ((accessor.getBlock() == Blocks.PISTON || accessor.getBlock() == Blocks.PISTON_HEAD || accessor.getBlock() == Blocks.STICKY_PISTON)) { Direction direction = Direction.byId(accessor.getData()); @@ -34,18 +39,8 @@ public static void doPistonUpdate(ServerWorld world, Packet packet) { } } public static boolean canPlayerActuallyModifyAt(ServerWorld world, PlayerEntity playerEntity_1, BlockPos blockPos_1) { - return !world.getServer().isSpawnProtected(world, blockPos_1, playerEntity_1) && world.getWorldBorder().contains(blockPos_1); + return !world.getServer().isSpawnProtected(world, blockPos_1, playerEntity_1) && !world.getWorldBorder().contains(blockPos_1); }; - public static boolean canModifyAtClaimed(PlayerEntity player, BlockPos blockPos_1) { - if (player.world.isClient()) return false; - Claim claim = ClaimManager.INSTANCE.getClaimAt(blockPos_1, player.getEntityWorld().getDimension().getType()); - if (claim != null) { - if (!claim.hasPermission(player.getGameProfile().getId(), Claim.Permission.SPAWN_PROTECT)) { - return false; - } - } - return true; - } public static boolean isBucketEmpty(BucketItem item) { return ((BucketItemMixin)item).getFluid() != Fluids.EMPTY; } @@ -59,7 +54,15 @@ public static boolean canClaimFly(ServerPlayerEntity player) { } } public static void refreshFly(ServerPlayerEntity player) { - flyers.put(player.getGameProfile().getId(), player.world.getServer().getPlayerManager().isOperator(player.getGameProfile()) || Thimble.PERMISSIONS.hasPermission("itsmine.claim_fly", player.getGameProfile().getId())); + flyers.put(player.getGameProfile().getId(), player.world.getServer().getPlayerManager().isOperator(player.getGameProfile()) || ItsMine.permissions().hasPermission(player.getUuid(), "itsmine.claim_fly")); + } + public static boolean canFly(ServerPlayerEntity player) { + boolean op = false; + if (player.world.getServer() != null) { + op = player.world.getServer().getPlayerManager().isOperator(player.getGameProfile()); + } + + return op || ItsMine.permissions().hasPermission(player.getUuid(), "itsmine.claim_fly"); } private static List claimFlyNow = new ArrayList<>(); public static boolean isClaimFlying(UUID player) { @@ -72,4 +75,71 @@ public static void setClaimFlying(UUID player, boolean flying) { claimFlyNow.remove(player); } } + + public static boolean canInteractWith(Claim claim, Block block, UUID player) { + return claim.hasPermission(player, Claim.Permission.INTERACT_BLOCKS) || + (BlockUtil.isButton(block) && claim.hasPermission(player, Claim.Permission.USE_BUTTONS)) || + (BlockUtil.isLever(block) && claim.hasPermission(player, Claim.Permission.USE_LEVERS)) || + (BlockUtil.isDoor(block) && claim.hasPermission(player, Claim.Permission.INTERACT_DOORS)) || + (BlockUtil.isContainer(block) && claim.hasPermission(player, Claim.Permission.CONTAINER)) || + (BlockUtil.isChest(block) && claim.hasPermission(player, Claim.Permission.CONTAINER_CHEST)) || + (BlockUtil.isEnderchest(block) && claim.hasPermission(player, Claim.Permission.CONTAINER_ENDERCHEST)) || + (BlockUtil.isShulkerBox(block) && claim.hasPermission(player, Claim.Permission.CONTAINER_SHULKERBOX)) || + (BlockUtil.isLectern(block) && claim.hasPermission(player, Claim.Permission.INTERACT_LECTERN)); + } + + public static boolean canInteractUsingItem(Claim claim, Item item, UUID player) { + return claim.hasPermission(player, Claim.Permission.USE_ITEMS_ON_BLOCKS) || + (item instanceof BlockItem && claim.hasPermission(player, Claim.Permission.BUILD)) || + (item instanceof BucketItem && claim.hasPermission(player, Claim.Permission.BUILD)); + } + + + public static boolean canDamageWithProjectile(ThrownEntity thrownEntity, Entity entity) { + if (checkCanDamageWithProjectile(entity, thrownEntity.getServer(), ((OwnedProjectile) thrownEntity).getOwner())) { + return true; + } + +// thrownEntity.kill(); + return false; + } + + public static boolean canDamageWithProjectile(ProjectileEntity projectile, Entity entity) { + if (checkCanDamageWithProjectile(entity, projectile.getServer(), ((OwnedProjectile) projectile).getOwner())) { +// projectile.kill(); + return true; + } + + return false; + } + + public static > Map sortByValue(Map map) { + List> list = new ArrayList<>(map.entrySet()); + list.sort(Map.Entry.comparingByValue()); + + Map result = new LinkedHashMap<>(); + for (Map.Entry entry : list) { + result.put(entry.getKey(), entry.getValue()); + } + + return result; + } + + public static boolean checkCanDamageWithProjectile(Entity entity, MinecraftServer server, UUID uuid) { + if (entity.world.isClient) + return true; + + ServerPlayerEntity owner = server.getPlayerManager().getPlayer(uuid); + Claim claim = ClaimManager.INSTANCE.getClaimAt(entity.getBlockPos(), entity.world.getDimension()); + + if (claim != null && owner != null && !claim.hasPermission(owner.getUuid(), Claim.Permission.DAMAGE_ENTITY)) { + owner.sendSystemMessage(Messages.MSG_DAMAGE_ENTITY, owner.getUuid()); + return false; + } + + return true; + } + + + } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/ItsMine.java b/src/main/java/io/github/indicode/fabric/itsmine/ItsMine.java index 5ead88f..c3ff19e 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/ItsMine.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/ItsMine.java @@ -1,48 +1,60 @@ package io.github.indicode.fabric.itsmine; -import io.github.indicode.fabric.permissions.PermChangeBehavior; -import io.github.indicode.fabric.permissions.Thimble; +import io.github.indicode.fabric.itsmine.config.Config; +import io.github.indicode.fabric.itsmine.util.PermissionUtil; import net.fabricmc.api.ModInitializer; -import net.minecraft.server.command.ServerCommandSource; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Logger; -import java.lang.reflect.InvocationTargetException; -import java.util.UUID; +import java.nio.file.Path; /** * @author Indigo Amann */ public class ItsMine implements ModInitializer { + private static PermissionUtil permissionUtil; + public static int time = 0; + public static int executed = 0; + + @Override public void onInitialize() { - Config.sync(false); - Thimble.permissionWriters.add((map, server) -> { - map.registerPermission("itsmine.specify_groups", PermChangeBehavior.UPDATE_COMMAND_TREE); - map.registerPermission("itsmine.claim_fly", (enabled, player) -> { - Functions.refreshFly(player); - }); - map.registerPermission("itsmine.admin.infinite_claim", PermChangeBehavior.UPDATE_COMMAND_TREE); - map.registerPermission("itsmine.admin.check_others", PermChangeBehavior.UPDATE_COMMAND_TREE); - map.registerPermission("itsmine.admin.modify_balance", PermChangeBehavior.UPDATE_COMMAND_TREE); - map.registerPermission("itsmine.admin.modify", PermChangeBehavior.UPDATE_COMMAND_TREE); - map.registerPermission("itsmine.admin.modify_permissions", PermChangeBehavior.UPDATE_COMMAND_TREE); - map.registerPermission("itsmine.admin.ignore_claims", PermChangeBehavior.UPDATE_COMMAND_TREE); - }); + new ItsMineConfig(); + permissionUtil = new PermissionUtil(); + + + //TODO: Enable when developing + //SharedConstants.isDevelopment = true; } - public static String blocksToAreaString3d(int blocks) { - int base = (int) Math.floor(Math.cbrt(blocks)); - int additionalBlocks = blocks - (int) Math.pow(base, 3); - int extraRows = (int) Math.floor(Math.cbrt(Math.floor((float)additionalBlocks / base))); - int leftoverBlocks = additionalBlocks % base; - return (base + extraRows) + "x" + base + "x" + base + "(+" + leftoverBlocks + ")"; + + public static void reload(){ + ItsMineConfig.reload(); +// PermissionUtil.reload(); } - public static String blocksToAreaString2d(int blocks) { - int base = (int) Math.floor(Math.sqrt(blocks)); - int additionalBlocks = blocks - (int) Math.pow(base, 2); - int extraRows = (int) Math.floor((float)additionalBlocks / base); - int leftoverBlocks = additionalBlocks % base; - return (base + extraRows) + "x" + base + "(+" + leftoverBlocks + ")"; + + public static PermissionUtil permissions() { + return permissionUtil; } - public static String blocksToAreaString(int blocks) { - return Config.claims2d ? blocksToAreaString2d(blocks) : blocksToAreaString3d(blocks); + + public static String getDirectory(){ + return System.getProperty("user.dir"); } + +// public static String blocksToAreaString3d(int blocks) { +// int base = (int) Math.floor(Math.cbrt(blocks)); +// int additionalBlocks = blocks - (int) Math.pow(base, 3); +// int extraRows = (int) Math.floor(Math.cbrt(Math.floor((float)additionalBlocks / base))); +// int leftoverBlocks = additionalBlocks % base; +// return (base + extraRows) + "x" + base + "x" + base + "(+" + leftoverBlocks + ")"; +// } +// public static String blocksToAreaString2d(int blocks) { +// int base = (int) Math.floor(Math.sqrt(blocks)); +// int additionalBlocks = blocks - (int) Math.pow(base, 2); +// int extraRows = (int) Math.floor((float)additionalBlocks / base); +// int leftoverBlocks = additionalBlocks % base; +// return (base + extraRows) + "x" + base + "(+" + leftoverBlocks + ")"; +// } +// public String blocksToAreaString(int blocks) { +// return config.claims2d ? blocksToAreaString2d(blocks) : blocksToAreaString3d(blocks); +// } } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/ItsMineConfig.java b/src/main/java/io/github/indicode/fabric/itsmine/ItsMineConfig.java new file mode 100644 index 0000000..5c8ad8d --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/ItsMineConfig.java @@ -0,0 +1,60 @@ +package io.github.indicode.fabric.itsmine; + +import com.google.common.reflect.TypeToken; +import io.github.indicode.fabric.itsmine.config.Config; +import ninja.leaping.configurate.ConfigurationNode; +import ninja.leaping.configurate.ConfigurationOptions; +import ninja.leaping.configurate.commented.CommentedConfigurationNode; +import ninja.leaping.configurate.hocon.HoconConfigurationLoader; +import ninja.leaping.configurate.loader.ConfigurationLoader; +import ninja.leaping.configurate.objectmapping.DefaultObjectMapperFactory; +import ninja.leaping.configurate.objectmapping.ObjectMappingException; + +import java.io.File; +import java.io.IOException; + +public class ItsMineConfig { + private static Config config; + private static ConfigurationNode mainNode; + + public ItsMineConfig() { + try { + File CONFIG_FILE = new File(ItsMine.getDirectory() + "/config/itsmine.hocon"); + + ConfigurationLoader mainLoader = HoconConfigurationLoader.builder() + .setFile(CONFIG_FILE).build(); + + + CONFIG_FILE.createNewFile(); + + mainNode = mainLoader.load(configurationOptions()); + + config = mainNode.getValue(TypeToken.of(Config.class), new Config()); + + mainLoader.save(mainNode); + } catch (IOException | ObjectMappingException e) { + System.out.println("Exception loading config file"); + e.printStackTrace(); + } + } + + public static Config main() { + return config; + } + + public static ConfigurationNode getMainNode() { + return mainNode; + } + + + public static void reload() { + new ItsMineConfig(); + } + + public static ConfigurationOptions configurationOptions() { + return ConfigurationOptions.defaults() + .setHeader(Config.HEADER) + .setObjectMapperFactory(DefaultObjectMapperFactory.getInstance()) + .setShouldCopyDefaults(true); + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/Messages.java b/src/main/java/io/github/indicode/fabric/itsmine/Messages.java new file mode 100644 index 0000000..3ced3e8 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/Messages.java @@ -0,0 +1,187 @@ +package io.github.indicode.fabric.itsmine; + +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.claim.ClaimFlags; +import io.github.indicode.fabric.itsmine.util.ChatColor; +import net.minecraft.text.LiteralText; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +public class Messages { + public static final MutableText PREFIX = new LiteralText(ChatColor.translate(ItsMineConfig.main().prefix)); + + public static final Text INVALID_CLAIM = PREFIX.copy().append(new LiteralText("Can not find a claim with that name or a claim at your position").formatted(Formatting.RED)); + + public static final Text INVALID_SETTING = PREFIX.copy().append(new LiteralText("Invalid Claim Flag!").formatted(Formatting.RED)); + + public static final Text INVALID_PERMISSION = PREFIX.copy().append(new LiteralText("Invalid Claim Permission!")); + + public static final Text NO_PERMISSION = PREFIX.copy().append(new LiteralText(ChatColor.translate(ItsMineConfig.main().message().noPermission))); + + public static final Text INVALID_MESSAGE_EVENT = PREFIX.copy().append(new LiteralText("Invalid Message Event!")); + + public static final Text INVALID_PLAYER = PREFIX.copy().append(new LiteralText("Can not find a Player with that Name!")); + + public static final Text TOO_MANY_SELECTIONS = PREFIX.copy().append(new LiteralText("Only one selection is allowed!")); + + public static final Text MSG_PLACE_BLOCK = PREFIX.copy().append(new LiteralText(ChatColor.translate(ItsMineConfig.main().message().placeBlock))); + + public static final Text MSG_BREAK_BLOCK = PREFIX.copy().append(new LiteralText(ChatColor.translate(ItsMineConfig.main().message().breakBlock)).formatted(Formatting.RED)); + + public static final Text MSG_CANT_ENTER = PREFIX.copy().append(new LiteralText(ChatColor.translate(ItsMineConfig.main().message().cantEnter)).formatted(Formatting.RED)); + + public static final Text MSG_INTERACT_ENTITY = PREFIX.copy().append(new LiteralText(ChatColor.translate(ItsMineConfig.main().message().interactEntity)).formatted(Formatting.RED)); + + public static final Text MSG_INTERACT_BLOCK = PREFIX.copy().append(new LiteralText(ChatColor.translate(ItsMineConfig.main().message().interactBlock)).formatted(Formatting.RED)); + + public static final Text MSG_OPEN_CONTAINER = PREFIX.copy().append(new LiteralText(ChatColor.translate(ItsMineConfig.main().message().openContainer)).formatted(Formatting.RED)); + + public static final Text MSG_DAMAGE_ENTITY = PREFIX.copy().append(new LiteralText(ChatColor.translate(ItsMineConfig.main().message().attackEntity)).formatted(Formatting.RED)); + + public static final Text MSG_CANT_USE = PREFIX.copy().append(new LiteralText(ChatColor.translate(ItsMineConfig.main().message().cantUse)).formatted(Formatting.RED)); + + public static final Text MSG_LONG_NAME = PREFIX.copy().append(new LiteralText(ChatColor.translate(ItsMineConfig.main().message().longName)).formatted(Formatting.RED)); + + public static final Text MSG_CANT_DO = PREFIX.copy().append(new LiteralText(ChatColor.translate(ItsMineConfig.main().message().cantDo)).formatted(Formatting.RED)); + + public static final Text[] GET_STARTED = new MutableText[]{ + header("How to Claim (Basics)") + .append(line(1, "Type &6/claim stick&e then Left click with a stick on a block to set the &6first&e corner of your claim")) + .append(line(2, "Right click to set the other corner")) + .append(line(3, "Type &6/claim create &e to create your claim!")) + .append(line(4, "To trust a player in your claim type &6/claim trust ")) + .append(line(5, "To untrust a player in your claim type &6/claim distrust ")), + header("How to Claim (Flags)") + .append(line("Flags allow you to change some properties of your claim, they are basically global permissions").formatted(Formatting.LIGHT_PURPLE)) + .append(line(1, "To change a flag, type ").append(text("/claim flags [true | false]").formatted(Formatting.GOLD))) + .append(line(2, "To check a flag, type ").append(text("/claim flags ").formatted(Formatting.GOLD))) + .append(line(3, "To see a list of flags, type ").append(text("/claim flags").formatted(Formatting.GOLD))), + header("How to Claim (Player Permissions)") + .append(line("You can set different permissions for each trusted player!").formatted(Formatting.LIGHT_PURPLE)) + .append(line(1, "To set a permission, type ").append(text("/claim permissions player [true | false]").formatted(Formatting.GOLD))) + .append(line(2, "To check someone's permission, type ").append(text("/claim permissions player ").formatted(Formatting.GOLD))) + .append(line(3, "To see a list of trusted players, type ").append(text("/claim trusted").formatted(Formatting.GOLD))), + header("How to Claim (Resizing)") + .append(line("You can always change the size of your claim if you aren't happy with it!").formatted(Formatting.LIGHT_PURPLE)) + .append(line(1, "To expand your claim in a direction, type ").append(text("/claim expand ").formatted(Formatting.GOLD))) + .append(line(2, "If you want to specify a direction, you can type ").append(text("/claim expand ").formatted(Formatting.GOLD))) + .append(line(3, "To shrink a claim you do the same thing but replace \"expand\" with \"shrink\"")), + header("How to Claim (Subzones)") + .append(line("Subzones allow you to have seperate permissions / flags in certain areas of your claim").formatted(Formatting.LIGHT_PURPLE)) + .append(line(1, "To create a subzone, you select an area inside your claim the way you would select a normal claim")) + .append(line(2, "Type ").append(text("/claim subzone add ")).formatted(Formatting.GOLD).append(text(" to create a subzone")).formatted(Formatting.YELLOW)) + .append(line(3,"Done! Everything else works the same way claims work")) + }; + + public static final Text[] HELP = new Text[]{ + header("Arguments") + .append(line("&6create ").append(text("&eCreates a claim"))) + .append(line("&6blocks ").append(text("&eShows how many blocks you have left"))) + .append(line("&6trust ").append(text("&eLets you trust a player in your claim"))) + .append(line("&6distrust ").append(text("&eLets you distrust a player in your claim"))) + .append(line("&6trusted ").append(text("&eShows you a list of all the trusted players"))) + .append(line("&6expand ").append(text("&eLets you expand your claim"))), + + header("Arguments") + .append(line("&6shrink ").append(text("&eLets you shrink your claim"))) + .append(line("&6help ").append(text("&eShows this list"))) + .append(line("&6show ").append(text("&eShows the borders of your claim"))) + .append(line("&6hide ").append(text("&eHides the borders of your claim"))) + .append(line("&6info ").append(text("&eShows you some information about a claim"))) + .append(line("&6list ").append(text("&eShows you the list of your claims"))), + + header("Arguments") + .append(line("&6permissions ").append(text("&eLets you modify the permissions of players and add exceptions"))) + .append(line("&6remove ").append(text("&eRemoves your claim"))) + .append(line("&6rename ").append(text("&eLets you rename your claim"))) + .append(line("&6flags ").append(text("&eLets you modify the global permissions and flag of your claim"))) + .append(line("&6message ").append(text("&eLets you modify the different message events"))) + .append(line("&6stick ").append(text("&eEnables/disables the claim stick for marking the positions"))), + + header("Arguments") + .append(line("&6transfer ").append(text("&eLets you transfer the ownership of a claim"))) + .append(line("&6message ").append(text("&eLets you modify the different message events"))) + }; + + public static final Text[] SETTINGS_AND_PERMISSIONS = new Text[]{ + header("Permissions") + .append(line("&6build ").append(text("&eAllows others to build (place and break blocks)"))) + .append(line("&6interact_blocks ").append(text("&eAllows others to Interact (Right click) with blocks"))) + .append(line("&6use_items_on_blocks ").append(text("&eAllows others to use items on blocks (Right click on blocks with an Item)"))) + .append(line("&6use.button ").append(text("&eAllows others to press Buttons"))) + .append(line("&6use.levers ").append(text("&eAllows others to ue Levers"))) + .append(line("&6interact_doors ").append(text("&eAllows others to Interact with Doors"))) + .append(line("&6interact_entity ").append(text("&eAllows others to Interact with Entities (Right click on Entities)"))), + + header("Permissions") + .append(line("&6damage_entity ").append(text("&eAllows others to Damage (Attack) Entities"))) + .append(line("&6damage_entity.hostile ").append(text("&eAllows others Damage (Attack) Hostile Entities, e.g: Zombie, Creeper, Skeleton etc"))) + .append(line("&6damage_entity.passive ").append(text("&eAllows others to Damage (Attack) Passive Entities, e.g: Sheep, Cow, Chicken etc"))) + .append(line("&6flight ").append(text("&eEnables Flight in the claim (Only for those who have the Flight permission)"))), + + header("Permissions") + .append(line("&6container.enderchest ").append(text("&eAllows others to only open Ender Chest containers"))) + .append(line("&6container.shulkerbox ").append(text("&eAllows others to only open shulkerox container"))) + .append(line("&6modify.properties ").append(text("&eAllows others to modify the properties of the claim (e.g: Join/leave messages)"))) + .append(line("&6container ").append(text("&eAllows others to open containers (e.g: Chest, EnderChest etc)"))) + .append(line("&6container ").append(text("&eAllows others to open containers (e.g: Chest, EnderChest etc)"))) + .append(line("&6container.chest ").append(text("&eAllows others to only open chest containers (Chests and Barrels)"))), + + header("Flags") + .append(line("&6flight_allowed ").append(text("Allows others to fly in the claim (Only for those who have the Flight permission)"))) + .append(line("&6explosion_destruction ").append(text("Explosions destroy blocks"))) + .append(line("&6explosion_damage ").append(text("Explosions damage entities"))) + .append(line("&6fluid_crosses_border ").append(text("Let fluids go across the borders"))) + .append(line("&6fire_crosses_border ").append(text("Let fire to spread across the borders"))), + + header("Flags") + .append(line("&6fire_damage ").append(text("Fire damages entities"))) + .append(line("&6piston_from_inside ").append(text("Let pistons to move blocks to outside the claim"))) + .append(line("&6mob_spawning ").append(text("Allow mobs to spawn inside the claim"))) + .append(line("&6enter_sound ").append(text("Play a sound when entering the claim"))) + .append(line("&6break_farmlands ").append(text("Allow turning Farmlands into Dirt by jumping on them"))) + }; + + public static MutableText header(String title) { + return new LiteralText("").append(new LiteralText(title + ":").formatted(Formatting.AQUA).formatted(Formatting.UNDERLINE)).formatted(Formatting.WHITE).append(new LiteralText("\n")); + } + + public static MutableText line(int num, String string) { + return line("&e" + num + ".&e " + string); + } + + public static MutableText line(String string) { + return new LiteralText("\n").append(new LiteralText(ChatColor.translate(string))).formatted(Formatting.YELLOW); + } + + public static MutableText text(String text) { + return new LiteralText(ChatColor.translate(text)); + } + + public static class Command { + public static Text getFlags(Claim claim) { + MutableText claimFlags = new LiteralText(""); + boolean nextEnabled = false; + boolean nextDisabled = false; + for (ClaimFlags.Flag value : ClaimFlags.Flag.values()) { + boolean enabled = claim.flags.getFlag(value); + Formatting formatting; + if (enabled) { + if (nextEnabled) formatting = Formatting.GREEN; + else formatting = Formatting.DARK_GREEN; + nextEnabled = !nextEnabled; + } else { + if (nextDisabled) formatting = Formatting.RED; + else formatting = Formatting.DARK_RED; + nextDisabled = !nextDisabled; + } + + claimFlags.append(new LiteralText(" ")).append(new LiteralText(value.id).formatted(formatting)); + } + + return claimFlags; + } + + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/MonitorableWorld.java b/src/main/java/io/github/indicode/fabric/itsmine/MonitorableWorld.java new file mode 100644 index 0000000..f367c72 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/MonitorableWorld.java @@ -0,0 +1,14 @@ +package io.github.indicode.fabric.itsmine; + +import net.minecraft.entity.Entity; + +import java.util.ArrayList; +import java.util.Map; +import java.util.UUID; + +public interface MonitorableWorld { + + int loadedEntities(); + + Map EntityList(); +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/claim/Claim.java b/src/main/java/io/github/indicode/fabric/itsmine/claim/Claim.java new file mode 100644 index 0000000..0ecf5af --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/claim/Claim.java @@ -0,0 +1,778 @@ +package io.github.indicode.fabric.itsmine.claim; + +import blue.endless.jankson.annotation.Nullable; +import io.github.indicode.fabric.itsmine.*; +import io.github.indicode.fabric.itsmine.util.WorldUtil; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.*; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.dimension.DimensionType; + +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; + +import static io.github.indicode.fabric.itsmine.util.NbtUtil.*; + +/** + * @author Indigo Amann + */ +public class Claim { + public String name; + public BlockPos min, max; + public @Nullable BlockPos tpPos; + public DimensionType dimension; + public List children = new ArrayList<>(); + public ClaimFlags flags = new ClaimFlags(); + public PermissionManager permissionManager = new PermissionManager(); + public Rent rent = new Rent(); + public UUID claimBlockOwner = null; + public String customOwnerName, enterMessage, leaveMessage; + public boolean isChild = false; + public Claim() { + } + + public Claim(CompoundTag tag) { + fromTag(tag); + } + public Claim(String name, UUID claimBlockOwner, BlockPos min, BlockPos max, DimensionType dimension) { + this(name, claimBlockOwner, min, max, dimension, null, false); + } + public Claim(String name, UUID claimBlockOwner, BlockPos min, BlockPos max, DimensionType dimension, @Nullable BlockPos tpPo, boolean isChild) { + this.claimBlockOwner = claimBlockOwner; + this.min = min; + this.max = max; + this.name = name; + this.dimension = dimension; + this.tpPos = tpPos; + this.isChild = isChild; + } + public boolean includesPosition(BlockPos pos) { + return pos.getX() >= min.getX() && pos.getY() >= min.getY() && pos.getZ() >= min.getZ() && + pos.getX() <= max.getX() && pos.getY() <= max.getY() && pos.getZ() <= max.getZ(); + } + + public boolean isInside (Claim claim){ + BlockPos a = min, + b = max, + c = new BlockPos(max.getX(), min.getY(), min.getZ()), + d = new BlockPos(min.getX(), max.getY(), min.getZ()), + e = new BlockPos(min.getX(), min.getY(), max.getZ()), + f = new BlockPos(max.getX(), max.getY(), min.getZ()), + g = new BlockPos(max.getX(), min.getY(), max.getZ()), + h = new BlockPos(min.getX(), max.getY(), max.getZ()); + if( + claim.includesPosition(a) && + claim.includesPosition(b) && + claim.includesPosition(c) && + claim.includesPosition(d) && + claim.includesPosition(e) && + claim.includesPosition(f) && + claim.includesPosition(g) && + claim.includesPosition(h) + ){ + return true; + } + return false; + } + + public boolean intersects(Claim claim) { + return intersects(claim, true, false); + } + + public int getEntities(ServerWorld world){ + AtomicReference entities = new AtomicReference<>(); + entities.set(0); + MonitorableWorld monitorableWorld = (MonitorableWorld) world; + monitorableWorld.EntityList().forEach((uuid, entity) -> { + if(includesPosition(entity.getBlockPos())) { + entities.set(entities.get()+1); + } + }); + return entities.get(); + } + + + public boolean intersects(Claim claim, boolean checkOther, boolean checkforsubzone) { + if (claim == null) return false; + if (!claim.dimension.equals(dimension)) return false; + BlockPos a = min, + b = max, + c = new BlockPos(max.getX(), min.getY(), min.getZ()), + d = new BlockPos(min.getX(), max.getY(), min.getZ()), + e = new BlockPos(min.getX(), min.getY(), max.getZ()), + f = new BlockPos(max.getX(), max.getY(), min.getZ()), + g = new BlockPos(max.getX(), min.getY(), max.getZ()), + h = new BlockPos(min.getX(), max.getY(), max.getZ()); + if(claim.isChild && checkforsubzone || !claim.isChild && !checkforsubzone){ + if( + claim.includesPosition(a) || + claim.includesPosition(b) || + claim.includesPosition(c) || + claim.includesPosition(d) || + claim.includesPosition(e) || + claim.includesPosition(f) || + claim.includesPosition(g) || + claim.includesPosition(h) + ) { + return true; + } + //If the claim is a subzone and checking for subzone is disabled or if the claim isnt a subzone and checking is enabled, instantly return false + }else if (claim.isChild && !checkforsubzone || !claim.isChild && checkforsubzone) { + return false; + } + else return checkOther && claim.intersects(this, false, checkforsubzone); + return false; + } + +/* + @Nullable + public Claim getZoneCovering(BlockPos pos) { + if (includesPosition(pos)) { + for (Claim child : children) { + Claim value = child.getZoneCovering(pos); + if (value != null) { + return value; + } + } + + return this; + } + + return null; + } +*/ + public boolean hasPermission(UUID player, Permission permission) { + return ClaimManager.INSTANCE.ignoringClaims.contains(player) || permissionManager.hasPermission(player, permission); + } + + public void addSubzone(Claim claim) { + children.add(claim); + } + + public void removeSubzone(Claim claim) { + children.remove(claim); + } + + public BlockPos getSize() { + return max.subtract(min); + } + + public void expand(BlockPos modifier) { + if (modifier.getX() > 0) { + max = max.add(modifier.getX(), 0, 0); + } + else { + min = min.add(modifier.getX(), 0, 0); + } + if (modifier.getY() > 0) { + max = max.add(0, modifier.getY(), 0); + } + else { + min = min.add(0, modifier.getY(), 0); + } + if (modifier.getZ() > 0) { + max = max.add(0, 0, modifier.getZ()); + } + else { + min = min.add(0, 0, modifier.getZ()); + } + } + public void shrink(BlockPos modifier) { + if (modifier.getX() < 0) { + min = min.add(-modifier.getX(), 0, 0); + } else { + max = max.add(-modifier.getX(), 0, 0); + } + if (modifier.getY() < 0) { + min = min.add(0, -modifier.getY(), 0); + } else { + max = max.add(0, -modifier.getY(), 0); + } + if (modifier.getZ() < 0) { + min = min.add(0, 0, -modifier.getZ()); + } else { + max = max.add(0, 0, -modifier.getZ()); + } + } + + public boolean canShrinkWithoutHittingOtherSide(BlockPos modifier){ + if (modifier.getX() < 0) { + if (min.getX() - modifier.getX() > max.getX()) return false; + } else { + if (max.getX() - modifier.getX() < min.getX()) return false; + } + if (modifier.getY() < 0) { + if (min.getY() - modifier.getY() > max.getY()) return false; + } else { + if (max.getY() - modifier.getY() < min.getY()) return false; + } + if (modifier.getZ() < 0) { + if (min.getZ() - modifier.getZ() > max.getZ()) return false; + } else { + if (max.getZ() - modifier.getZ() < min.getZ()) return false; + } + return true; + } + + public void expand(Direction direction, int distance) { + expand(new BlockPos(direction.getOffsetX() * distance, direction.getOffsetY() * distance, direction.getOffsetZ() * distance)); + } + public void shrink(Direction direction, int distance) { + shrink(new BlockPos(direction.getOffsetX() * distance, direction.getOffsetY() * distance, direction.getOffsetZ() * distance)); + } + public int getArea() { + return getSize().getX() * (ItsMineConfig.main().claims2d ? 1 : getSize().getY()) * getSize().getZ(); + } + + + public CompoundTag toTag() { + CompoundTag tag = new CompoundTag(); + { + CompoundTag pos = new CompoundTag(); + pos.putInt("minX", min.getX()); + pos.putInt("minY", min.getY()); + pos.putInt("minZ", min.getZ()); + pos.putInt("maxX", max.getX()); + pos.putInt("maxY", max.getY()); + pos.putInt("maxZ", max.getZ()); + pos.putString("dimension", WorldUtil.getDimensionNameWithNameSpace(dimension)); + if (tpPos != null) { + pos.putInt("tpX", this.tpPos.getX()); + pos.putInt("tpY", this.tpPos.getY()); + pos.putInt("tpZ", this.tpPos.getZ()); + } + tag.put("position", pos); + } + { + if(!isChild){ + ListTag subzoneList = new ListTag(); + children.forEach(it -> subzoneList.add(it.toTag())); + tag.put("subzones", subzoneList); + } + } + { + CompoundTag rent1 = new CompoundTag(); + { + CompoundTag rented = new CompoundTag(); + if(rent.getTenant() != null) rented.putUuidNew("tenant", rent.getTenant()); + if(rent.getRentedUntil() != 0) rented.putInt("rentedUntil", rent.getRentedUntil()); + + { + if(rent.getRevenue() != null){ + CompoundTag revenue = new CompoundTag(); + int i = 0; + for(ItemStack itemStack : rent.getRevenue()){ + CompoundTag revenueTag = new CompoundTag(); + itemStack.toTag(revenueTag); + i++; + revenue.put(String.valueOf(i), revenueTag); + rent1.put("revenue", revenue); + } + } + } + rent1.put("rented", rented); + } + { + CompoundTag rentable = new CompoundTag(); + rentable.putBoolean("rentable", rent.isRentable()); + CompoundTag currency = new CompoundTag(); + if(rent.getCurrency() != ItemStack.EMPTY) rent.getCurrency().toTag(currency); + if(rent.getRentAbleTime() != 0) rentable.putInt("rentTime", rent.getRentAbleTime()); + if(rent.getMaxrentAbleTime() != 0) rentable.putInt("maxrentTime", rent.getMaxrentAbleTime()); + + rent1.put("rentable", rentable); + rentable.put("currency", currency); + } + tag.put("rent", rent1); + + } + { + tag.put("flags", flags.toTag()); + tag.put("permissions", permissionManager.toNBT()); + if(claimBlockOwner != null) tag.putUuidNew("top_owner", claimBlockOwner); + + } + { + CompoundTag meta = new CompoundTag(); + if (this.enterMessage != null) meta.putString("enterMsg", this.enterMessage); + if (this.leaveMessage != null) meta.putString("leaveMsg", this.leaveMessage); + tag.put("meta", meta); + } + + if (this.customOwnerName != null) tag.putString("cOwnerName", this.customOwnerName); + tag.putString("name", name); + return tag; + } + public void fromTag(CompoundTag tag) { + System.out.println("Loading claim"); + { + CompoundTag pos = tag.getCompound("position"); + int minX = pos.getInt("minX"); + int minY = pos.getInt("minY"); + int minZ = pos.getInt("minZ"); + int maxX = pos.getInt("maxX"); + int maxY = pos.getInt("maxY"); + int maxZ = pos.getInt("maxZ"); + if (maxY == 0) maxY = 255; + this.min = new BlockPos(minX, minY, minZ); + this.max = new BlockPos(maxX, maxY, maxZ); + if (pos.contains("tpX") && pos.contains("tpY") && pos.contains("tpZ")) { + this.tpPos = new BlockPos(pos.getInt("tpX"), pos.getInt("tpY"), pos.getInt("tpZ")); + } + + this.dimension = WorldUtil.getDimensionType(pos.getString("dimension")); + } + { + if(!isChild){ + children = new ArrayList<>(); + ListTag subzoneList = (ListTag) tag.get("subzones"); + if (subzoneList != null) { + subzoneList.forEach(it -> { + Claim claim = new Claim((CompoundTag) it); + claim.isChild = true; + children.add(claim); + }); + } + } + } + { + CompoundTag rent1 = tag.getCompound("rent"); + { + CompoundTag rented = rent1.getCompound("rented"); + if (containsUUID(rented, "tenant")) rent.setTenant(getUUID(rented,"tenant")); + if(rented.contains("rentedUntil")) rent.setRentedUntil(rented.getInt("rentedUntil")); + } + { + CompoundTag rentable = rent1.getCompound("rentable"); + CompoundTag currency = rentable.getCompound("currency"); + if(rentable.contains("rentable")) rent.setRentable(rentable.getBoolean("rentable")); + if(currency != null) rent.setCurrency(ItemStack.fromTag(currency)); + if(rentable.contains("rentTime")) rent.setRentAbleTime(rentable.getInt("rentTime")); + if(rentable.contains("maxrentTime")) rent.setMaxrentAbleTime(rentable.getInt("maxrentTime")); + } + { + CompoundTag revenue = rent1.getCompound("revenue"); + if(!revenue.isEmpty()){ + for(int i = 1; i <= revenue.getSize(); i++){ + CompoundTag revenueTag = revenue.getCompound(String.valueOf(i)); + rent.addRevenue(ItemStack.fromTag(revenueTag)); + } + } + } + } + { + CompoundTag flags = tag.getCompound("flags"); + if(!flags.isEmpty()){ + this.flags = new ClaimFlags(flags); + } + CompoundTag settings = tag.getCompound("settings"); + if(!settings.isEmpty()){ + this.flags = new ClaimFlags(settings); + } + permissionManager = new PermissionManager(); + permissionManager.fromNBT(tag.getCompound("permissions")); + if (containsUUID(tag, "top_owner")) claimBlockOwner = getUUID(tag,"top_owner"); + + } + { + CompoundTag meta = tag.getCompound("meta"); + if (meta.contains("enterMsg")) this.enterMessage = meta.getString("enterMsg"); + if (meta.contains("leaveMsg")) this.leaveMessage = meta.getString("leaveMsg"); + } + if (tag.contains("cOwnerName")) this.customOwnerName = tag.getString("cOwnerName"); + name = tag.getString("name"); + } + + public boolean is2d() { + return min.getY() == 0 && max.getY() == 255; + } + + public void endRent(){ + permissionManager.playerPermissions.put(rent.getTenant(), new Claim.DefaultPermissionMap()); + rent.setRentedUntil(0); + rent.setTenant(null); + } + + public enum Permission { + //Admin + REMOVE_CLAIM("remove_claim", "Remove Claim"), + MODIFY_SIZE("modify.size", "Modify Claim Size"), + MODIFY_SETTINGS("modify.flags", "Change Claim Flags"), + MODIFY_PERMISSIONS("modify.permissions", "Change Permissions"), + //Normal + MODIFY_PROPERTIES("modify.properties", "Modify Claim Properties"), + MODIFY_SUBZONE("modify.subzone", "Add subzones"), + MOVE("move", "Move inside claim"), + BUILD("build", "Place/Break Blocks"), + INTERACT_BLOCKS("interact_blocks", "Interact With Blocks"), + USE_ITEMS_ON_BLOCKS("use_items_on_blocks", "Use Block Modifying items"), + USE_LEVERS("use.levers", "Use Levers"), + INTERACT_DOORS("interact_doors", "Use Doors"), + INTERACT_ENTITY("interact_entity", "Entity Interaction"), + INTERACT_LECTERN("interact_lectern", "Lectern Interaction"), + DAMAGE_ENTITY("damage_entities", "Hurt Entities"), + DAMAGE_ENTITY_HOSTILE("damage_entities.hostile", "Hurt Hostile Entities"), + DAMAGE_ENTITY_PASSIVE("damage_entities.passive", "Hurt Passive Entities"), + FLIGHT("flight", "Flight"), + CONTAINER("container", "Open Containers"), + CONTAINER_ENDERCHEST("container.enderchest", "Open Enderchests"), + CONTAINER_CHEST("container.chest", "Open Chests"), + CONTAINER_SHULKERBOX("container.shulkerbox", "Open Shulker Boxes"), + USE_ENDER_PEARL("use.enderpearl", "Use Ender Pearls"), + USE_BUTTONS("use.button", "Use Buttons"), + SPAWN_BOAT("spawn.boat", "Spawn Boats"); + + + public String id; + public String name; + Permission(String id, String name) { + this.id = id; + this.name = name; + } + public static Permission byId(String id) { + for (Permission permission: values()) { + if (permission.id.equals(id)) return permission; + } + return null; + } + } + + public class Rent { + + public UUID tenant = null; + public boolean rentable = false; + + public int rentTime = 0; + public int maxrentTime = 0; + public ArrayList revenue = new ArrayList<>(); + + + public ArrayList getRevenue() { + return revenue; + } + + public void addRevenue(ItemStack revenue) { + this.revenue.add(revenue); + } + + public void clearRevenue() { + revenue.clear(); + } + + //Payement + public ItemStack currency = ItemStack.EMPTY; + + public int rentedUntil = 0; + + public void setRentTime(int rentTime) { this.rentTime = rentTime; } + + //Max rent time + public int getMaxrentAbleTime() { return maxrentTime; } + public boolean isRented() { return rentedUntil != 0; } + + public void setMaxrentAbleTime(int maxrentTime) { this.maxrentTime = maxrentTime; } + + public int getRentedUntil() { + return rentedUntil; + } + + public void setRentedUntil(int rentedUntil) { + this.rentedUntil = rentedUntil; + } + + public int getRentTimeLeft(){ + return rentedUntil - getUnixTime(); + } + + public int getRentAbleTime() { return rentTime; } + + public void setRentAbleTime(int rentTime) { this.rentTime = rentTime; } + + //Returns seconds passed (Unix time) + public int getUnixTime(){ + return (int) (System.currentTimeMillis() / 1000); + } + + public void addRentTimeLeft(int rent){ + rentedUntil = rentedUntil + rent; + } + + public void removeRentTimeLeft(int rent){ addRentTimeLeft(-rent); } + + public void setRentTimeLeft(int time) { rentedUntil = getUnixTime() + time; } + + public UUID getTenant() { return tenant; } + + public void setTenant(UUID tenant) { this.tenant = tenant; } + + public boolean isRentable() { return rentable; } + + public void setRentable(boolean rentable) { this.rentable = rentable; } + + public int getAmount() { return currency.getCount(); } + + public void setAmount(int amount) { currency.setCount(amount); } + + public ItemStack getCurrency() { return currency; } + + public void setCurrency(ItemStack currency) { this.currency = currency; } + } + + public static class PermissionManager { + public ClaimPermissionMap defaults = new DefaultPermissionMap(); + public Map playerPermissions = new HashMap<>(); + public Map groupPermissions = new HashMap<>(); + public boolean isPermissionSet(UUID player, Permission permission) { + return playerPermissions.get(player) != null && playerPermissions.get(player).isPermissionSet(permission); + } + public boolean hasPermission(UUID player, Permission permission) { + if (isPermissionSet(player, permission)) + return playerPermissions.get(player).hasPermission(permission); + + for (Map.Entry entry : groupPermissions.entrySet()) { +// if (Thimble.PERMISSIONS.hasPermission(entry.getKey(), player) && entry.getValue().hasPermission(permission)) +// return true; + return ItsMine.permissions().hasPermission(player, entry.getKey()) && entry.getValue().hasPermission(permission); + } + + return defaults.hasPermission(permission); + } + public void setPermission(UUID player, Permission permission, boolean enabled) { + if (!playerPermissions.containsKey(player)) playerPermissions.put(player, new DefaultPermissionMap()); + playerPermissions.get(player).setPermission(permission, enabled); + } + public void clearPermission(UUID player, Permission permission) { + if (!playerPermissions.containsKey(player)) playerPermissions.put(player, new DefaultPermissionMap()); + playerPermissions.get(player).clearPermission(permission); + } + public void resetPermissions(UUID player) { + playerPermissions.remove(player); + } +// public boolean isPermissionSet(String group, Permission permission) { +// return groupPermissions.get(group) != null && groupPermissions.get(group).isPermissionSet(permission); +// } +// public boolean hasPermission(String group, Permission permission) { +// if (isPermissionSet(group, permission)) return groupPermissions.get(group).hasPermission(permission); +// return defaults.hasPermission(permission); +// } + public void setPermission(String group, Permission permission, boolean enabled) { + if (!groupPermissions.containsKey(group)) groupPermissions.put(group, new DefaultPermissionMap()); + groupPermissions.get(group).setPermission(permission, enabled); + } + public void clearPermission(String group, Permission permission) { + if (!groupPermissions.containsKey(group)) groupPermissions.put(group, new DefaultPermissionMap()); + groupPermissions.get(group).clearPermission(permission); + } + public void resetPermissions(String group) { + groupPermissions.remove(group); + } + public CompoundTag toNBT() { + CompoundTag tag = new CompoundTag(); + tag.put("defaults", defaults.toRegisteredNBT()); + { + CompoundTag players = new CompoundTag(); + if (playerPermissions != null) playerPermissions.forEach((player, map) -> {if (player != null && map != null) players.put(player.toString(), map.toRegisteredNBT());}); + tag.put("players", players); + } + { + CompoundTag groups = new CompoundTag(); + groupPermissions.forEach((group, map) -> groups.put(group, map.toRegisteredNBT())); + tag.put("groups", groups); + } + return tag; + } + public void fromNBT(CompoundTag tag) { + defaults = ClaimPermissionMap.fromRegisteredNBT(tag.getCompound("defaults")); + { + CompoundTag players = tag.getCompound("players"); + playerPermissions.clear(); + players.getKeys().forEach(player -> playerPermissions.put(UUID.fromString(player), ClaimPermissionMap.fromRegisteredNBT(players.getCompound(player)))); + } + { + CompoundTag groups = tag.getCompound("groups"); + groupPermissions.clear(); + groups.getKeys().forEach(group -> groupPermissions.put(group, ClaimPermissionMap.fromRegisteredNBT(groups.getCompound(group)))); + } + } + } + public static abstract class ClaimPermissionMap { + protected static HashMap> mapTypes = new HashMap<>(); + protected static HashMap, String> reverseMapTypes = new HashMap<>(); + static { + mapTypes.put("default", DefaultPermissionMap.class); + reverseMapTypes.put(DefaultPermissionMap.class, "default"); + mapTypes.put("inverted", InvertedPermissionMap.class); + reverseMapTypes.put(InvertedPermissionMap.class, "inverted"); + } + public abstract boolean isPermissionSet(Permission permission); + public abstract boolean hasPermission(Permission permission); + public abstract void setPermission(Permission permission, boolean has); + public abstract void clearPermission(Permission permission); + public abstract void fromNBT(CompoundTag tag); + public abstract CompoundTag toNBT(); + public CompoundTag toRegisteredNBT() { + CompoundTag tag = toNBT(); + tag.putString("type", reverseMapTypes.get(this.getClass())); + return tag; + } + public static ClaimPermissionMap fromRegisteredNBT(CompoundTag tag) { + String type = tag.getString("type"); + tag.remove("type"); + Class clazz = mapTypes.get(type); + if (clazz == null) return new DefaultPermissionMap(); + try { + ClaimPermissionMap map = clazz.newInstance(); + map.fromNBT(tag); + return map; + } catch (InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } + } + public static class DefaultPermissionMap extends ClaimPermissionMap { + private HashMap permissions = new HashMap<>(); + @Override + public boolean isPermissionSet(Permission permission) { + return permissions.containsKey(permission); + } + + @Override + public boolean hasPermission(Permission permission) { + return isPermissionSet(permission) && permissions.get(permission); + } + + @Override + public void setPermission(Permission permission, boolean has) { + permissions.put(permission, has); + } + + @Override + public void clearPermission(Permission permission) { + permissions.remove(permission); + } + + @Override + public void fromNBT(CompoundTag tag) { + permissions.clear(); + for (String permissionString : tag.getKeys()) { + Permission permission = Permission.byId(permissionString); + if (permission == null) continue; + boolean allowed = tag.getBoolean(permissionString); + permissions.put(permission, allowed); + } + } + + @Override + public CompoundTag toNBT() { + CompoundTag tag = new CompoundTag(); + permissions.forEach((permission, allowed) -> { + if (allowed != null) tag.putBoolean(permission.id, allowed); + }); + return tag; + } + } + public static class InvertedPermissionMap extends ClaimPermissionMap { + + private HashMap permissions = new HashMap<>(); + @Override + public boolean isPermissionSet(Permission permission) { + return true; + } + + @Override + public boolean hasPermission(Permission permission) { + return !permissions.containsKey(permission) || permissions.get(permission); + } + + @Override + public void setPermission(Permission permission, boolean has) { + permissions.put(permission, has); + } + + @Override + public void clearPermission(Permission permission) { + permissions.remove(permission); + } + + @Override + public void fromNBT(CompoundTag tag) { + permissions.clear(); + for (String permissionString : tag.getKeys()) { + Permission permission = Permission.byId(permissionString); + if (permission == null) continue; + boolean allowed = tag.getBoolean(permissionString); + permissions.put(permission, allowed); + } + } + + @Override + public CompoundTag toNBT() { + CompoundTag tag = new CompoundTag(); + permissions.forEach((permission, allowed) -> { + if (allowed != null) tag.putBoolean(permission.id, allowed); + }); + return tag; + } + } + public enum Event { + ENTER_CLAIM("enter", ItsMineConfig.main().message().enterDefault), + LEAVE_CLAIM("leave", ItsMineConfig.main().message().leaveDefault); + + public String id; + String defaultValue; + Event(String id, String defaultValue) { + this.id = id; + this.defaultValue = defaultValue; + } + + @Nullable + public static Event getById(String id) { + for (Event value : values()) { + if (value.id.equalsIgnoreCase(id)) { + return value; + } + } + + return null; + } + } + + public enum HelpBook { + GET_STARTED("getStarted", Messages.GET_STARTED, "Get Started"), + COMMAND("commands", Messages.HELP, "Claim Commands"), + PERMS_AND_SETTINGS("perms_and_flags", Messages.SETTINGS_AND_PERMISSIONS, "Claim Permissions and Flags"); + + public String id; + public String title; + public Text[] texts; + HelpBook(String id, Text[] texts, String title) { + this.id = id; + this.title = title; + this.texts = texts; + } + + public String getCommand() { + return "/claim help " + this.id + " %page%"; + } + + @Nullable + public static HelpBook getById(String id) { + for (HelpBook value : values()) { + if (value.id.equalsIgnoreCase(id)) { + return value; + } + } + + return null; + } + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/claim/ClaimFlags.java b/src/main/java/io/github/indicode/fabric/itsmine/claim/ClaimFlags.java new file mode 100644 index 0000000..9b5994a --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/claim/ClaimFlags.java @@ -0,0 +1,62 @@ +package io.github.indicode.fabric.itsmine.claim; + +import net.minecraft.nbt.CompoundTag; + +import java.util.HashMap; +import java.util.Map; + +public class ClaimFlags{ + public enum Flag { + FLIGHT_ALLOWED("flight_allowed", "Flying Allowed", true), + EXPLOSION_DESTRUCTION("explosion_destruction", "Explosion Destroys Blocks", false), + EXPLOSION_DAMAGE("explosion_damage", "Explosion Damages Entities", false), + FLUID_CROSSES_BORDERS("fluid_crosses_borders", "Fluid Crosses Borders", false), + FIRE_CROSSES_BORDERS("fire_crosses_borders", "Fire Crosses Borders", false), + FIRE_DAMAGE("fire_damage", "Fire Damages Entities", false), + PISTON_FROM_INSIDE("pistons_inside_border", "Pistons Cross border from Inside", true), + PISTON_FROM_OUTSIDE("pistons_outside_border", "Pistons Cross border from Outside", false), + MOB_SPAWNING("mob_spawn", "Natural mob spawning", true), + // KEEP_INVENTORY("keep_inventory", "Keep Inventory", true), + ENTER_SOUND("enter_sound", "Enter Sound", false), + BREAK_FARMLANDS("break_farmlands", "Break Farmlands", false); + + public String id, name; + boolean defaultValue; + + Flag(String id, String name, boolean defaultValue) { + this.id = id; + this.name = name; + this.defaultValue = defaultValue; + } + public static Flag byId(String id) { + for (Flag permission: values()) { + if (permission.id.equals(id)) return permission; + } + return null; + } + } + public Map flags = new HashMap<>(); + public ClaimFlags(CompoundTag tag) { + fromTag(tag); + } + public ClaimFlags() { + } + public boolean getFlag(Flag flag) { + return flags.getOrDefault(flag, flag.defaultValue); + } + public CompoundTag toTag() { + CompoundTag tag = new CompoundTag(); + this.flags.forEach((flag, data) -> { + tag.putBoolean(flag.id, data); + }); + return tag; + } + public void fromTag(CompoundTag tag) { + flags.clear(); + tag.getKeys().forEach(key -> { + Flag flag = Flag.byId(key); + if (flag == null) return; + this.flags.put(flag, tag.getBoolean(key)); + }); + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/BlockCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/BlockCommand.java new file mode 100644 index 0000000..7d6bdca --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/BlockCommand.java @@ -0,0 +1,43 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.util.PermissionUtil; +import net.minecraft.command.EntitySelector; +import net.minecraft.command.arguments.EntityArgumentType; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Style; +import net.minecraft.util.Formatting; + +import java.util.UUID; + +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class BlockCommand { + + static void register(LiteralArgumentBuilder command) { + LiteralArgumentBuilder check = literal("blocks"); + RequiredArgumentBuilder other = argument("player", EntityArgumentType.player()); + other.requires(source -> ItsMine.permissions().hasPermission(source, PermissionUtil.Command.ADMIN_CHECK_OTHERS, 2)); + other.executes(ctx -> blocksLeft(ctx.getSource(), EntityArgumentType.getPlayer(ctx, "player").getGameProfile().getId())); + check.then(other); + check.executes(ctx -> blocksLeft(ctx.getSource())); + command.then(check); + } + + static int blocksLeft(ServerCommandSource source, UUID player) throws CommandSyntaxException { + int blocks = ClaimManager.INSTANCE.getClaimBlocks(player); + source.sendFeedback(new LiteralText((source.getPlayer().getGameProfile().getId().equals(player) ? "You have " : "They have ") + blocks + " blocks left").formatted(Formatting.YELLOW), false); + return 1; + } + static int blocksLeft(ServerCommandSource source) throws CommandSyntaxException { + int blocks = ClaimManager.INSTANCE.getClaimBlocks(source.getPlayer().getUuid()); + source.sendFeedback(new LiteralText("You have " + blocks + " blocks left").formatted(Formatting.YELLOW), false); + return 1; + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/ClaimsCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/ClaimsCommand.java new file mode 100644 index 0000000..f037a56 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/ClaimsCommand.java @@ -0,0 +1,65 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.authlib.GameProfile; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.Messages; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.*; +import net.minecraft.util.Formatting; + +import java.util.List; + +import static net.minecraft.server.command.CommandManager.literal; + +public class ClaimsCommand { + public static void register(LiteralArgumentBuilder command, CommandDispatcher dispatcher) { + LiteralArgumentBuilder claims = literal("claims"); + claims.executes(context -> list(context.getSource(), context.getSource().getName())); + dispatcher.register(claims); + } + + public static int list(ServerCommandSource source, String target) throws CommandSyntaxException { + ServerPlayerEntity player = source.getPlayer(); + GameProfile profile = target == null ? player.getGameProfile() : source.getMinecraftServer().getUserCache().findByName(target); + + if (profile == null) { + source.sendError(Messages.INVALID_PLAYER); + return -1; + } + + List claims = ClaimManager.INSTANCE.getPlayerClaims(profile.getId()); + if (claims.isEmpty()) { + source.sendFeedback(new LiteralText("No Claims").formatted(Formatting.RED), false); + return -1; + } + + + MutableText text = new LiteralText("\n").append(new LiteralText("Claims (" + target + "): ").formatted(Formatting.GOLD)).append("\n "); + boolean nextColor = false; + for (Claim claim : claims) { + if(!claim.isChild) { + MutableText cText = new LiteralText(claim.name).formatted(nextColor ? Formatting.YELLOW : Formatting.GOLD).styled((style) -> { + MutableText hoverText = new LiteralText("Click for more Info").formatted(Formatting.GREEN); + if (claim.children.size() > 0) { + hoverText.append("\n\nSubzones:"); + for (Claim subzone : claim.children) { + hoverText.append("\n- " + subzone.name); + } + } + return style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/claim info " + claim.name)).setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverText)); + }); + + nextColor = !nextColor; + text.append(cText.append(" ")); + } + } + + source.sendFeedback(text.append("\n"), false); + return 1; + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/CommandManager.java b/src/main/java/io/github/indicode/fabric/itsmine/command/CommandManager.java new file mode 100644 index 0000000..9f76f6a --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/CommandManager.java @@ -0,0 +1,54 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import io.github.indicode.fabric.itsmine.ItsMineConfig; +import io.github.indicode.fabric.itsmine.command.admin.AdminCommand; +import io.github.indicode.fabric.itsmine.command.subzone.SubzoneCommand; +import net.minecraft.server.command.ServerCommandSource; + +import static io.github.indicode.fabric.itsmine.util.ArgumentUtil.getClaims; + + +public class CommandManager { + + public static CommandDispatcher dispatcher; + + + public static void register() { + LiteralArgumentBuilder main = LiteralArgumentBuilder.literal("itsmine"); + LiteralArgumentBuilder alias = LiteralArgumentBuilder.literal("claim"); + register(main, dispatcher); + register(alias, dispatcher); + dispatcher.register(main); + dispatcher.register(alias); + } + + + public static void register(LiteralArgumentBuilder command, CommandDispatcher dispatcher) { + AdminCommand.register(command, dispatcher); + BlockCommand.register(command); + CreateCommand.register(command); + ClaimsCommand.register(command, dispatcher); +// DebugCommand.register(command); + ExpandCommand.register(command, false); + FlyCommand.register(command); + HelpCommand.register(command); + InfoCommand.register(command, getClaims()); + ListCommand.register(command); + MessageCommand.register(command, false, getClaims()); + PermissionCommand.register(command, false, getClaims()); + RemoveCommand.register(command, getClaims(), false); + RenameCommand.register(command, false); + RentableCommand.register(command, getClaims()); + RentCommand.register(command, getClaims()); + RevenueCommand.register(command, getClaims()); + FlagsCommand.register(command, false, getClaims()); + ShowCommand.register(command); + StickCommand.register(command); + SubzoneCommand.register(command, dispatcher, false); + TransferCommand.register(command); + TrustCommand.register(command, dispatcher, getClaims(), false); + TrustedCommand.register(command); + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/CreateCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/CreateCommand.java new file mode 100644 index 0000000..ba50dc5 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/CreateCommand.java @@ -0,0 +1,132 @@ +package io.github.indicode.fabric.itsmine.command; + +import blue.endless.jankson.annotation.Nullable; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.*; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.util.PermissionUtil; +import net.minecraft.command.arguments.BlockPosArgumentType; +import net.minecraft.command.arguments.PosArgument; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.HoverEvent; +import net.minecraft.text.LiteralText; +import net.minecraft.text.MutableText; +import net.minecraft.util.Formatting; +import net.minecraft.util.Pair; +import net.minecraft.util.math.BlockPos; + +import java.util.UUID; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static com.mojang.brigadier.arguments.StringArgumentType.word; +import static io.github.indicode.fabric.itsmine.command.ShowCommand.executeShowClaim; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class CreateCommand { + static void register(LiteralArgumentBuilder command) { + LiteralArgumentBuilder create = literal("create"); + RequiredArgumentBuilder name = argument("name", word()); + + name.executes(context -> { + ServerPlayerEntity player = context.getSource().getPlayer(); + Pair selectedPositions = ClaimManager.INSTANCE.stickPositions.get(player); + if (selectedPositions == null) { + context.getSource().sendFeedback(new LiteralText("You need to specify block positions or select them with a stick.").formatted(Formatting.RED), false); + } else if (selectedPositions.getLeft() == null) { + context.getSource().sendFeedback(new LiteralText("You need to specify block positions or select position #1(Right Click) with a stick.").formatted(Formatting.RED), false); + } else if (selectedPositions.getRight() == null) { + context.getSource().sendFeedback(new LiteralText("You need to specify block positions or select position #2(Left Click) with a stick.").formatted(Formatting.RED), false); + } else { + String cname = getString(context, "name"); + if (createClaim(cname, context.getSource(), selectedPositions.getLeft(), selectedPositions.getRight(), false, null) > 0) { + ClaimManager.INSTANCE.stickPositions.remove(player); + } + } + return 0; + }); + + ArgumentBuilder min = argument("min", BlockPosArgumentType.blockPos()); + RequiredArgumentBuilder max = argument("max", BlockPosArgumentType.blockPos()); + max.executes(context -> createClaim(getString(context, "name"), context.getSource(), BlockPosArgumentType.getBlockPos(context, "min"), BlockPosArgumentType.getBlockPos(context, "max"), false, null)); + min.then(max); + name.then(min); + create.then(name); + command.then(create); + } + + public static int createClaim(String name, ServerCommandSource owner, BlockPos posA, BlockPos posB, boolean admin, @Nullable String cOwnerName) throws CommandSyntaxException { + if (name.length() > 30) { + owner.sendError(Messages.MSG_LONG_NAME); + return -1; + } + if(!name.matches("[A-Za-z0-9]+")){ + owner.sendError(new LiteralText("Invalid claim name")); + return -1; + } + UUID ownerID = owner.getPlayer().getGameProfile().getId(); + int x, y = 0, z, mx, my = 255, mz; + if (posA.getX() > posB.getX()) { + x = posB.getX(); + mx = posA.getX(); + } else { + x = posA.getX(); + mx = posB.getX(); + } + if (!ItsMineConfig.main().claims2d) { + if (posA.getY() > posB.getY()) { + y = posB.getY(); + my = posA.getY(); + } else { + y = posA.getY(); + my = posB.getY(); + } + } + if (posA.getZ() > posB.getZ()) { + z = posB.getZ(); + mz = posA.getZ(); + } else { + z = posA.getZ(); + mz = posB.getZ(); + } + BlockPos min = new BlockPos(x, y, z); + BlockPos max = new BlockPos(mx, my, mz); + BlockPos sub = max.subtract(min); + sub = sub.add(1, ItsMineConfig.main().claims2d ? 0 : 1,1); + int subInt = sub.getX() * (ItsMineConfig.main().claims2d ? 1 : sub.getY()) * sub.getZ(); + + Claim claim = new Claim(name, admin ? null : ownerID, min, max, owner.getWorld().getDimension(), owner.getPlayer().getBlockPos(), false); + if (cOwnerName != null) claim.customOwnerName = cOwnerName; + claim.permissionManager.playerPermissions.put(ownerID, new Claim.InvertedPermissionMap()); + if (!ClaimManager.INSTANCE.claimsByName.containsKey(name)) { + if (!ClaimManager.INSTANCE.wouldIntersect(claim)) { + // works because only the first statement is evaluated if true + if ((admin && ItsMine.permissions().hasPermission(owner, PermissionUtil.Command.INFINITE_BLOCKS, 2)) || ClaimManager.INSTANCE.useClaimBlocks(ownerID, subInt)) { + ClaimManager.INSTANCE.addClaim(claim); + MutableText message = new LiteralText(""); + message.append(new LiteralText("Your claim was created").formatted(Formatting.GREEN)); + message.append(new LiteralText("(Area: " + sub.getX() + "x" + sub.getY() + "x" + sub.getZ() + ")").styled(style -> { + return style.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new LiteralText(subInt + " blocks").formatted(Formatting.YELLOW))); + })); + owner.sendFeedback(message, false); + BlockCommand.blocksLeft(owner); + executeShowClaim(owner, claim, false); + if (admin) + owner.getMinecraftServer().sendSystemMessage(new LiteralText(owner.getPlayer().getGameProfile().getName() + " Has created a new claim(" + claim.name + ") using the admin command."), owner.getPlayer().getUuid()); + return 1; + } else { + owner.sendFeedback(new LiteralText("You don't have enough claim blocks. You have " + ClaimManager.INSTANCE.getClaimBlocks(ownerID) + ", you need " + subInt + "(" + (subInt - ClaimManager.INSTANCE.getClaimBlocks(ownerID)) + " more)").formatted(Formatting.RED), false); + } + } else { + owner.sendFeedback(new LiteralText("Your claim would overlap with another claim").formatted(Formatting.RED), false); + } + } else { + owner.sendFeedback(new LiteralText("The name \"" + name + "\" is already taken.").formatted(Formatting.RED), false); + } + return 0; + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/DebugCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/DebugCommand.java new file mode 100644 index 0000000..c0f1354 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/DebugCommand.java @@ -0,0 +1,35 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.ItsMine; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; + +import static io.github.indicode.fabric.itsmine.util.ChatColor.translateStringToText; + +public class DebugCommand { + + public static void register(LiteralArgumentBuilder command) { + LiteralArgumentBuilder debug = LiteralArgumentBuilder.literal("debug"); + RequiredArgumentBuilder string = RequiredArgumentBuilder.argument("string", StringArgumentType.greedyString()); + debug.executes(DebugCommand::execute); + debug.then(string); + command.then(debug); + + } + + private static int execute(CommandContext context) throws CommandSyntaxException { +// context.getSource().getPlayer().sendSystemMessage(translateStringToText('&', StringArgumentType.getString(context, "string"))); + ServerPlayerEntity player = context.getSource().getPlayer(); + player.sendSystemMessage(translateStringToText('&', "&eTime elapsed: &6" + ItsMine.time + "μs"), player.getUuid()); + player.sendSystemMessage(translateStringToText('&', "&eExecuted: &6" + ItsMine.executed), player.getUuid()); + player.sendSystemMessage(translateStringToText('&', "&eAverage: &6" + ItsMine.time / ItsMine.executed + "μs"), player.getUuid()); + + return 1; + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/ExpandCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/ExpandCommand.java new file mode 100644 index 0000000..4f07d40 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/ExpandCommand.java @@ -0,0 +1,173 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.util.ClaimUtil; +import io.github.indicode.fabric.itsmine.util.ShowerUtil; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; + +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static io.github.indicode.fabric.itsmine.command.BlockCommand.blocksLeft; +import static io.github.indicode.fabric.itsmine.util.ArgumentUtil.getDirections; +import static io.github.indicode.fabric.itsmine.util.DirectionUtil.directionByName; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class ExpandCommand { + + public static void register(LiteralArgumentBuilder command, boolean admin) { + { + LiteralArgumentBuilder expand = literal("expand"); + RequiredArgumentBuilder amount = argument("distance", IntegerArgumentType.integer(1, Integer.MAX_VALUE)); + RequiredArgumentBuilder direction = getDirections(); + + direction.executes(context -> expand( + ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getBlockPos(), context.getSource().getWorld().getDimension()), + IntegerArgumentType.getInteger(context, "distance"), + directionByName(getString(context, "direction")), + context.getSource(), + admin + )); + + amount.executes(context -> expand( + ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getBlockPos(), context.getSource().getWorld().getDimension()), + IntegerArgumentType.getInteger(context, "distance"), + Direction.getEntityFacingOrder(context.getSource().getPlayer())[0], + context.getSource(), + admin + )); + + amount.then(direction); + expand.then(amount); + command.then(expand); + } + { + LiteralArgumentBuilder shrink = literal("shrink"); + RequiredArgumentBuilder amount = argument("distance", IntegerArgumentType.integer(1, Integer.MAX_VALUE)); + RequiredArgumentBuilder direction = getDirections(); + + direction.executes(context -> expand( + ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getBlockPos(), context.getSource().getWorld().getDimension()), + -IntegerArgumentType.getInteger(context, "distance"), + directionByName(getString(context, "direction")), + context.getSource(), + admin + )); + + amount.executes(context -> expand( + ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getBlockPos(), context.getSource().getWorld().getDimension()), + -IntegerArgumentType.getInteger(context, "distance"), + Direction.getEntityFacingOrder(context.getSource().getPlayer())[0], + context.getSource(), + admin + )); + + amount.then(direction); + shrink.then(amount); + command.then(shrink); + } + } + + private static void undoExpand(Claim claim, Direction direction, int amount){ + if (amount < 0) claim.expand(direction, -amount); + else claim.shrink(direction, amount); + } + + public static int expand(Claim claim, int amount, Direction direction, ServerCommandSource source, boolean admin) throws CommandSyntaxException { + UUID ownerID = source.getPlayer().getGameProfile().getId(); + if (claim == null) { + source.sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); + return 0; + } + if (direction == null) { + source.sendFeedback(new LiteralText("That is not a valid direction").formatted(Formatting.RED), false); + return 0; + } + if (!claim.permissionManager.hasPermission(ownerID, Claim.Permission.MODIFY_SIZE)) { + source.sendFeedback(new LiteralText("You do not have border change permissions in that claim").formatted(Formatting.RED), false); + if (!admin) return 0; + } + int oldArea = claim.getArea(); + + + if (amount > 0) { + claim.expand(direction, amount); + } + else { + claim.shrink(direction, -amount); + } + + if (!claim.canShrinkWithoutHittingOtherSide(new BlockPos(direction.getOffsetX() * amount, direction.getOffsetY() * amount, direction.getOffsetZ() * amount))) { + source.sendFeedback(new LiteralText("You can't shrink your claim that far. It would pass its opposite wall.").formatted(Formatting.RED), false); + undoExpand(claim, direction, amount); + return 0; + } + + if(!claim.isChild){ + if (ClaimManager.INSTANCE.wouldIntersect(claim)) { + undoExpand(claim, direction, amount); + source.sendFeedback(new LiteralText("Expansion would result in hitting another claim").formatted(Formatting.RED), false); + return 0; + } + + //Check if shrinking would reset a subzone to be outside of its parent claim + AtomicBoolean returnValue = new AtomicBoolean(); + returnValue.set(false); + claim.children.forEach(claim1 -> { + if(!claim1.isInside(claim)){ + undoExpand(claim, direction, amount); + source.sendFeedback(new LiteralText("Shrinking would result in " + claim1.name + " being outside of " + claim.name).formatted(Formatting.RED), true); + returnValue.set(true); + } + }); + if(returnValue.get()) return 0; + + int newArea = claim.getArea() - oldArea; + if (!admin && claim.claimBlockOwner != null && ClaimManager.INSTANCE.getClaimBlocks(ownerID) < newArea) { + undoExpand(claim, direction, amount); + source.sendFeedback(new LiteralText("You don't have enough claim blocks. You have " + ClaimManager.INSTANCE.getClaimBlocks(ownerID) + ", you need " + newArea + "(" + (newArea - ClaimManager.INSTANCE.getClaimBlocks(ownerID)) + " more)").formatted(Formatting.RED), false); + blocksLeft(source); + return 0; + } else { + if (!admin && claim.claimBlockOwner != null) ClaimManager.INSTANCE.useClaimBlocks(ownerID, newArea); + source.sendFeedback(new LiteralText("Your claim was " + (amount > 0 ? "expanded" : "shrunk") + " by " + (amount < 0 ? -amount : amount) + (amount == 1 ? " block " : " blocks ") + direction.getName()).formatted(Formatting.GREEN), false); + blocksLeft(source); + undoExpand(claim, direction, amount); + ShowerUtil.update(claim, source.getWorld(), true); + if (amount > 0) claim.expand(direction, amount); + else claim.shrink(direction, -amount); + ShowerUtil.update(claim, source.getWorld(), false); + } + return 0; + }else{ + Claim parent = ClaimUtil.getParentClaim(claim); + if(!claim.isInside(parent)) { + source.sendFeedback(new LiteralText("Expansion would result in expanding outside of your main claim").formatted(Formatting.RED), false); + undoExpand(claim, direction, amount); + } else if(ClaimManager.INSTANCE.wouldSubzoneIntersect((claim))){ + source.sendFeedback(new LiteralText("Expansion would result in overlapping with another subzone").formatted(Formatting.RED), false); + undoExpand(claim, direction, amount); + }else{ + source.sendFeedback(new LiteralText("Your subzone was " + (amount > 0 ? "expanded" : "shrunk") + " by " + (amount < 0 ? -amount : amount) + " blocks " + direction.getName()).formatted(Formatting.GREEN), false); + //The expansion is undone to hide the claimshower + undoExpand(claim, direction, amount); + ShowerUtil.update(parent, source.getWorld(), true); + if (amount > 0) claim.expand(direction, amount); + else claim.shrink(direction, -amount); + ShowerUtil.update(parent, source.getWorld(), false); + } + } + return 0; + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/FlagsCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/FlagsCommand.java new file mode 100644 index 0000000..fdffe23 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/FlagsCommand.java @@ -0,0 +1,50 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.arguments.BoolArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.Messages; +import net.minecraft.server.command.ServerCommandSource; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static io.github.indicode.fabric.itsmine.command.HelpCommand.sendPage; +import static io.github.indicode.fabric.itsmine.util.ArgumentUtil.getFlags; +import static io.github.indicode.fabric.itsmine.util.ClaimUtil.executeFlag; +import static io.github.indicode.fabric.itsmine.util.ClaimUtil.queryFlags; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class FlagsCommand { + + public static void register(LiteralArgumentBuilder command, boolean admin, RequiredArgumentBuilder claim) { + LiteralArgumentBuilder flags = literal("flags"); + + if (!admin) { + flags.executes((context) -> sendPage(context.getSource(), Messages.SETTINGS_AND_PERMISSIONS, 1, "Claim Permissions and Flags", "/claim help perms_and_flags %page%")); + + claim.executes((context) -> { + Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")); + if (claim1 == null) { + context.getSource().sendError(Messages.INVALID_CLAIM); + return -1; + } + return queryFlags(context.getSource(), claim1); + }); + } + + RequiredArgumentBuilder id = getFlags(); + RequiredArgumentBuilder set = argument("set", BoolArgumentType.bool()); + + id.executes((context) -> executeFlag(context.getSource(), getString(context, "flag"), getString(context, "claim"), true, false, admin)); + set.executes((context) -> executeFlag(context.getSource(), getString(context, "flag"), getString(context, "claim"), false, BoolArgumentType.getBool(context, "set"), admin)); + + id.then(set); + claim.then(id); + flags.then(claim); + command.then(flags); + } + + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/FlyCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/FlyCommand.java new file mode 100644 index 0000000..c8e829e --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/FlyCommand.java @@ -0,0 +1,42 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.arguments.BoolArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.util.PermissionUtil; +import net.minecraft.server.command.CommandManager; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; + +import static net.minecraft.server.command.CommandManager.literal; + +public class FlyCommand { + static void register(LiteralArgumentBuilder command) { + LiteralArgumentBuilder fly = literal("fly"); + fly.requires(src -> ItsMine.permissions().hasPermission(src, PermissionUtil.Command.CLAIM_FLY, 2)); + RequiredArgumentBuilder setArgument = CommandManager.argument("set", BoolArgumentType.bool()); + fly.executes((context) -> executeSetFly(context, !ClaimManager.INSTANCE.flyers.contains(context.getSource().getPlayer().getUuid()))); + setArgument.executes((context) -> executeSetFly(context, BoolArgumentType.getBool(context, "set"))); + fly.then(setArgument); + command.then(fly); + } + + private static int executeSetFly(CommandContext context, boolean set) throws CommandSyntaxException { + ServerPlayerEntity player = context.getSource().getPlayer(); + if (set) { + ClaimManager.INSTANCE.flyers.add(player.getUuid()); + player.sendSystemMessage(new LiteralText("Enabled Ability to fly in Claims").formatted(Formatting.GREEN), player.getUuid()); + return 1; + } + + player.sendSystemMessage(new LiteralText("Disabled Ability to fly in Claims").formatted(Formatting.RED), player.getUuid()); + ClaimManager.INSTANCE.flyers.remove(player.getUuid()); + return -1; + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/HelpCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/HelpCommand.java new file mode 100644 index 0000000..97c223d --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/HelpCommand.java @@ -0,0 +1,101 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import io.github.indicode.fabric.itsmine.util.ChatColor; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.Messages; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.*; +import net.minecraft.util.Formatting; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static io.github.indicode.fabric.itsmine.util.ArgumentUtil.getHelpId; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class HelpCommand { + + public static void register(LiteralArgumentBuilder command) { + command.executes((context) -> sendPage(context.getSource(), Messages.GET_STARTED, 1, "Get Started", "/claim help getStarted %page%")); + + LiteralArgumentBuilder help = literal("help"); + help.executes((context) -> sendPage(context.getSource(), Messages.HELP, 1, "Its Mine!", "/claim help commands %page%")); + + RequiredArgumentBuilder id = getHelpId(); + RequiredArgumentBuilder page = argument("page", IntegerArgumentType.integer(1)); + + page.executes((context) -> { + Claim.HelpBook book = Claim.HelpBook.getById(getString(context, "id")); + if (book == null) { + context.getSource().sendError(new LiteralText("Invalid Book!")); + return -1; + } + int p = IntegerArgumentType.getInteger(context, "page"); + + if (p > book.texts.length) p = 1; + return sendPage(context.getSource(), book.texts, p, book.title, book.getCommand()); + }); + + id.then(page); + help.then(id); + command.then(help); + } + + public static int sendPage(ServerCommandSource source, Text[] text, int page, String title, String command) { + int prevPage = page - 2; + int thisPage = page - 1; + int nextPage = page + 1; + final String SEPARATOR = "-----------------------------------------------------"; + MutableText header = new LiteralText("") + .append(new LiteralText("- [ ").formatted(Formatting.GRAY)) + .append(new LiteralText(title).formatted(Formatting.GOLD)) + .append(new LiteralText(" ] ")) + .append(new LiteralText(SEPARATOR.substring(ChatColor.removeAlternateColorCodes('&', title).length() + 4))) + .formatted(Formatting.GRAY); + + Text button_prev = new LiteralText("") + .append(new LiteralText("<-").formatted(Formatting.WHITE).formatted(Formatting.BOLD)) + .append(new LiteralText(" ")).append(new LiteralText("Prev").formatted(Formatting.GOLD)) + .styled((style) -> { + if (prevPage >= 0){ + return style.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new LiteralText((prevPage >= 0) ? "<<<" : "|<").formatted(Formatting.GRAY))).withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command.replace("%page%", String.valueOf(page - 1)))); + } + return style.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new LiteralText((prevPage >= 0) ? "<<<" : "|<").formatted(Formatting.GRAY))); + }); + + Text button_next = new LiteralText("") + .append(new LiteralText("Next").formatted(Formatting.GOLD)) + .append(new LiteralText(" ")).append(new LiteralText("->").formatted(Formatting.WHITE).formatted(Formatting.BOLD)).append(new LiteralText(" ")) + .styled((style) -> { + if (nextPage <= text.length){ + return style.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new LiteralText((nextPage <= text.length) ? ">>>" : ">|").formatted(Formatting.GRAY))).withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command.replace("%page%", String.valueOf(nextPage)))); + } + return style.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new LiteralText((nextPage <= text.length) ? ">>>" : ">|").formatted(Formatting.GRAY))); + }); + + Text buttons = new LiteralText("") + .append(new LiteralText("[ ").formatted(Formatting.GRAY)) + .append(button_prev) + .append(new LiteralText(" ")) + .append( + new LiteralText(String.valueOf(page)).formatted(Formatting.GREEN) + .append(new LiteralText("/").formatted(Formatting.GRAY)) + .append(new LiteralText(String.valueOf(text.length)).formatted(Formatting.GREEN)) + ) + .append(new LiteralText(" ")) + .append(button_next) + .append(new LiteralText("] ").formatted(Formatting.GRAY)); + + Text footer = new LiteralText("- ") + .formatted(Formatting.GRAY) + .append(buttons).append(new LiteralText(" ------------------------------").formatted(Formatting.GRAY)); + + header.append(new LiteralText("\n")).append(text[thisPage]).append(new LiteralText("\n")).append(footer); + source.sendFeedback(header, false); + return 1; + } + + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/InfoCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/InfoCommand.java new file mode 100644 index 0000000..6e0ec94 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/InfoCommand.java @@ -0,0 +1,101 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.authlib.GameProfile; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.Messages; +import io.github.indicode.fabric.itsmine.util.TimeUtil; +import io.github.indicode.fabric.itsmine.util.WorldUtil; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.HoverEvent; +import net.minecraft.text.LiteralText; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.registry.Registry; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static net.minecraft.server.command.CommandManager.literal; + +public class InfoCommand { + public static void register(LiteralArgumentBuilder command, RequiredArgumentBuilder claim) { + LiteralArgumentBuilder info = literal("info"); + info.executes(context -> info( + context.getSource(), + ClaimManager.INSTANCE.getClaimAt(new BlockPos(context.getSource().getPosition()), context.getSource().getWorld().getDimension()) + )); + claim.executes(context -> info(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")) + )); + info.then(claim); + command.then(info); + } + + private static int info(ServerCommandSource source, Claim claim) throws CommandSyntaxException { + if (claim == null) { + source.sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); + return 0; + } + + GameProfile owner = claim.claimBlockOwner == null ? null : source.getMinecraftServer().getUserCache().getByUuid(claim.claimBlockOwner); + BlockPos size = claim.getSize(); + + MutableText text = new LiteralText("\n"); + text.append(new LiteralText("Claim Info: " + claim.name).formatted(Formatting.GOLD)).append(new LiteralText("\n")); + text.append(newInfoLine("Name", new LiteralText(claim.name).formatted(Formatting.WHITE))); + text.append(newInfoLine("Entities", new LiteralText(String.valueOf(claim.getEntities(source.getWorld()))).formatted(Formatting.AQUA))); + text.append(newInfoLine("Owner", + owner != null && claim.customOwnerName == null ? new LiteralText(owner.getName()).formatted(Formatting.GOLD) : + claim.customOwnerName != null ? new LiteralText(claim.customOwnerName).formatted(Formatting.GOLD) : + new LiteralText("No Owner").formatted(Formatting.RED).formatted(Formatting.ITALIC))); + text.append(newInfoLine("Size", new LiteralText(size.getX() + (claim.is2d() ? "x" : ("x" + size.getY() + "x")) + size.getZ()).formatted(Formatting.GREEN))); + + + text.append(new LiteralText("").append(new LiteralText("* Flags:").formatted(Formatting.YELLOW)) + .append(Messages.Command.getFlags(claim)).append(new LiteralText("\n"))); + MutableText pos = new LiteralText(""); + Text min = newPosLine(claim.min, Formatting.AQUA, Formatting.DARK_AQUA); + Text max = newPosLine(claim.max, Formatting.LIGHT_PURPLE, Formatting.DARK_PURPLE); + + + pos.append(newInfoLine("Position", new LiteralText("") + .append(new LiteralText("Min ").formatted(Formatting.WHITE).append(min)) + .append(new LiteralText(" ")) + .append(new LiteralText("Max ").formatted(Formatting.WHITE).append(max)))); + text.append(pos); + text.append(newInfoLine("Dimension", new LiteralText(WorldUtil.getDimensionName(claim.dimension)))); + if(claim.rent.isRented()){ + GameProfile tenant = claim.rent.getTenant() == null ? null : source.getMinecraftServer().getUserCache().getByUuid(claim.rent.getTenant()); + text.append(newInfoLine("Status", new LiteralText("Rented").formatted(Formatting.RED).styled(style -> { + java.util.Date time=new java.util.Date((long) claim.rent.getRentedUntil()*1000); + return style.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, newInfoLine("Until", new LiteralText(time.toString()).formatted(Formatting.WHITE)).append(newInfoLine("By", new LiteralText(tenant.getName()).formatted(Formatting.WHITE))).append(newInfoLine("Price", new LiteralText(claim.rent.getAmount() + " " + claim.rent.getCurrency().getName().asString() + " every " + TimeUtil.convertSecondsToString(claim.rent.getRentAbleTime(),'f', 'f')).formatted(Formatting.WHITE))))); + }))); + } else if (claim.rent.isRentable() && !claim.rent.isRented()){ + text.append(newInfoLine("Status", new LiteralText("For Rent").formatted(Formatting.GREEN).styled(style -> { + return style.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, newInfoLine("Price", new LiteralText(claim.rent.getAmount() + " " + claim.rent.getCurrency().getName().asString() + " every " + TimeUtil.convertSecondsToString(claim.rent.getRentAbleTime(),'f', 'f')).formatted(Formatting.WHITE)).append(newInfoLine("Max Rent", new LiteralText(claim.rent.getMaxrentAbleTime() / 86400 + " days")).formatted(Formatting.WHITE)))); + }))); + + } else { + text.append(newInfoLine("Status", new LiteralText("Not For Rent").formatted(Formatting.GREEN))); + + } + source.sendFeedback(text, false); + return 1; + } + + private static MutableText newPosLine(BlockPos pos, Formatting form1, Formatting form2) { + return new LiteralText("") + .append(new LiteralText(String.valueOf(pos.getX())).formatted(form1)) + .append(new LiteralText(" ")) + .append(new LiteralText(String.valueOf(pos.getY())).formatted(form2)) + .append(new LiteralText(" ")) + .append(new LiteralText(String.valueOf(pos.getZ())).formatted(form1)); + } + private static MutableText newInfoLine(String title, Text text) { + return new LiteralText("").append(new LiteralText("* " + title + ": ").formatted(Formatting.YELLOW)) + .append(text).append(new LiteralText("\n")); + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/ListCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/ListCommand.java new file mode 100644 index 0000000..55ed653 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/ListCommand.java @@ -0,0 +1,28 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.util.PermissionUtil; +import net.minecraft.server.command.ServerCommandSource; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static io.github.indicode.fabric.itsmine.command.ClaimsCommand.list; +import static io.github.indicode.fabric.itsmine.command.admin.AdminCommand.PERMISSION_CHECK_ADMIN; +import static io.github.indicode.fabric.itsmine.util.ArgumentUtil.getPlayers; +import static net.minecraft.server.command.CommandManager.literal; + +public class ListCommand { + + public static void register(LiteralArgumentBuilder command) { + LiteralArgumentBuilder list = literal("list"); + RequiredArgumentBuilder player = getPlayers(); + player.requires(source -> ItsMine.permissions().hasPermission(source, PermissionUtil.Command.ADMIN_CHECK_OTHERS, 2)); + list.executes(context -> list(context.getSource(), context.getSource().getName())); + player.requires(PERMISSION_CHECK_ADMIN); + player.executes(context -> list(context.getSource(), getString(context, "player"))); + list.then(player); + command.then(list); + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/MessageCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/MessageCommand.java new file mode 100644 index 0000000..b037bde --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/MessageCommand.java @@ -0,0 +1,45 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.Messages; +import net.minecraft.server.command.ServerCommandSource; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static io.github.indicode.fabric.itsmine.util.ArgumentUtil.getEventMessage; +import static io.github.indicode.fabric.itsmine.util.ArgumentUtil.getMessageEvent; +import static io.github.indicode.fabric.itsmine.util.ClaimUtil.setEventMessage; +import static io.github.indicode.fabric.itsmine.util.ClaimUtil.verifyPermission; +import static net.minecraft.server.command.CommandManager.literal; + +public class MessageCommand { + + public static void register(LiteralArgumentBuilder command, boolean admin, RequiredArgumentBuilder claim) { + LiteralArgumentBuilder message = literal("message"); + RequiredArgumentBuilder messageEvent = getMessageEvent(); + RequiredArgumentBuilder messageArgument = getEventMessage(); + messageArgument.executes(context -> { + Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")); + if (verifyPermission(claim1, Claim.Permission.MODIFY_PROPERTIES, context, admin)) { + Claim.Event event = Claim.Event.getById(getString(context, "messageEvent")); + + if (event == null) { + context.getSource().sendError(Messages.INVALID_MESSAGE_EVENT); + return -1; + } + + return setEventMessage(context.getSource(), claim1, event, getString(context, "message")); + } + + return -1; + }); + + messageEvent.then(messageArgument); + claim.then(messageEvent); + message.then(claim); + command.then(message); + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/PermissionCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/PermissionCommand.java new file mode 100644 index 0000000..df2f3df --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/PermissionCommand.java @@ -0,0 +1,110 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.arguments.BoolArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.Messages; +import net.minecraft.command.EntitySelector; +import net.minecraft.command.arguments.EntityArgumentType; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static io.github.indicode.fabric.itsmine.command.HelpCommand.sendPage; +import static io.github.indicode.fabric.itsmine.command.TrustCommand.setTrust; +import static io.github.indicode.fabric.itsmine.command.TrustedCommand.showTrustedList; +import static io.github.indicode.fabric.itsmine.util.ArgumentUtil.getPermissions; +import static io.github.indicode.fabric.itsmine.util.ClaimUtil.*; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class PermissionCommand { + + public static void register(LiteralArgumentBuilder command, boolean admin, RequiredArgumentBuilder claim) { + LiteralArgumentBuilder exception = literal("permissions"); + RequiredArgumentBuilder player = argument("player", EntityArgumentType.player()); + LiteralArgumentBuilder all = literal("*"); + RequiredArgumentBuilder allstate = argument("allow", BoolArgumentType.bool()); + RequiredArgumentBuilder permNode = getPermissions(); + RequiredArgumentBuilder allow = argument("allow", BoolArgumentType.bool()); + + exception.executes((context) -> sendPage(context.getSource(), Messages.SETTINGS_AND_PERMISSIONS, 1, "Claim Permissions and Flags", "/claim help perms_and_flags %page%")); + claim.executes((context) -> { + Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")); + if (claim1 == null) { + context.getSource().sendError(Messages.INVALID_CLAIM); + return -1; + } + return showTrustedList(context, claim1, false); + }); + + claim.executes((context) -> { + Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")); + if (claim1 == null) { + context.getSource().sendError(new LiteralText("That claim does not exist")); + return -1; + } + return showTrustedList(context, claim1, true); + }); + + allstate.executes(context -> { + Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")); + ServerPlayerEntity player1 = EntityArgumentType.getPlayer(context, "player"); + validateClaim(claim1); + return setTrust(context, claim1, player1.getGameProfile(), BoolArgumentType.getBool(context, "allow"), admin); + }); + + allow.executes(context -> allow(context, admin, BoolArgumentType.getBool(context, "allow"))); + permNode.executes(context -> query(context, admin)); + all.then(allstate); + permNode.then(allow); + player.then(permNode); + player.then(all); + claim.then(player); + exception.then(claim); + command.then(exception); + } + + private static int allow(CommandContext context, boolean admin, boolean allow) throws CommandSyntaxException { + ServerCommandSource source = context.getSource(); + Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")); + if (verifyPermission(claim1, Claim.Permission.MODIFY_PERMISSIONS, context, admin)) { + ServerPlayerEntity player1 = EntityArgumentType.getPlayer(context, "player"); + boolean permission = BoolArgumentType.getBool(context, "allow"); + Claim.Permission value = Claim.Permission.byId(StringArgumentType.getString(context, "permission")); + if(value == null) { + source.sendError(Messages.INVALID_PERMISSION); + return 0; + } + modifyException(claim1, player1, value, permission); + source.sendFeedback(new LiteralText(player1.getGameProfile().getName() + (permission ? " now" : " no longer") + " has the permission " + value).formatted(Formatting.YELLOW), false); + return 1; + } + return 0; + } + + private static int query(CommandContext context, boolean admin) throws CommandSyntaxException { + ServerCommandSource source = context.getSource(); + Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")); + if (verifyPermission(claim1, Claim.Permission.MODIFY_PERMISSIONS, context, admin)) { + ServerPlayerEntity player1 = EntityArgumentType.getPlayer(context, "player"); + Claim.Permission value = Claim.Permission.byId(StringArgumentType.getString(context, "permission")); + if(value == null) { + source.sendError(Messages.INVALID_PERMISSION); + return 0; + } + boolean permission = hasPermission(claim1, player1, value); + source.sendFeedback(new LiteralText(player1.getGameProfile().getName() + (permission ? " has" : " does not have") + " the permission " + value.name).formatted(Formatting.YELLOW), false); + return 1; + } + return 0; + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/RemoveCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/RemoveCommand.java new file mode 100644 index 0000000..5b50c63 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/RemoveCommand.java @@ -0,0 +1,90 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.ClaimShower; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.util.ClaimUtil; +import io.github.indicode.fabric.itsmine.util.PermissionUtil; +import io.github.indicode.fabric.itsmine.util.ShowerUtil; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.ClickEvent; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; +import net.minecraft.util.math.BlockPos; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static io.github.indicode.fabric.itsmine.util.ShowerUtil.silentHideShow; +import static net.minecraft.server.command.CommandManager.literal; + +public class RemoveCommand { + + public static void register(LiteralArgumentBuilder command, RequiredArgumentBuilder claim, boolean admin) { + LiteralArgumentBuilder delete = literal("remove"); + LiteralArgumentBuilder confirm = literal("confirm"); + confirm.executes(context -> delete(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")), admin)); + claim.executes(context -> requestDelete(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")), admin)); + claim.then(confirm); + delete.then(claim); + delete.executes(context -> requestDelete(context.getSource(), ClaimManager.INSTANCE.getClaimAt(new BlockPos(context.getSource().getPosition()), context.getSource().getWorld().getDimension()), admin)); + command.then(delete); + } + public static int requestDelete(ServerCommandSource sender, Claim claim, boolean admin) throws CommandSyntaxException { + if (claim == null) { + sender.sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); + return 0; + } + if (!claim.permissionManager.hasPermission(sender.getPlayer().getGameProfile().getId(), Claim.Permission.REMOVE_CLAIM)) { + if (admin && ItsMine.permissions().hasPermission(sender, PermissionUtil.Command.ADMIN_MODIFY, 2)) { + sender.sendFeedback(new LiteralText("WARNING: This is not your claim...").formatted(Formatting.DARK_RED).formatted(Formatting.BOLD), false); + } else { + sender.sendFeedback(new LiteralText("You cannot delete that claim").formatted(Formatting.RED), false); + return 0; + } + } + sender.sendFeedback(new LiteralText("").append(new LiteralText("Are you sure you want to delete the claim \"" + claim.name + "\"? ").formatted(Formatting.GOLD)) + .append(new LiteralText("[I'M SURE]").styled(style -> { + return style.withColor(Formatting.DARK_RED).withBold(true).withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, (admin ? "/claim admin" : "/claim") + " remove " + claim.name + " confirm")); + })), false); + return 0; + } + public static int delete(ServerCommandSource source, Claim claim, boolean admin) throws CommandSyntaxException { + ServerWorld world = source.getWorld(); + if (claim == null) { + source.sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); + return 0; + } + if (!claim.permissionManager.hasPermission(source.getPlayer().getGameProfile().getId(), Claim.Permission.REMOVE_CLAIM)) { + if (admin && ItsMine.permissions().hasPermission(source, PermissionUtil.Command.ADMIN_MODIFY, 2)) { + source.sendFeedback(new LiteralText("Deleting a claim belonging to somebody else").formatted(Formatting.DARK_RED).formatted(Formatting.BOLD), false); + } else { + source.sendFeedback(new LiteralText("You cannot delete that claim").formatted(Formatting.RED), false); + return 0; + } + } + if(!claim.isChild){ + ClaimManager.INSTANCE.releaseBlocksToOwner(claim); + ShowerUtil.update(claim, world, true); + ClaimManager.INSTANCE.claimsByName.remove(claim.name); + for(Claim subzone : claim.children){ + ClaimManager.INSTANCE.claimsByName.remove(subzone.name); + } + }else{ + Claim parent = ClaimUtil.getParentClaim(claim); + ShowerUtil.update(parent, world, true); + ClaimUtil.getParentClaim(claim).removeSubzone(claim); + ClaimManager.INSTANCE.claimsByName.remove(claim.name); + ShowerUtil.update(parent, world, false); + } + source.getWorld().getPlayers().forEach(playerEntity -> { + if (((ClaimShower)playerEntity).getShownClaim() != null && ((ClaimShower)playerEntity).getShownClaim().name.equals(claim.name)) silentHideShow(playerEntity, claim, true, true, ((ClaimShower)playerEntity).getMode()); + }); + + source.sendFeedback(new LiteralText("Deleted the claim \"" + claim.name + "\"").formatted(Formatting.GREEN), !claim.permissionManager.hasPermission(source.getPlayer().getGameProfile().getId(), Claim.Permission.REMOVE_CLAIM)); + return 0; + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/RenameCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/RenameCommand.java new file mode 100644 index 0000000..fc31fdf --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/RenameCommand.java @@ -0,0 +1,61 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.Messages; +import io.github.indicode.fabric.itsmine.util.ArgumentUtil; +import io.github.indicode.fabric.itsmine.util.ClaimUtil; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static com.mojang.brigadier.arguments.StringArgumentType.word; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class RenameCommand { + + public static void register(LiteralArgumentBuilder command, boolean admin) { + LiteralArgumentBuilder rename = literal("rename"); + RequiredArgumentBuilder claimArgument = ArgumentUtil.getClaims(); + RequiredArgumentBuilder nameArgument = argument("name", word()); + nameArgument.executes((context) -> rename(context, admin)); + claimArgument.then(nameArgument); + rename.then(claimArgument); + command.then(rename); + } + + public static int rename(CommandContext context, boolean admin) throws CommandSyntaxException { + String name = getString(context, "claim"); + String newName = getString(context, "name"); + if(!newName.matches("[A-Za-z0-9]+")){ + context.getSource().sendError(new LiteralText("Invalid claim name")); + return -1; + } + Claim claim = ClaimManager.INSTANCE.claimsByName.get(name); + if (claim == null) { + context.getSource().sendError(Messages.INVALID_CLAIM); + return -1; + } + if (ClaimManager.INSTANCE.claimsByName.containsKey(newName)) { + context.getSource().sendError(new LiteralText("That name is already taken!")); + return -1; + } + if (!admin && !claim.hasPermission(context.getSource().getPlayer().getUuid(), Claim.Permission.MODIFY_PROPERTIES)) { + context.getSource().sendError(new LiteralText("You don't have permission to modify claim properties!")); + return -1; + } + ClaimManager.INSTANCE.claimsByName.remove(name); + if(claim.isChild) claim.name = ClaimUtil.getParentClaim(claim).name + "." + newName; + else claim.name = newName; + ClaimManager.INSTANCE.addClaim(claim); + context.getSource().sendFeedback(new LiteralText("Renamed Claim " + name + " to " + claim.name).formatted(Formatting.GOLD), admin); + return -1; + } + + } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/RentCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/RentCommand.java new file mode 100644 index 0000000..59aec59 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/RentCommand.java @@ -0,0 +1,92 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.Messages; +import io.github.indicode.fabric.itsmine.util.TimeUtil; +import net.minecraft.item.ItemStack; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; + +import static com.mojang.brigadier.arguments.StringArgumentType.*; +import static io.github.indicode.fabric.itsmine.command.admin.AdminCommand.PERMISSION_CHECK_ADMIN; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class RentCommand { + public static void register(LiteralArgumentBuilder command, RequiredArgumentBuilder claim) { + LiteralArgumentBuilder rent = literal("rent"); + RequiredArgumentBuilder days = argument("days", word()); + days.executes(context -> rent(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")), getString(context, "days"))); + rent.requires(PERMISSION_CHECK_ADMIN); + claim.then(days); + rent.then(claim); + command.then(rent); + } + private static int rent(ServerCommandSource source, Claim claim, String rentString) throws CommandSyntaxException { + if(claim == null){ + source.sendFeedback(Messages.INVALID_CLAIM, true); + return 0; + } + int rentTime = (int) TimeUtil.convertStringtoSeconds(rentString); + int rentAbleTime = claim.rent.getRentAbleTime(); + int maxrentAbleTime = claim.rent.getMaxrentAbleTime(); + ItemStack currency = claim.rent.getCurrency(); + ItemStack handItem = source.getPlayer().inventory.getMainHandStack(); + ItemStack revenue = handItem.copy(); + if(rentTime % claim.rent.getRentAbleTime() != 0){ + source.sendFeedback(new LiteralText("You have to rent this claim for a time by a multiple of " + TimeUtil.convertSecondsToString(rentAbleTime, 'c', 'c')).formatted(Formatting.RED), true); + return 0; + } + int rentAmount = rentTime / claim.rent.getRentAbleTime(); + if(currency.getItem() != handItem.getItem() || handItem.getCount() < claim.rent.getAmount() * rentAmount){ + source.sendFeedback(new LiteralText("You don't have enough " + currency.getName().asString()).formatted(Formatting.RED), true); + return 0; + } + if (!claim.rent.isRentable()) { + source.sendFeedback(new LiteralText(claim.name + " is not for rent").formatted(Formatting.RED), true); + return 0; + } + if (rentTime > claim.rent.getMaxrentAbleTime()) { + source.sendFeedback(new LiteralText("You can't rent this claim for longer than " + TimeUtil.convertSecondsToString(maxrentAbleTime, 'c', 'c')).formatted(Formatting.RED), true); + return 0; + } + if(claim.rent.getTenant() == null){ + //Setup for claim rent + claim.rent.setTenant(source.getPlayer().getUuid()); + claim.rent.setRentedUntil(claim.rent.getUnixTime() + rentTime); + //Remove items from player + handItem.setCount(handItem.getCount() - claim.rent.getAmount() * rentAmount); + revenue.setCount(claim.rent.getAmount() * rentAmount); + claim.rent.addRevenue(revenue); + //Give Permissions to Tenant + claim.permissionManager.playerPermissions.put(source.getPlayer().getUuid(), new Claim.InvertedPermissionMap()); + source.sendFeedback(new LiteralText("Renting " + claim.name + " for " + claim.rent.getAmount() * rentAmount + " " + claim.rent.getCurrency().getName().asString() + " for " + TimeUtil.convertSecondsToString(rentTime, '2', 'a')).formatted(Formatting.GREEN), true); + return 1; + } else if(claim.rent.getTenant().toString().equalsIgnoreCase(source.getPlayer().getUuid().toString())){ + if (claim.rent.getRentTimeLeft() + rentTime <= maxrentAbleTime) { + //Setup for claim rent + claim.rent.setRentedUntil(claim.rent.getUnixTime() + rentTime + claim.rent.getRentTimeLeft()); + //Remove items from player + handItem.setCount(handItem.getCount() - claim.rent.getAmount() * rentAmount); + + revenue.setCount(claim.rent.getAmount() * rentAmount); + claim.rent.addRevenue(revenue); + //Give Permissions to Tenant + source.sendFeedback(new LiteralText("Extended rent " + claim.name + " by " + TimeUtil.convertSecondsToString(rentTime, '2', 'a') + "for " + claim.rent.getAmount() * rentAmount + " " + claim.rent.getCurrency().getName().asString()).formatted(Formatting.GREEN), true); + return 1; + } else { + source.sendFeedback(new LiteralText("Rent would exceed the limit by " + TimeUtil.convertSecondsToString(claim.rent.getRentTimeLeft() + rentTime - maxrentAbleTime, 'c', 'c')).formatted(Formatting.RED), true); + return 0; + } + } else { + source.sendFeedback(new LiteralText("This claim is already rented").formatted(Formatting.RED), true); + return 0; + } + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/RentableCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/RentableCommand.java new file mode 100644 index 0000000..3f5b2b6 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/RentableCommand.java @@ -0,0 +1,79 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.ItsMineConfig; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.util.ArgumentUtil; +import io.github.indicode.fabric.itsmine.util.TimeUtil; +import net.minecraft.command.arguments.ItemStackArgument; +import net.minecraft.command.arguments.ItemStackArgumentType; +import net.minecraft.item.ItemStack; +import net.minecraft.server.command.CommandManager; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; + +import static com.mojang.brigadier.arguments.StringArgumentType.*; +import static io.github.indicode.fabric.itsmine.command.admin.AdminCommand.PERMISSION_CHECK_ADMIN; +import static net.minecraft.server.command.CommandManager.literal; + +public class RentableCommand { + + public static void register(LiteralArgumentBuilder command, RequiredArgumentBuilder claim) { + LiteralArgumentBuilder rentable = literal("rentable"); + RequiredArgumentBuilder currency = net.minecraft.server.command.CommandManager.argument("item", ItemStackArgumentType.itemStack()).suggests(ArgumentUtil::itemsSuggestion); + RequiredArgumentBuilder amount = net.minecraft.server.command.CommandManager.argument("count", IntegerArgumentType.integer(1)); + RequiredArgumentBuilder days = net.minecraft.server.command.CommandManager.argument("days", word()); + RequiredArgumentBuilder maxdays = CommandManager.argument("maxdays", word()); + maxdays.executes(context -> makeRentable(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")), ItemStackArgumentType.getItemStackArgument(context, "item").createStack(1, false), IntegerArgumentType.getInteger(context, "count"), getString(context, "days"), getString(context, "maxdays"))); + rentable.requires(PERMISSION_CHECK_ADMIN); + claim.executes(context -> { + Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")); + if(claim1.rent.getCurrency() !=null || claim1.rent.getAmount() != 0 || claim1.rent.getRentAbleTime() != 0 || claim1.rent.getMaxrentAbleTime() != 0 && claim1.rent.isRentable()) { + context.getSource().sendFeedback(new LiteralText("Can't enable rent for " + claim1.name + ", because no values are set").formatted(Formatting.RED), true); + return 0; + } + if(claim1.rent.getTenant() == null){ + String state = claim1.rent.isRentable() ? "disabled" : "enabled"; + claim1.rent.setRentable(!claim1.rent.isRentable()); + context.getSource().sendFeedback(new LiteralText("Renting for " + claim1.name + " has been " + state).formatted(Formatting.GREEN), true); + return 1; + } else { + context.getSource().sendFeedback(new LiteralText("Can't disable rent for " + claim1.name + ", because it is currently being rented").formatted(Formatting.RED), true); + return 0; + } + }); + + days.then(maxdays); + amount.then(days); + currency.then(amount); + claim.then(currency); + rentable.then(claim); + command.then(rentable); + } + + private static int makeRentable(ServerCommandSource source, Claim claim, ItemStack item, int amount, String rentString, String maxrentString) throws CommandSyntaxException { + int rentTime = TimeUtil.convertStringtoSeconds(rentString); + int maxrentTime = TimeUtil.convertStringtoSeconds(maxrentString); + if(claim != null){ + if(rentTime <= maxrentTime){ + Claim.Rent rent = claim.rent; + rent.setRentable(true); + item.setCount(amount); + rent.setCurrency(item); + rent.setRentAbleTime(rentTime); + if(maxrentTime > ItsMineConfig.main().rent().maxRentTime) maxrentTime = ItsMineConfig.main().rent().maxRentTime; + rent.setMaxrentAbleTime(maxrentTime); + source.sendFeedback(new LiteralText("Claim " + claim.name + " can now be rented for " + amount + " " + item.getName().asString() + " every " + TimeUtil.convertSecondsToString(rentTime, '2', 'a')).formatted(Formatting.GREEN), true); + return 1; + } + } + return 0; + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/RevenueCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/RevenueCommand.java new file mode 100644 index 0000000..e561704 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/RevenueCommand.java @@ -0,0 +1,86 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.arguments.BoolArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.Messages; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.*; +import net.minecraft.util.Formatting; +import net.minecraft.util.math.BlockPos; + +import java.util.HashMap; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static io.github.indicode.fabric.itsmine.command.admin.AdminCommand.PERMISSION_CHECK_ADMIN; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class RevenueCommand { + + public static void register(LiteralArgumentBuilder command, RequiredArgumentBuilder claim) { + LiteralArgumentBuilder revenue = literal("revenue"); + RequiredArgumentBuilder claimRevenue = argument("claimRevenue", BoolArgumentType.bool()); + revenue.executes(context -> revenue(context.getSource(), ClaimManager.INSTANCE.getClaimAt(new BlockPos(context.getSource().getPosition()), context.getSource().getWorld().getDimension()), false)); + revenue.requires(PERMISSION_CHECK_ADMIN); + claim.executes(context -> revenue(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")), false)); + claimRevenue.executes(context -> revenue(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")), true)); + claim.then(claimRevenue); + revenue.then(claim); + command.then(revenue); + } + + private static int revenue(ServerCommandSource source, Claim claim, boolean claimrevenue) throws CommandSyntaxException { + //Show subzones (so you can just claim everything in one place) maybe just all claims + if(claim == null){ + source.sendFeedback(Messages.INVALID_CLAIM,true); + return 0; + } + if(!claim.claimBlockOwner.toString().equalsIgnoreCase(source.getPlayer().getUuid().toString())){ + source.sendFeedback(Messages.NO_PERMISSION, true); + return 0; + } + + if(claimrevenue){ + for(ItemStack itemStack : claim.rent.getRevenue()){ + source.getPlayer().inventory.insertStack(itemStack); + } + claim.rent.clearRevenue(); + return 1; + + } else { + if(claim.rent.getRevenue().isEmpty()){ + source.sendFeedback(new LiteralText("No Revenue").formatted(Formatting.RED), true); + return 0; + } + MutableText text = new LiteralText("Revenue\n").formatted(Formatting.AQUA); + HashMap hashMap = new HashMap<>(); + for(ItemStack itemStack : claim.rent.getRevenue()){ + Item value = itemStack.getItem(); + if(hashMap.containsKey(value)){ + hashMap.put(value, hashMap.get(value) + itemStack.getCount()); + } else { + hashMap.put(value, + itemStack.getCount()); + } + + hashMap.forEach((item, integer) -> { + boolean color = true; + text.append(new LiteralText(String.valueOf(integer)).append(new LiteralText(" ")).append(new TranslatableText(item.getTranslationKey())).append(new LiteralText(" ")).formatted(color ? Formatting.GOLD : Formatting.YELLOW)).styled(style -> { + return style.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new LiteralText("Click to claim revenue!").formatted(Formatting.GREEN))).withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/claim revenue " + claim.name + " true")); + }); + color = !color; + }); + + } + text.append(new LiteralText("\n")); + source.sendFeedback(text, true); + return 1; + } + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/ShowCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/ShowCommand.java new file mode 100644 index 0000000..35fa22e --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/ShowCommand.java @@ -0,0 +1,74 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.ClaimShower; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.ItsMineConfig; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.util.ArgumentUtil; +import io.github.indicode.fabric.itsmine.util.ClaimUtil; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static io.github.indicode.fabric.itsmine.util.ArgumentUtil.getShowMode; +import static io.github.indicode.fabric.itsmine.util.ShowerUtil.silentHideShow; +import static net.minecraft.server.command.CommandManager.literal; + +public class ShowCommand { + public static void register(LiteralArgumentBuilder command) { + { + RequiredArgumentBuilder mode = getShowMode(); + LiteralArgumentBuilder show = literal("show"); + show.executes(context -> executeShowClaim(context.getSource(), ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getBlockPos(), context.getSource().getWorld().getDimension()), false)); + RequiredArgumentBuilder claim = ArgumentUtil.getClaims(); + claim.executes(context -> executeShowClaim(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")), false)); + mode.executes(context -> executeShowClaim(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")), false, StringArgumentType.getString(context, "mode"))); + claim.then(mode); + show.then(claim); + command.then(show); + } + { + LiteralArgumentBuilder hide = literal("hide"); + hide.executes(context -> executeShowClaim(context.getSource(), null, true)); + RequiredArgumentBuilder claim = ArgumentUtil.getClaims(); + claim.executes(context -> executeShowClaim(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")), true)); + hide.then(claim); + command.then(hide); + } + + + LiteralArgumentBuilder hide = literal("hide"); + hide.executes(context -> executeShowClaim(context.getSource(), null, true)); + command.then(hide); + } + public static int executeShowClaim(ServerCommandSource source, Claim claim, boolean reset) throws CommandSyntaxException { + return executeShowClaim(source, claim, reset, null); + } + + public static int executeShowClaim(ServerCommandSource source, Claim claim, boolean reset, String mode) throws CommandSyntaxException { + ServerPlayerEntity player = source.getPlayer(); + if (!reset && ((ClaimShower)player).getShownClaim() != null && !(!ItsMineConfig.main().claims2d &&((ClaimShower)player).getShownClaim() != claim)) executeShowClaim(source, ((ClaimShower)player).getShownClaim(), true, ((ClaimShower)player).getMode()); + if (reset && ((ClaimShower)player).getShownClaim() != null) claim = ((ClaimShower)player).getShownClaim(); + if (claim != null) { + if (!claim.dimension.equals(source.getWorld().getDimension())) { + if (claim == ((ClaimShower)player).getShownClaim()) ((ClaimShower)player).setShownClaim(null); // just so we dont have extra packets on this + source.sendFeedback(new LiteralText("That claim is not in this dimension").formatted(Formatting.RED), false); + return 0; + } + source.sendFeedback(new LiteralText((!reset ? "Showing" : "Hiding") + " claim: " + claim.name).formatted(Formatting.GREEN), false); + if(claim.isChild) silentHideShow(player, ClaimUtil.getParentClaim(claim), reset, true, mode); + else silentHideShow(player, claim, reset, true, mode); + + } else { + source.sendFeedback(new LiteralText("That is not a valid claim").formatted(Formatting.RED), false); + } + return 0; + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/StickCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/StickCommand.java new file mode 100644 index 0000000..46d1e27 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/StickCommand.java @@ -0,0 +1,30 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import io.github.indicode.fabric.itsmine.ClaimManager; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; +import net.minecraft.util.Pair; +import net.minecraft.util.math.BlockPos; + +import static net.minecraft.server.command.CommandManager.literal; + +public class StickCommand { + + public static void register(LiteralArgumentBuilder command) { + LiteralArgumentBuilder stick = literal("stick"); + stick.executes(context -> { + Pair posPair = ClaimManager.INSTANCE.stickPositions.get(context.getSource().getPlayer()); + context.getSource().sendFeedback(new LiteralText(posPair == null ? "You can now use a stick to create claims. Run this command again to disable" : "Claim stick disabled. Run this command again to enable").formatted(Formatting.DARK_PURPLE), false); + if (posPair == null) { + ClaimManager.INSTANCE.stickPositions.put(context.getSource().getPlayer(), new Pair<>(null, null)); + } else { + ClaimManager.INSTANCE.stickPositions.remove(context.getSource().getPlayer()); + } + return 0; + }); + command.then(stick); + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/TransferCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/TransferCommand.java new file mode 100644 index 0000000..699657a --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/TransferCommand.java @@ -0,0 +1,148 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.authlib.GameProfile; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.Messages; +import io.github.indicode.fabric.itsmine.util.ArgumentUtil; +import io.github.indicode.fabric.itsmine.util.PermissionUtil; +import net.minecraft.command.EntitySelector; +import net.minecraft.command.arguments.EntityArgumentType; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.ClickEvent; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; +import net.minecraft.util.math.BlockPos; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class TransferCommand { + public static void register(LiteralArgumentBuilder command) { + + LiteralArgumentBuilder transfer = literal("transfer"); + RequiredArgumentBuilder claim = ArgumentUtil.getClaims(); + RequiredArgumentBuilder player = argument("player", EntityArgumentType.player()); + LiteralArgumentBuilder confirm = literal("confirm"); + confirm.executes(context -> { + final String string = "-accept-"; + ServerPlayerEntity p = EntityArgumentType.getPlayer(context, "player"); + String input = getString(context, "claim"); + String claimName = input.replace(string, ""); + Claim claim1 = ClaimManager.INSTANCE.claimsByName.get(claimName); + if (claim1 == null) { + context.getSource().sendError(Messages.INVALID_CLAIM); + return -1; + } + if (input.startsWith(string)) { + return acceptTransfer(context.getSource()); + } + return transfer(context.getSource(), claim1, p, false); + }); + player.executes(context -> requestTransfer(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")), EntityArgumentType.getPlayer(context, "player"), false)); + player.then(confirm); + claim.then(player); + transfer.then(claim); + transfer.executes(context -> requestTransfer(context.getSource(), ClaimManager.INSTANCE.getClaimAt(new BlockPos(context.getSource().getPosition()), context.getSource().getWorld().getDimension()), EntityArgumentType.getPlayer(context, "player"), false)); + command.then(transfer); + } + + public static int acceptTransfer(ServerCommandSource sender) throws CommandSyntaxException { + Claim claim = ClaimManager.INSTANCE.claimsByName.get(pendingClaimTransfers.get(sender.getPlayer().getGameProfile().getId())); + if (claim == null) { + sender.sendFeedback(new LiteralText("You have no pending claim transfers").formatted(Formatting.RED), false); + return 0; + } + ServerPlayerEntity player = sender.getMinecraftServer().getPlayerManager().getPlayer(claim.claimBlockOwner); + if (player != null) { + player.sendSystemMessage(new LiteralText("").append(new LiteralText(sender.getPlayer().getGameProfile().getName() + " has taken ownership of the claim \"" + claim.name + "\"").formatted(Formatting.YELLOW)), player.getUuid()); + } + Claim.ClaimPermissionMap op = claim.permissionManager.playerPermissions.get(claim.claimBlockOwner); + claim.permissionManager.playerPermissions.put(claim.claimBlockOwner, claim.permissionManager.playerPermissions.get(sender.getPlayer().getGameProfile().getId())); + claim.permissionManager.playerPermissions.put(sender.getPlayer().getGameProfile().getId(), op); + claim.claimBlockOwner = sender.getPlayer().getGameProfile().getId(); + claim.children.forEach(subzone -> { + try { + Claim.ClaimPermissionMap op1 = subzone.permissionManager.playerPermissions.get(subzone.claimBlockOwner); + subzone.permissionManager.playerPermissions.put(subzone.claimBlockOwner, subzone.permissionManager.playerPermissions.get(sender.getPlayer().getGameProfile().getId())); + subzone.permissionManager.playerPermissions.put(sender.getPlayer().getGameProfile().getId(), op1); + subzone.claimBlockOwner = sender.getPlayer().getGameProfile().getId(); + } catch (CommandSyntaxException e) { + e.printStackTrace(); + } + }); + return 0; + } + + private static int requestTransfer(ServerCommandSource sender, Claim claim, ServerPlayerEntity player, boolean admin) throws CommandSyntaxException { + if (claim == null) { + sender.sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); + return 0; + } + if(claim.isChild){ + sender.sendFeedback(new LiteralText("You can't transfer ownership of subzones").formatted(Formatting.RED), false); + return 0; + } + if(sender.getPlayer().getUuidAsString().equalsIgnoreCase(player.getUuidAsString())){ + sender.sendFeedback(new LiteralText("Huh? That makes no sence").formatted(Formatting.RED), true); + return 0; + } + if (!claim.claimBlockOwner.equals(sender.getPlayer().getGameProfile().getId())) { + if (admin && ItsMine.permissions().hasPermission(sender, PermissionUtil.Command.ADMIN_MODIFY, 2)) { + sender.sendFeedback(new LiteralText("WARNING: This is not your claim...").formatted(Formatting.DARK_RED).formatted(Formatting.BOLD), false); + } else { + sender.sendFeedback(new LiteralText("You can't transfer ownership of that claim").formatted(Formatting.RED), false); + return 0; + } + } + sender.sendFeedback(new LiteralText("").append(new LiteralText("Are you sure you want to transfer ownership of \"" + claim.name + "\" to " + player.getGameProfile().getName() + "? ").formatted(Formatting.GOLD)) + .append(new LiteralText("[YES]").styled(style -> { + return style.withColor(Formatting.DARK_RED).withBold(true).withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, (admin ? "/claim admin" : "/claim") + " transfer " + claim.name + " " + player.getGameProfile().getName() + " confirm")); + })), false); + return 0; + } + private static Map pendingClaimTransfers = new HashMap<>(); + private static int transfer(ServerCommandSource sender, Claim claim, ServerPlayerEntity player, boolean admin) throws CommandSyntaxException { + if (claim == null) { + sender.sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); + return 0; + } + if (claim.isChild) { + sender.sendFeedback(new LiteralText("You can't transfer ownership of subzones").formatted(Formatting.RED), false); + return 0; + } + if (sender.getPlayer().getUuidAsString().equalsIgnoreCase(player.getUuidAsString())) { + sender.sendFeedback(new LiteralText("Huh? That makes no sence").formatted(Formatting.RED), true); + return 0; + } + if (!claim.claimBlockOwner.equals(sender.getPlayer().getGameProfile().getId())) { + if (admin && ItsMine.permissions().hasPermission(sender, PermissionUtil.Command.ADMIN_MODIFY, 2)) { + sender.sendFeedback(new LiteralText("Transfering ownership of a claim belonging to somebody else").formatted(Formatting.DARK_RED).formatted(Formatting.BOLD), false); + } else { + sender.sendFeedback(new LiteralText("You can't transfer ownership of that claim").formatted(Formatting.RED), false); + return 0; + } + } + GameProfile profile = sender.getWorld().getServer().getUserCache().getByUuid(claim.claimBlockOwner); + sender.sendFeedback(new LiteralText("Transferring ownership of the claim \"" + claim.name + "\" to " + player.getGameProfile().getName() + " if they accept").formatted(Formatting.GREEN), claim.claimBlockOwner != player.getGameProfile().getId()); + player.sendSystemMessage(new LiteralText("").append(new LiteralText("Do you want to accept ownership of the claim \"" + claim.name + "\" from " + profile == null ? "Not Present" : profile.getName() + "? ").formatted(Formatting.GOLD)) + .append(new LiteralText("[ACCEPT]").styled(style -> { + style.withColor(Formatting.GREEN); + style.withBold(true); + style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/claim transfer -accept-" + claim.name + " " + player.getEntityName() + " confirm")); + return style; + })), player.getUuid()); + pendingClaimTransfers.put(player.getGameProfile().getId(), claim.name); + return 0; + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/TrustCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/TrustCommand.java new file mode 100644 index 0000000..5791b33 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/TrustCommand.java @@ -0,0 +1,86 @@ +package io.github.indicode.fabric.itsmine.command; + +import blue.endless.jankson.annotation.Nullable; +import com.mojang.authlib.GameProfile; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import net.minecraft.command.arguments.GameProfileArgumentType; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; + +import java.util.Collection; +import java.util.concurrent.atomic.AtomicInteger; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static io.github.indicode.fabric.itsmine.util.ArgumentUtil.PLAYERS_PROVIDER; +import static io.github.indicode.fabric.itsmine.util.ClaimUtil.validateClaim; +import static io.github.indicode.fabric.itsmine.util.ClaimUtil.verifyPermission; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class TrustCommand { + public static void register(LiteralArgumentBuilder command, CommandDispatcher dispatcher, RequiredArgumentBuilder claim, boolean admin) { + { + LiteralArgumentBuilder trust = literal("trust"); + RequiredArgumentBuilder playerArgument = argument("player", GameProfileArgumentType.gameProfile()).suggests(PLAYERS_PROVIDER); + playerArgument.executes((context -> executeTrust(context, GameProfileArgumentType.getProfileArgument(context, "player"), true, null, admin))); + claim.executes((context -> executeTrust(context, GameProfileArgumentType.getProfileArgument(context, "player"), true, getString(context, "claim"), admin))); + + playerArgument.then(claim); + trust.then(playerArgument); + command.then(trust); + dispatcher.register(trust); + } + { + LiteralArgumentBuilder distrust = literal("distrust"); + RequiredArgumentBuilder playerArgument = argument("player", GameProfileArgumentType.gameProfile()).suggests(PLAYERS_PROVIDER); + + playerArgument.executes((context -> executeTrust(context, GameProfileArgumentType.getProfileArgument(context, "player"), false, null, admin))); + claim.executes((context -> executeTrust(context, GameProfileArgumentType.getProfileArgument(context, "player"), false, getString(context, "claim"), admin))); + + playerArgument.then(claim); + distrust.then(playerArgument); + command.then(distrust); + dispatcher.register(distrust); + } + } + private static int executeTrust(CommandContext context, Collection targetCollection, boolean set, @Nullable String claimName, boolean admin) throws CommandSyntaxException { + AtomicInteger integer = new AtomicInteger(); + + if(targetCollection.isEmpty()){ + context.getSource().sendFeedback(new LiteralText("No player provided").formatted(Formatting.RED), true); + return 0; + } + ServerPlayerEntity p = context.getSource().getPlayer(); + Claim claim = claimName == null ? ClaimManager.INSTANCE.getClaimAt(p.getBlockPos(), p.world.getDimension()) : ClaimManager.INSTANCE.claimsByName.get(claimName); + validateClaim(claim); + targetCollection.iterator().forEachRemaining(gameProfile -> { + try { + //This is supposed to check if the player has played before :shrug: + if(context.getSource().getMinecraftServer().getUserCache().getByUuid(gameProfile.getId()) == gameProfile){ + integer.set(setTrust(context, claim, gameProfile, set, admin)); + } else { + context.getSource().sendFeedback(new LiteralText("Unknown player!").formatted(Formatting.RED), true); + integer.set(0); + } + } catch (CommandSyntaxException e) { + e.printStackTrace(); + } + }); + return integer.get(); + } + static int setTrust(CommandContext context, Claim claim, GameProfile target, boolean set, boolean admin) throws CommandSyntaxException { + if (verifyPermission(claim, Claim.Permission.MODIFY_PERMISSIONS, context, admin)) { + claim.permissionManager.playerPermissions.put(target.getId(), set ? new Claim.InvertedPermissionMap() : new Claim.DefaultPermissionMap()); + context.getSource().sendFeedback(new LiteralText(target.getName() + (set ? " now" : " no longer") + " has all the permissions").formatted(Formatting.YELLOW), false); + } + return 1; + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/TrustedCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/TrustedCommand.java new file mode 100644 index 0000000..e126dec --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/TrustedCommand.java @@ -0,0 +1,122 @@ +package io.github.indicode.fabric.itsmine.command; + +import com.mojang.authlib.GameProfile; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.Messages; +import io.github.indicode.fabric.itsmine.util.ArgumentUtil; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.*; +import net.minecraft.util.Formatting; + +import java.util.concurrent.atomic.AtomicInteger; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static net.minecraft.server.command.CommandManager.literal; + +public class TrustedCommand { + + public static void register(LiteralArgumentBuilder command) { + LiteralArgumentBuilder trusted = literal("trusted"); + RequiredArgumentBuilder claimArgument = ArgumentUtil.getClaims(); + trusted.executes((context)-> { + ServerPlayerEntity player = context.getSource().getPlayer(); + Claim claim = ClaimManager.INSTANCE.getClaimAt(player.getBlockPos(), player.world.getDimension()); + if (claim == null) { + context.getSource().sendError(Messages.INVALID_CLAIM); + return -1; + } + return showTrustedList(context, claim, false); + }); + + claimArgument.executes((context) -> { + Claim claim = ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")); + if (claim == null) { + context.getSource().sendError(Messages.INVALID_CLAIM); + return -1; + } + return showTrustedList(context, claim, false); + }); + trusted.then(claimArgument); + command.then(trusted); + } + + static int showTrustedList(CommandContext context, Claim claim, boolean showSelf) throws CommandSyntaxException { + ServerCommandSource source = context.getSource(); + ServerPlayerEntity player = source.getPlayer(); + int mapSize = claim.permissionManager.playerPermissions.size(); + + if (mapSize == 1 && !showSelf) { + source.sendError(new LiteralText(claim.name + " is not trusting anyone!")); + return -1; + } + + MutableText text = new LiteralText("\n"); + text.append(new LiteralText("Trusted players for Claim ").formatted(Formatting.YELLOW)) + .append(new LiteralText(claim.name).formatted(Formatting.GOLD)).append(new LiteralText("\n")); + + AtomicInteger atomicInteger = new AtomicInteger(); + claim.permissionManager.playerPermissions.forEach((uuid, perm) -> { + atomicInteger.incrementAndGet(); + MutableText pText = new LiteralText(""); + MutableText owner; + GameProfile profile = source.getMinecraftServer().getUserCache().getByUuid(uuid); + if (profile != null) { + owner = new LiteralText(profile.getName()); + } else { + owner = new LiteralText(uuid.toString()).styled((style) -> { + return style.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new LiteralText("Click to Copy"))).withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, uuid.toString())); + }); + } + + pText.append(new LiteralText(atomicInteger.get() + ". ").formatted(Formatting.GOLD)) + .append(owner.formatted(Formatting.YELLOW)); + + MutableText hover = new LiteralText(""); + hover.append(new LiteralText("Permissions:").formatted(Formatting.WHITE)).append(new LiteralText("\n")); + + int allowed = 0; + int i = 0; + boolean nextColor = false; + MutableText perms = new LiteralText(""); + + for (Claim.Permission value : Claim.Permission.values()) { + if (claim.permissionManager.hasPermission(uuid, value)) { + Formatting formatting = nextColor ? Formatting.GREEN : Formatting.DARK_GREEN; + perms.append(new LiteralText(value.id).formatted(formatting)).append(new LiteralText(" ")); + if (i == 3) perms.append(new LiteralText("\n")); + allowed++; + i++; + nextColor = !nextColor; + } + } + + if (allowed == Claim.Permission.values().length) { + hover.append(new LiteralText("All " + allowed + " Permissions").formatted(Formatting.YELLOW).formatted(Formatting.ITALIC)); + } else { + hover.append(perms); + } + + pText.append(new LiteralText(" ") + .append(new LiteralText("(").formatted(Formatting.GOLD)) + .append(new LiteralText(String.valueOf(allowed)).formatted(Formatting.GREEN)) + .append(new LiteralText("/").formatted(Formatting.GOLD)) + .append(new LiteralText(String.valueOf(Claim.Permission.values().length)).formatted(Formatting.YELLOW)) + .append(new LiteralText(")").formatted(Formatting.GOLD)) + ); + + pText.styled((style) -> { + return style.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hover)); + }); + text.append(pText).append(new LiteralText("\n")); + }); + + source.sendFeedback(text, false); + return 1; + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/admin/AdminCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/AdminCommand.java new file mode 100644 index 0000000..bdb4f59 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/AdminCommand.java @@ -0,0 +1,51 @@ +package io.github.indicode.fabric.itsmine.command.admin; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.command.MessageCommand; +import io.github.indicode.fabric.itsmine.command.PermissionCommand; +import io.github.indicode.fabric.itsmine.command.FlagsCommand; +import io.github.indicode.fabric.itsmine.command.subzone.SubzoneCommand; +import net.minecraft.server.command.ServerCommandSource; + +import java.util.function.Predicate; + +import static io.github.indicode.fabric.itsmine.util.ArgumentUtil.getClaims; +import static net.minecraft.server.command.CommandManager.literal; + +public class AdminCommand { + + public static void register(LiteralArgumentBuilder command, CommandDispatcher dispatcher) { + LiteralArgumentBuilder admin = literal("admin"); + admin.requires(PERMISSION_CHECK_ADMIN); + registerAdmin(admin, dispatcher); + command.then(admin); + } + + private static void registerAdmin(LiteralArgumentBuilder admin, CommandDispatcher dispatcher) { + BlocksCommand.register(admin); + CreateCommand.register(admin); + EntitiesCommand.register(admin); + ExpandCommand.register(admin); + IgnoreCommand.register(admin); + ListAllCommand.register(admin); + MessageCommand.register(admin, true, getClaims()); + OwnerCommand.register(admin); + PermissionCommand.register(admin, true, getClaims()); + ReloadCommand.register(admin); + RemoveCommand.register(admin); + RenameCommand.register(admin); + FlagsCommand.register(admin, true, getClaims()); + SubzoneCommand.register(admin, dispatcher, true); + } + + private static Predicate perm(String str) { + return perm(str, 2); + } + private static Predicate perm(String str, int op) { + return source -> ItsMine.permissions().hasPermission(source, "itsmine." + str, op); + } + public static final Predicate PERMISSION_CHECK_ADMIN = src -> perm("admin").test(src); + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/admin/BlocksCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/BlocksCommand.java new file mode 100644 index 0000000..473431a --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/BlocksCommand.java @@ -0,0 +1,65 @@ +package io.github.indicode.fabric.itsmine.command.admin; + +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.util.PermissionUtil; +import net.minecraft.command.EntitySelector; +import net.minecraft.command.arguments.EntityArgumentType; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; + +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class BlocksCommand { + + public static void register(LiteralArgumentBuilder command) { + { + LiteralArgumentBuilder add = literal("addBlocks"); + add.requires(source -> ItsMine.permissions().hasPermission(source, PermissionUtil.Command.ADMIN_MODIFY_BALANCE, 2)); + RequiredArgumentBuilder player = argument("player", EntityArgumentType.players()); + RequiredArgumentBuilder amount = argument("amount", IntegerArgumentType.integer()); + amount.executes(context -> { + ClaimManager.INSTANCE.addClaimBlocks(EntityArgumentType.getPlayers(context, "player"), IntegerArgumentType.getInteger(context, "amount")); + context.getSource().sendFeedback(new LiteralText("Gave " + IntegerArgumentType.getInteger(context, "amount") + " claim blocks").formatted(Formatting.GREEN), true); + return 0; + }); + player.then(amount); + add.then(player); + command.then(add); + } + { + LiteralArgumentBuilder remove = literal("removeBlocks"); + remove.requires(source ->ItsMine.permissions().hasPermission(source, PermissionUtil.Command.ADMIN_MODIFY_BALANCE, 2)); + RequiredArgumentBuilder player = argument("player", EntityArgumentType.players()); + RequiredArgumentBuilder amount = argument("amount", IntegerArgumentType.integer()); + amount.executes(context -> { + ClaimManager.INSTANCE.addClaimBlocks(EntityArgumentType.getPlayers(context, "player"), -IntegerArgumentType.getInteger(context, "amount")); + context.getSource().sendFeedback(new LiteralText("Took " + IntegerArgumentType.getInteger(context, "amount") + " claim blocks").formatted(Formatting.GREEN), true); + return 0; + }); + player.then(amount); + remove.then(player); + command.then(remove); + } + { + LiteralArgumentBuilder set = literal("setBlocks"); + set.requires(source -> ItsMine.permissions().hasPermission(source, PermissionUtil.Command.ADMIN_MODIFY_BALANCE, 2)); + RequiredArgumentBuilder player = argument("player", EntityArgumentType.players()); + RequiredArgumentBuilder amount = argument("amount", IntegerArgumentType.integer()); + amount.executes(context -> { + ClaimManager.INSTANCE.setClaimBlocks(EntityArgumentType.getPlayers(context, "player"), IntegerArgumentType.getInteger(context, "amount")); + context.getSource().sendFeedback(new LiteralText("Set claim block amount to " + IntegerArgumentType.getInteger(context, "amount")).formatted(Formatting.GREEN), true); + return 0; + }); + player.then(amount); + set.then(player); + command.then(set); + } + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/admin/CreateCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/CreateCommand.java new file mode 100644 index 0000000..f7ed03c --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/CreateCommand.java @@ -0,0 +1,81 @@ +package io.github.indicode.fabric.itsmine.command.admin; + +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.util.PermissionUtil; +import net.minecraft.command.arguments.BlockPosArgumentType; +import net.minecraft.command.arguments.PosArgument; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; +import net.minecraft.util.Pair; +import net.minecraft.util.math.BlockPos; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static com.mojang.brigadier.arguments.StringArgumentType.word; +import static io.github.indicode.fabric.itsmine.command.CreateCommand.createClaim; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class CreateCommand { + public static void register(LiteralArgumentBuilder command) { + LiteralArgumentBuilder create = literal("create"); + create.requires(source -> ItsMine.permissions().hasPermission(source, PermissionUtil.Command.ADMIN_INFINITE_CLAIM, 2)); + ArgumentBuilder name = argument("name", word()); + ArgumentBuilder customOwner = argument("customOwnerName", word()); + ArgumentBuilder min = argument("min", BlockPosArgumentType.blockPos()); + RequiredArgumentBuilder max = argument("max", BlockPosArgumentType.blockPos()); + max.executes(context -> createClaim( + getString(context, "name"), + context.getSource(), + BlockPosArgumentType.getBlockPos(context, "min"), + BlockPosArgumentType.getBlockPos(context, "max"), + true, + null + )); + name.executes(context -> { + ServerPlayerEntity player = context.getSource().getPlayer(); + Pair selectedPositions = ClaimManager.INSTANCE.stickPositions.get(player); + if (selectedPositions == null) { + context.getSource().sendFeedback(new LiteralText("You need to specify block positions or select them with a stick.").formatted(Formatting.RED), false); + } else if (selectedPositions.getLeft() == null) { + context.getSource().sendFeedback(new LiteralText("You need to specify block positions or select position #1(Right Click) with a stick.").formatted(Formatting.RED), false); + } else if (selectedPositions.getRight() == null) { + context.getSource().sendFeedback(new LiteralText("You need to specify block positions or select position #2(Left Click) with a stick.").formatted(Formatting.RED), false); + } else { + String cname = getString(context, "name"); + if (createClaim(cname, context.getSource(), selectedPositions.getLeft(), selectedPositions.getRight(), true, null) > 0) { + ClaimManager.INSTANCE.stickPositions.remove(player); + } + } + return 0; + }); + customOwner.executes(context -> { + ServerPlayerEntity player = context.getSource().getPlayer(); + Pair selectedPositions = ClaimManager.INSTANCE.stickPositions.get(player); + if (selectedPositions == null) { + context.getSource().sendFeedback(new LiteralText("You need to specify block positions or select them with a stick.").formatted(Formatting.RED), false); + } else if (selectedPositions.getLeft() == null) { + context.getSource().sendFeedback(new LiteralText("You need to specify block positions or select position #1(Right Click) with a stick.").formatted(Formatting.RED), false); + } else if (selectedPositions.getRight() == null) { + context.getSource().sendFeedback(new LiteralText("You need to specify block positions or select position #2(Left Click) with a stick.").formatted(Formatting.RED), false); + } else { + String cname = getString(context, "name"); + if (createClaim(cname, context.getSource(), selectedPositions.getLeft(), selectedPositions.getRight(), true, getString(context, "customOwnerName")) > 0) { + ClaimManager.INSTANCE.stickPositions.remove(player); + } + } + return 0; + }); + min.then(max); + name.then(customOwner); + name.then(min); + create.then(name); + command.then(create); + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/admin/EntitiesCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/EntitiesCommand.java new file mode 100644 index 0000000..59dd894 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/EntitiesCommand.java @@ -0,0 +1,64 @@ +package io.github.indicode.fabric.itsmine.command.admin; + +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import io.github.indicode.fabric.itsmine.*; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.util.ArgumentUtil; +import io.github.indicode.fabric.itsmine.util.PermissionUtil; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.HoverEvent; +import net.minecraft.text.LiteralText; +import net.minecraft.text.MutableText; +import net.minecraft.util.Formatting; + +import java.util.ArrayList; +import java.util.Map; + +import static io.github.indicode.fabric.itsmine.Messages.header; +import static io.github.indicode.fabric.itsmine.util.EntityUtil.*; +import static net.minecraft.server.command.CommandManager.literal; + +public class EntitiesCommand { + public static void register(LiteralArgumentBuilder command) { + LiteralArgumentBuilder entity = literal("entities"); + entity.requires(source -> ItsMine.permissions().hasPermission(source, PermissionUtil.Command.ADMIN_MODIFY, 2)); + RequiredArgumentBuilder claim = ArgumentUtil.getClaims(); + entity.executes(context -> execute(context, ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getBlockPos(), context.getSource().getPlayer().world.getDimension()))); + claim.executes(context -> execute(context, ClaimManager.INSTANCE.getClaim(StringArgumentType.getString(context, "claim")))); + entity.then(claim); + command.then(entity); + } + + public static int execute(CommandContext context, Claim claim){ + ServerCommandSource source = context.getSource(); + if(claim == null){ + source.sendError(Messages.INVALID_CLAIM); + return 1; + } + + ArrayList entityList = getEntities(claim); + MutableText message = header("Entities (" + claim.name +") - " + entityList.size()).append(new LiteralText("\n\n")); + for(SpawnGroup spawnGroup : SpawnGroup.values()){ + MutableText entities = new LiteralText(""); + Map entityMap = sortByType(filterByCategory(entityList, spawnGroup)); + entityMap.forEach((entityType, integer) -> { + entities.append(entityType.getName().getString() + ": ").formatted(Formatting.YELLOW).append(new LiteralText(String.valueOf(integer))).formatted(Formatting.GOLD).append("\n"); + + }); + if(entityMap.size() > 0){ + message.append(new LiteralText(spawnGroup.getName()).styled(style -> { + return style.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, entities)).withFormatting(Formatting.GOLD); + }).append(" ")); + } + } + source.sendFeedback(message, false); + return 1; + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/admin/ExpandCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/ExpandCommand.java new file mode 100644 index 0000000..1b49151 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/ExpandCommand.java @@ -0,0 +1,76 @@ +package io.github.indicode.fabric.itsmine.command.admin; + +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.util.PermissionUtil; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.util.math.Direction; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static io.github.indicode.fabric.itsmine.command.ExpandCommand.expand; +import static io.github.indicode.fabric.itsmine.util.ArgumentUtil.getDirections; +import static io.github.indicode.fabric.itsmine.util.DirectionUtil.directionByName; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class ExpandCommand { + + public static void register(LiteralArgumentBuilder command) { + { + LiteralArgumentBuilder expand = literal("expand"); + expand.requires(source -> ItsMine.permissions().hasPermission(source, PermissionUtil.Command.ADMIN_INFINITE_CLAIM, 2) && ItsMine.permissions().hasPermission(source, PermissionUtil.Command.ADMIN_MODIFY, 2)); + RequiredArgumentBuilder amount = argument("distance", IntegerArgumentType.integer(1, Integer.MAX_VALUE)); + RequiredArgumentBuilder direction = getDirections(); + + direction.executes(context -> expand( + ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getBlockPos(), context.getSource().getWorld().getDimension()), + IntegerArgumentType.getInteger(context, "distance"), + directionByName(getString(context, "direction")), + context.getSource(), + true + )); + + amount.executes(context -> expand( + ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getBlockPos(), context.getSource().getWorld().getDimension()), + IntegerArgumentType.getInteger(context, "distance"), + Direction.getEntityFacingOrder(context.getSource().getPlayer())[0], + context.getSource(), + true + )); + + amount.then(direction); + expand.then(amount); + command.then(expand); + } + { + LiteralArgumentBuilder shrink = literal("shrink"); + shrink.requires(source -> ItsMine.permissions().hasPermission(source, PermissionUtil.Command.ADMIN_INFINITE_CLAIM, 2) && ItsMine.permissions().hasPermission(source, PermissionUtil.Command.ADMIN_MODIFY, 2)); + RequiredArgumentBuilder amount = argument("distance", IntegerArgumentType.integer(1, Integer.MAX_VALUE)); + RequiredArgumentBuilder direction = getDirections(); + + direction.executes(context -> expand( + ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getBlockPos(), context.getSource().getWorld().getDimension()), + -IntegerArgumentType.getInteger(context, "distance"), + directionByName(getString(context, "direction")), + context.getSource(), + true + )); + + amount.executes(context -> expand( + ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getBlockPos(), context.getSource().getWorld().getDimension()), + -IntegerArgumentType.getInteger(context, "distance"), + Direction.getEntityFacingOrder(context.getSource().getPlayer())[0], + context.getSource(), + true + )); + + amount.then(direction); + shrink.then(amount); + command.then(shrink); + } + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/admin/IgnoreCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/IgnoreCommand.java new file mode 100644 index 0000000..5c11385 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/IgnoreCommand.java @@ -0,0 +1,30 @@ +package io.github.indicode.fabric.itsmine.command.admin; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.util.PermissionUtil; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; + +import java.util.UUID; + +import static net.minecraft.server.command.CommandManager.literal; + +public class IgnoreCommand { + public static void register(LiteralArgumentBuilder command) { + LiteralArgumentBuilder ignore = literal("ignoreClaims"); + ignore.requires(source -> ItsMine.permissions().hasPermission(source, PermissionUtil.Command.ADMIN_IGNORE_CLAIMS, 2)); + ignore.executes(context -> { + UUID id = context.getSource().getPlayer().getGameProfile().getId(); + boolean isIgnoring = ClaimManager.INSTANCE.ignoringClaims.contains(id); + if (isIgnoring) ClaimManager.INSTANCE.ignoringClaims.remove(id); + else ClaimManager.INSTANCE.ignoringClaims.add(id); + context.getSource().sendFeedback(new LiteralText("You are " + (isIgnoring ? "no longer" : "now") + " ignoring claims.").formatted(Formatting.GREEN), false); + return 0; + }); + command.then(ignore); + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/admin/ListAllCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/ListAllCommand.java new file mode 100644 index 0000000..10461a8 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/ListAllCommand.java @@ -0,0 +1,59 @@ +package io.github.indicode.fabric.itsmine.command.admin; + +import com.mojang.brigadier.arguments.BoolArgumentType; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.util.MessageUtil; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +import java.util.ArrayList; +import java.util.List; + +import static io.github.indicode.fabric.itsmine.util.ClaimUtil.getClaims; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class ListAllCommand { + public static void register(LiteralArgumentBuilder command) { + LiteralArgumentBuilder listall = literal("listall"); + RequiredArgumentBuilder page = argument("page", IntegerArgumentType.integer(1)); + RequiredArgumentBuilder entries = argument("entries", IntegerArgumentType.integer(1, 100)); + RequiredArgumentBuilder offline = argument("offline", BoolArgumentType.bool()); + entries.executes(context -> listall(context.getSource(), IntegerArgumentType.getInteger(context, "page"), IntegerArgumentType.getInteger(context, "entries"), BoolArgumentType.getBool(context, "offline"))); + page.executes(context -> listall(context.getSource(), IntegerArgumentType.getInteger(context, "page"), 10, BoolArgumentType.getBool(context, "offline"))); + listall.executes(context -> listall(context.getSource(), 1, 10, true)); + offline.executes(context -> listall(context.getSource(), 1, 10, BoolArgumentType.getBool(context, "offline"))); + page.then(entries); + offline.then(page); + listall.then(offline); + command.then(listall); + } + private static int listall(ServerCommandSource source, int page, int entries, boolean offline){ + List claims = getClaims(); + Text title = new LiteralText("Claim List:").formatted(Formatting.AQUA).formatted(Formatting.UNDERLINE); + ArrayList claimList = new ArrayList<>(); + if(!offline){ + for(ServerPlayerEntity serverPlayerEntity : source.getMinecraftServer().getPlayerManager().getPlayerList()){ + for(Claim claim : ClaimManager.INSTANCE.getPlayerClaims(serverPlayerEntity.getUuid())){ + claimList.add(new LiteralText(claim.name).formatted(Formatting.GOLD).append(new LiteralText(" ")).append(new LiteralText(String.valueOf(claim.getEntities(source.getWorld()))).formatted(Formatting.YELLOW))); + } + } + } else { + for (Claim claim : claims) { + claimList.add(new LiteralText(claim.name).formatted(Formatting.GOLD).append(new LiteralText(" "))); + } + } + MessageUtil.sendPage(source, title, entries, page, "/claim admin listall " + offline + " %page% " + entries, claimList); + return 1; + } + + + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/admin/OwnerCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/OwnerCommand.java new file mode 100644 index 0000000..9bd1196 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/OwnerCommand.java @@ -0,0 +1,114 @@ +package io.github.indicode.fabric.itsmine.command.admin; + +import com.mojang.authlib.GameProfile; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.Messages; +import io.github.indicode.fabric.itsmine.util.ArgumentUtil; +import net.minecraft.command.arguments.GameProfileArgumentType; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; + +import java.util.Collection; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static com.mojang.brigadier.arguments.StringArgumentType.word; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class OwnerCommand { + public static void register(LiteralArgumentBuilder command) { + { + LiteralArgumentBuilder set = literal("setOwner"); + RequiredArgumentBuilder newOwner = argument("newOwner", GameProfileArgumentType.gameProfile()); + RequiredArgumentBuilder claimArgument = ArgumentUtil.getClaims(); + + newOwner.executes((context) -> { + Claim claim = ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getBlockPos(), context.getSource().getPlayer().world.getDimension()); + if (claim == null) { + context.getSource().sendError(Messages.INVALID_CLAIM); + return -1; + } + + Collection profiles = GameProfileArgumentType.getProfileArgument(context, "newOwner"); + + if (profiles.size() > 1) { + context.getSource().sendError(Messages.TOO_MANY_SELECTIONS); + return -1; + } + return setOwner(context.getSource(), claim, profiles.iterator().next()); + }); + + claimArgument.executes((context) -> { + Claim claim = ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")); + if (claim == null) { + context.getSource().sendError(Messages.INVALID_CLAIM); + return -1; + } + + Collection profiles = GameProfileArgumentType.getProfileArgument(context, "newOwner"); + + if (profiles.size() > 1) { + context.getSource().sendError(Messages.TOO_MANY_SELECTIONS); + return -1; + } + return setOwner(context.getSource(), claim, profiles.iterator().next()); + }); + + newOwner.then(claimArgument); + set.then(newOwner); + command.then(set); + } + + { + LiteralArgumentBuilder set = literal("setOwnerName"); + RequiredArgumentBuilder nameArgument = argument("newName", word()); + RequiredArgumentBuilder claimArgument = ArgumentUtil.getClaims(); + + nameArgument.executes((context) -> { + Claim claim = ClaimManager.INSTANCE.getClaimAt(context.getSource().getPlayer().getBlockPos(), context.getSource().getPlayer().world.getDimension()); + if (claim == null) { + context.getSource().sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); + return -1; + } + return setOwnerName(context.getSource(), claim, getString(context, "newName")); + }); + + claimArgument.executes((context) -> { + Claim claim = ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")); + if (claim == null) { + context.getSource().sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); + return -1; + } + return setOwnerName(context.getSource(), claim, getString(context, "newName")); + }); + + nameArgument.then(claimArgument); + set.then(nameArgument); + command.then(set); + } + } + private static int setOwnerName(ServerCommandSource source, Claim claim, String input) { + String name = input.equals("reset") ? null : input; + source.sendFeedback(new LiteralText("Set the Custom Owner Name to ") + .formatted(Formatting.YELLOW).append(new LiteralText(name == null ? "Reset" : name).formatted(Formatting.GOLD)).append(new LiteralText(" from ")) + .append(new LiteralText(claim.customOwnerName == null ? "Not Present" : claim.customOwnerName).formatted(Formatting.GOLD)) + .append(new LiteralText(" for ").formatted(Formatting.YELLOW)).append(new LiteralText(claim.name).formatted(Formatting.GOLD)) + , false); + claim.customOwnerName = input; + return 1; + } + private static int setOwner(ServerCommandSource source, Claim claim, GameProfile profile) { + GameProfile oldOwner = source.getMinecraftServer().getUserCache().getByUuid(claim.claimBlockOwner); + source.sendFeedback(new LiteralText("Set the Claim Owner to ") + .formatted(Formatting.YELLOW).append(new LiteralText(profile.getName()).formatted(Formatting.GOLD)).append(new LiteralText(" from ")) + .append(new LiteralText(oldOwner == null ? "(" + claim.claimBlockOwner + ")" : oldOwner.getName()).formatted(Formatting.GOLD)) + .append(new LiteralText(" for ").formatted(Formatting.YELLOW)).append(new LiteralText(claim.name).formatted(Formatting.GOLD)) + , false); + claim.claimBlockOwner = profile.getId(); + return 1; + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/admin/ReloadCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/ReloadCommand.java new file mode 100644 index 0000000..0c37e5a --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/ReloadCommand.java @@ -0,0 +1,36 @@ +package io.github.indicode.fabric.itsmine.command.admin; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.ItsMineConfig; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; +import org.apache.commons.lang3.time.StopWatch; + +import java.text.DecimalFormat; +import java.util.concurrent.TimeUnit; + +public class ReloadCommand { + + public static void register(LiteralArgumentBuilder command) { + LiteralArgumentBuilder reload = LiteralArgumentBuilder.literal("reload"); + reload.executes(ReloadCommand::execute); + command.then(reload); + } + + + public static int execute(CommandContext context) throws CommandSyntaxException { + ServerPlayerEntity player = context.getSource().getPlayer(); + StopWatch watch = new StopWatch(); + watch.start(); + ItsMine.reload(); + watch.stop(); + String timeElapsed = new DecimalFormat("##.##").format(watch.getTime(TimeUnit.MICROSECONDS)); + player.sendSystemMessage(new LiteralText("Reloaded! Took " + timeElapsed + "μs").formatted(Formatting.YELLOW), player.getUuid()); + return 1; + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/admin/RemoveCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/RemoveCommand.java new file mode 100644 index 0000000..20d2ac7 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/RemoveCommand.java @@ -0,0 +1,31 @@ +package io.github.indicode.fabric.itsmine.command.admin; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.util.ArgumentUtil; +import io.github.indicode.fabric.itsmine.util.PermissionUtil; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.util.math.BlockPos; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static io.github.indicode.fabric.itsmine.command.RemoveCommand.delete; +import static io.github.indicode.fabric.itsmine.command.RemoveCommand.requestDelete; +import static net.minecraft.server.command.CommandManager.literal; + +public class RemoveCommand { + public static void register(LiteralArgumentBuilder command) { + LiteralArgumentBuilder delete = literal("remove"); + delete.requires(source -> ItsMine.permissions().hasPermission(source, PermissionUtil.Command.ADMIN_MODIFY, 2)); + RequiredArgumentBuilder claim = ArgumentUtil.getClaims(); + LiteralArgumentBuilder confirm = literal("confirm"); + confirm.executes(context -> delete(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")), true)); + claim.executes(context -> requestDelete(context.getSource(), ClaimManager.INSTANCE.claimsByName.get(getString(context, "claim")), true)); + claim.then(confirm); + delete.then(claim); + delete.executes(context -> requestDelete(context.getSource(), ClaimManager.INSTANCE.getClaimAt(new BlockPos(context.getSource().getPosition()), context.getSource().getWorld().getDimension()), true)); + command.then(delete); + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/admin/RenameCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/RenameCommand.java new file mode 100644 index 0000000..1798fcb --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/admin/RenameCommand.java @@ -0,0 +1,23 @@ +package io.github.indicode.fabric.itsmine.command.admin; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import io.github.indicode.fabric.itsmine.util.ArgumentUtil; +import net.minecraft.server.command.ServerCommandSource; + +import static com.mojang.brigadier.arguments.StringArgumentType.word; +import static io.github.indicode.fabric.itsmine.command.RenameCommand.rename; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class RenameCommand { + public static void register(LiteralArgumentBuilder command) { + LiteralArgumentBuilder rename = literal("rename"); + RequiredArgumentBuilder claimArgument = ArgumentUtil.getClaims(); + RequiredArgumentBuilder nameArgument = argument("name", word()); + nameArgument.executes((context) -> rename(context, true)); + claimArgument.then(nameArgument); + rename.then(claimArgument); + command.then(rename); + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/subzone/CreateCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/subzone/CreateCommand.java new file mode 100644 index 0000000..186cebe --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/subzone/CreateCommand.java @@ -0,0 +1,146 @@ +package io.github.indicode.fabric.itsmine.command.subzone; + +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.ItsMineConfig; +import io.github.indicode.fabric.itsmine.Messages; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.util.ArgumentUtil; +import net.minecraft.server.command.CommandManager; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; +import net.minecraft.util.Pair; +import net.minecraft.util.math.BlockPos; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +import static io.github.indicode.fabric.itsmine.command.ShowCommand.executeShowClaim; + +public class CreateCommand { + + public static void register(LiteralArgumentBuilder command, boolean admin) { + { + LiteralArgumentBuilder create = CommandManager.literal("create"); + + RequiredArgumentBuilder name = CommandManager.argument("name", StringArgumentType.word()) + .executes(ctx -> addZone(ctx.getSource(), StringArgumentType.getString(ctx, "name"), null, false)); + + RequiredArgumentBuilder claim = ArgumentUtil.getClaims() + .executes(ctx -> addZone(ctx.getSource(), StringArgumentType.getString(ctx, "name"), StringArgumentType.getString(ctx, "claim"), admin)); + + name.then(claim); + create.then(name); + command.then(create); + } + } + + private static int addZone(ServerCommandSource source, String name, @Nullable String claimName, boolean admin) throws CommandSyntaxException { + if (name.length() > 30) { + source.sendError(Messages.MSG_LONG_NAME); + return -1; + } + + ServerPlayerEntity player = source.getPlayer(); + Claim claim = validateAndGet(source, claimName, admin); + Claim subZone = null; + + if (!admin && !claim.permissionManager.hasPermission(player.getGameProfile().getId(), Claim.Permission.MODIFY_SUBZONE)) { + throw new SimpleCommandExceptionType(Messages.NO_PERMISSION).create(); + } + if(!name.matches("[A-Za-z0-9]+")){ + source.sendError(new LiteralText("Invalid claim name")); + return -1; + } + + if (ClaimManager.INSTANCE.claimsByName.containsKey(name)) { + source.sendFeedback(new LiteralText("The name \"" + name + "\" is already taken.").formatted(Formatting.RED), false); + return -1; + } + Pair selectedPositions = ClaimManager.INSTANCE.stickPositions.get(player); + if (selectedPositions == null) { + source.sendFeedback(new LiteralText("You need to specify block positions or select them with a stick.").formatted(Formatting.RED), false); + } else if (selectedPositions.getLeft() == null) { + source.sendFeedback(new LiteralText("You need to specify block positions or select position #1(Right Click) with a stick.").formatted(Formatting.RED), false); + } else if (selectedPositions.getRight() == null) { + source.sendFeedback(new LiteralText("You need to specify block positions or select position #2(Left Click) with a stick.").formatted(Formatting.RED), false); + } else { + name = claim.name + "." + name; + subZone = createSubzone(source, name, selectedPositions.getLeft(), selectedPositions.getRight(), admin); + if (subZone.dimension == claim.dimension && claim.includesPosition(subZone.min) && claim.includesPosition(subZone.max) && !claim.isChild){ + if (!ClaimManager.INSTANCE.wouldSubzoneIntersect((subZone))){ + claim.addSubzone(subZone); + ClaimManager.INSTANCE.addClaim(subZone); + subZone.permissionManager = claim.permissionManager; + executeShowClaim(source, claim, false); + source.sendFeedback(new LiteralText("").append(new LiteralText("Your subzone was created.").formatted(Formatting.GREEN)), false); + }else{ + player.sendSystemMessage(new LiteralText("Your subzone would overlap with another subzone").formatted(Formatting.RED), player.getUuid()); + } + if (subZone != null) { + ClaimManager.INSTANCE.stickPositions.remove(player); + return 1; + } + return 0; + }else{ + player.sendSystemMessage(new LiteralText("Subzone must be inside the original claim, in the same dimension").formatted(Formatting.RED), player.getUuid()); + } + } + return 0; + } + + private static Claim createSubzone(ServerCommandSource source, String name, BlockPos posA, BlockPos posB, boolean admin) throws CommandSyntaxException { + UUID ownerID = source.getPlayer().getGameProfile().getId(); + int x, y = 0, z, mx, my = 255, mz; + if (posA.getX() > posB.getX()) { + x = posB.getX(); + mx = posA.getX(); + } else { + x = posA.getX(); + mx = posB.getX(); + } + if (!ItsMineConfig.main().claims2d) { + if (posA.getY() > posB.getY()) { + y = posB.getY(); + my = posA.getY(); + } else { + y = posA.getY(); + my = posB.getY(); + } + } + if (posA.getZ() > posB.getZ()) { + z = posB.getZ(); + mz = posA.getZ(); + } else { + z = posA.getZ(); + mz = posB.getZ(); + } + BlockPos min = new BlockPos(x, y, z); + BlockPos max = new BlockPos(mx, my, mz); + BlockPos sub = max.subtract(min); + sub = sub.add(1, ItsMineConfig.main().claims2d ? 0 : 1,1); + return new Claim(name, admin ? null : ownerID, min, max, source.getWorld().getDimension(), source.getPlayer().getBlockPos(), true); + } + + private static Claim validateAndGet(ServerCommandSource source, @Nullable String claimName, boolean admin) throws CommandSyntaxException { + ServerPlayerEntity player = source.getPlayer(); + Claim claim = claimName == null ? ClaimManager.INSTANCE.getClaimAt(player.getBlockPos(), player.world.getDimension()) : + ClaimManager.INSTANCE.claimsByName.get(claimName); + + if (claim == null) { + throw new SimpleCommandExceptionType(Messages.INVALID_CLAIM).create(); + } + if (!admin && !claim.permissionManager.hasPermission(player.getGameProfile().getId(), Claim.Permission.MODIFY_SUBZONE)) { + throw new SimpleCommandExceptionType(Messages.NO_PERMISSION).create(); + } + + return claim; + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/command/subzone/SubzoneCommand.java b/src/main/java/io/github/indicode/fabric/itsmine/command/subzone/SubzoneCommand.java new file mode 100644 index 0000000..c3d3569 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/command/subzone/SubzoneCommand.java @@ -0,0 +1,35 @@ +package io.github.indicode.fabric.itsmine.command.subzone; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import io.github.indicode.fabric.itsmine.command.*; +import net.minecraft.server.command.ServerCommandSource; + +import static io.github.indicode.fabric.itsmine.command.admin.AdminCommand.PERMISSION_CHECK_ADMIN; +import static io.github.indicode.fabric.itsmine.util.ArgumentUtil.getSubzones; +import static net.minecraft.server.command.CommandManager.literal; + +public class SubzoneCommand { + public static void register(LiteralArgumentBuilder command, CommandDispatcher dispatcher, boolean admin) { + LiteralArgumentBuilder subzone = literal("subzone"); + subzone.requires(PERMISSION_CHECK_ADMIN); + registerSubzone(subzone, dispatcher, admin); + command.then(subzone); + } + + public static void registerSubzone(LiteralArgumentBuilder command, CommandDispatcher dispatcher, boolean admin) { + CreateCommand.register(command, admin); + ExpandCommand.register(command, admin); + InfoCommand.register(command, getSubzones()); + MessageCommand.register(command, admin, getSubzones()); + PermissionCommand.register(command, admin, getSubzones()); + RemoveCommand.register(command, getSubzones(), admin); + RenameCommand.register(command, admin); + RentableCommand.register(command, getSubzones()); + RentCommand.register(command, getSubzones()); + RevenueCommand.register(command, getSubzones()); + FlagsCommand.register(command, admin, getSubzones()); + TrustCommand.register(command, dispatcher, getSubzones(), admin); + TrustedCommand.register(command); + } +} \ No newline at end of file diff --git a/src/main/java/io/github/indicode/fabric/itsmine/config/Config.java b/src/main/java/io/github/indicode/fabric/itsmine/config/Config.java new file mode 100644 index 0000000..06abccc --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/config/Config.java @@ -0,0 +1,49 @@ +package io.github.indicode.fabric.itsmine.config; + +import io.github.indicode.fabric.itsmine.config.sections.DefaultClaimBlockSection; +import io.github.indicode.fabric.itsmine.config.sections.MessageSection; +import io.github.indicode.fabric.itsmine.config.sections.RentSection; +import ninja.leaping.configurate.objectmapping.Setting; +import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable; + + +@ConfigSerializable +public class Config { + + public static final String HEADER = "ItsMine! Main Configuration File"; + + @Setting(value = "debug") + public boolean debug = false; + + @Setting(value = "prefix") + public String prefix = "&f[&aClaims&f] "; + + @Setting(value = "permissionManager", comment = "Values: thimble, luckperms, vanilla") + public String permissionManager = "luckperms"; + + @Setting(value = "claims2d", comment = "If this is enabled, claims reach from 0 to 256 (claim blocks ignore the y-axis)") + public boolean claims2d = true; + + @Setting(value = "defaultClaimBlocks", comment = "Adjust the amount of claimblocks players get upon joining") + public DefaultClaimBlockSection defaultClaimBlockSection = new DefaultClaimBlockSection(); + + @Setting(value = "messages") + private MessageSection messageSection = new MessageSection(); + + @Setting(value = "rent") + private RentSection rentSection = new RentSection(); + + + public MessageSection message(){ + return messageSection; + } + + public DefaultClaimBlockSection claimBlock(){ + return defaultClaimBlockSection; + } + + public RentSection rent(){ + return rentSection; + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/config/sections/DefaultClaimBlockSection.java b/src/main/java/io/github/indicode/fabric/itsmine/config/sections/DefaultClaimBlockSection.java new file mode 100644 index 0000000..4ded101 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/config/sections/DefaultClaimBlockSection.java @@ -0,0 +1,16 @@ +package io.github.indicode.fabric.itsmine.config.sections; + +import ninja.leaping.configurate.objectmapping.Setting; +import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable; + +@ConfigSerializable +public class DefaultClaimBlockSection { + + @Setting(value = "default2D", comment = "2D base claim blocks") + public int default2D = 15625; + + @Setting(value = "default3D", comment = "3D base claim blocks") + public int default3D = 2500; + + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/config/sections/MessageSection.java b/src/main/java/io/github/indicode/fabric/itsmine/config/sections/MessageSection.java new file mode 100644 index 0000000..9852017 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/config/sections/MessageSection.java @@ -0,0 +1,52 @@ +package io.github.indicode.fabric.itsmine.config.sections; + +import ninja.leaping.configurate.objectmapping.Setting; +import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable; + +@ConfigSerializable +public class MessageSection { + @Setting(value = "messageCooldown") + public int messageCooldown = 20; + + @Setting(value = "eventStayTicks", comment = "Sets how many ticks an event message will stay on action bar, Default: -1") + public int eventStayTicks = -1; + + @Setting(value = "noPermission") + public String noPermission = "&cSorry but you don't have permission to do that"; + + @Setting(value = "interactEntity") + public String interactEntity = "&cSorry but you can't interact with Entities here!"; + + @Setting(value = "interactBlock") + public String interactBlock = "&cSorry but you can't interact with Blocks here!"; + + @Setting(value = "openContainer") + public String openContainer = "&cSorry but you can't open containers here!"; + + @Setting(value = "breakBlock") + public String breakBlock = "&cSorry but you can't Break Blocks here!"; + + @Setting(value = "placeBlock") + public String placeBlock = "&cSorry but you can't Place Blocks here!"; + + @Setting(value = "attackEntity") + public String attackEntity = "&cSorry but you can't Attack Entities here!"; + + @Setting(value = "enterDefault", comment = "Variables: %claim% %player%") + public String enterDefault = "&eNow entering claim &6%claim%"; + + @Setting(value = "leaveDefault", comment = "Variables: %claim% %player%") + public String leaveDefault = "&eNow leaving claim &6%claim%"; + + @Setting(value = "cantEnter") + public String cantEnter = "&cSorry but you don't have permission to enter this claim!"; + + @Setting(value = "cantUse") + public String cantUse = "&cSorry but you can't to use that here!"; + + @Setting(value = "longName") + public String longName = "&cThe name of the claim must be less than 30 characters!"; + + @Setting(value = "cantDo") + public String cantDo ="&cSorry but you can't do that!"; +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/config/sections/RentSection.java b/src/main/java/io/github/indicode/fabric/itsmine/config/sections/RentSection.java new file mode 100644 index 0000000..8edb63f --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/config/sections/RentSection.java @@ -0,0 +1,12 @@ +package io.github.indicode.fabric.itsmine.config.sections; + +import ninja.leaping.configurate.objectmapping.Setting; +import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable; + +@ConfigSerializable +public class RentSection { + + @Setting(value = "maxRentTime", comment = "Default: 7776000 (90d)") + public int maxRentTime = 7776000; + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/AbstractFireBlockMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/AbstractFireBlockMixin.java new file mode 100644 index 0000000..bfb739a --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/AbstractFireBlockMixin.java @@ -0,0 +1,25 @@ +package io.github.indicode.fabric.itsmine.mixin; + +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.claim.ClaimFlags; +import net.minecraft.block.AbstractFireBlock; +import net.minecraft.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(AbstractFireBlock.class) +public abstract class AbstractFireBlockMixin { + + @Redirect(method = "onEntityCollision", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;isFireImmune()Z")) + private boolean neverGonnaBurnYouUp(Entity entity) { + Claim claim = ClaimManager.INSTANCE.getClaimAt(entity.getBlockPos(), entity.world.getDimension()); + if (claim != null && !claim.flags.getFlag(ClaimFlags.Flag.FIRE_DAMAGE)) { + return true; + } + + return entity.isFireImmune(); + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/AnimalEntityMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/AnimalEntityMixin.java new file mode 100644 index 0000000..35bd1bf --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/AnimalEntityMixin.java @@ -0,0 +1,49 @@ +package io.github.indicode.fabric.itsmine.mixin; + +import blue.endless.jankson.annotation.Nullable; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.ItsMineConfig; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.util.ClaimUtil; +import io.github.indicode.fabric.itsmine.util.WorldUtil; +import net.minecraft.entity.passive.AnimalEntity; +import net.minecraft.network.packet.s2c.play.TitleS2CPacket; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; +import net.minecraft.world.World; +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.callback.CallbackInfoReturnable; + +@Mixin(AnimalEntity.class) +public abstract class AnimalEntityMixin { + + @Shadow @Nullable + public abstract ServerPlayerEntity getLovingPlayer(); + + @Shadow public abstract void resetLoveTicks(); + + @Inject(method = "canBreedWith", at = @At(value = "HEAD"), cancellable = true) + private void canBreed(AnimalEntity other, CallbackInfoReturnable cir){ + World world = other.getEntityWorld(); + Claim claim = ClaimManager.INSTANCE.getClaimAt(other.getBlockPos(), other.world.getDimension()); + if(claim != null){ + if(claim.isChild){ + claim = ClaimUtil.getParentClaim(claim); + } +// if(claim.getEntities(other.getEntityWorld().getServer().getWorld(other.getEntityWorld().getDimension())) > 100){ + if(claim.getEntities(WorldUtil.getServerWorld(other.getEntityWorld().getDimension())) > 100){ + ServerPlayerEntity player = this.getLovingPlayer(); + if(player != null){ + player.networkHandler.sendPacket(new TitleS2CPacket(TitleS2CPacket.Action.ACTIONBAR, new LiteralText("You reached the passive entity limit in your claim!").formatted(Formatting.RED), -1, ItsMineConfig.main().message().eventStayTicks, -1)); + } + this.resetLoveTicks(); + cir.setReturnValue(false); + } + } + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/BlockActionPacketMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/BlockActionPacketMixin.java index c044f66..7c78304 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/BlockActionPacketMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/BlockActionPacketMixin.java @@ -1,9 +1,7 @@ package io.github.indicode.fabric.itsmine.mixin; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; import net.minecraft.block.Block; -import net.minecraft.network.packet.s2c.play.BlockActionS2CPacket; +import net.minecraft.network.packet.s2c.play.BlockEventS2CPacket; import net.minecraft.util.math.BlockPos; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -11,17 +9,17 @@ /** * @author Indigo Amann */ -@Mixin(BlockActionS2CPacket.class) +@Mixin(BlockEventS2CPacket.class) public interface BlockActionPacketMixin { @Accessor("pos") - public BlockPos getPos(); + BlockPos getPos(); @Accessor("type") - public int getType(); + int getType(); @Accessor("data") - public int getData(); + int getData(); @Accessor("block") - public Block getBlock(); + Block getBlock(); } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/BoatItemMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/BoatItemMixin.java new file mode 100644 index 0000000..67f8af0 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/BoatItemMixin.java @@ -0,0 +1,45 @@ +package io.github.indicode.fabric.itsmine.mixin; + +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.Messages; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.BoatItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Hand; +import net.minecraft.util.TypedActionResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.RayTraceContext; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(BoatItem.class) +public abstract class BoatItemMixin extends Item { + + public BoatItemMixin(Settings settings) { + super(settings); + } + + @Inject(method = "use", at = @At(value = "HEAD"), cancellable = true) + private void dontSpawn(World world, PlayerEntity user, Hand hand, CallbackInfoReturnable> cir) { + ItemStack itemStack = user.getStackInHand(hand); + HitResult hitResult = rayTrace(world, user, RayTraceContext.FluidHandling.ANY); + Vec3d pos = hitResult.getPos(); + Claim claim = ClaimManager.INSTANCE.getClaimAt(new BlockPos(pos.getX(), pos.getY(), pos.getZ()), user.world.getDimension()); + + if (claim != null){ + if(!claim.hasPermission(user.getUuid(), Claim.Permission.BUILD) || !claim.hasPermission(user.getUuid(), Claim.Permission.SPAWN_BOAT)){ + user.sendSystemMessage(Messages.NO_PERMISSION, user.getUuid()); + cir.setReturnValue(TypedActionResult.fail(itemStack)); + } + } + + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/BucketItemMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/BucketItemMixin.java index caa36aa..d85d3fa 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/BucketItemMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/BucketItemMixin.java @@ -11,5 +11,5 @@ @Mixin(BucketItem.class) public interface BucketItemMixin { @Accessor("fluid") - public Fluid getFluid(); + Fluid getFluid(); } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/CommandManagerMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/CommandManagerMixin.java index 6c40133..800fd8f 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/CommandManagerMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/CommandManagerMixin.java @@ -1,8 +1,7 @@ package io.github.indicode.fabric.itsmine.mixin; import com.mojang.brigadier.CommandDispatcher; -import io.github.indicode.fabric.itsmine.ClaimCommand; -import net.minecraft.server.command.CommandManager; +import io.github.indicode.fabric.itsmine.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -13,12 +12,13 @@ /** * @author Indigo Amann */ -@Mixin(CommandManager.class) +@Mixin(net.minecraft.server.command.CommandManager.class) public class CommandManagerMixin { @Shadow private CommandDispatcher dispatcher; @Inject(method = "", at = @At("RETURN")) public void addCommand(boolean bool, CallbackInfo ci) { - ClaimCommand.register(dispatcher); + CommandManager.dispatcher = this.dispatcher; + CommandManager.register(); } } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/EnderDragonEntityMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/EnderDragonEntityMixin.java new file mode 100644 index 0000000..e29b880 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/EnderDragonEntityMixin.java @@ -0,0 +1,27 @@ +package io.github.indicode.fabric.itsmine.mixin; + +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.claim.ClaimFlags; +import net.minecraft.entity.boss.dragon.EnderDragonEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(EnderDragonEntity.class) +public class EnderDragonEntityMixin { + + @Redirect(method = "destroyBlocks", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;removeBlock(Lnet/minecraft/util/math/BlockPos;Z)Z")) + private boolean dontTouchieMyBlocksStupidDragon(World world, BlockPos pos, boolean move) { + Claim claim = ClaimManager.INSTANCE.getClaimAt(pos, world.getDimension()); + + if (claim != null && !claim.flags.getFlag(ClaimFlags.Flag.EXPLOSION_DESTRUCTION)) { + return false; + } + + return world.removeBlock(pos, false); + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/EnderPearlItemMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/EnderPearlItemMixin.java new file mode 100644 index 0000000..498c9eb --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/EnderPearlItemMixin.java @@ -0,0 +1,31 @@ +package io.github.indicode.fabric.itsmine.mixin; + +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.Messages; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.EnderPearlItem; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Hand; +import net.minecraft.util.TypedActionResult; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(EnderPearlItem.class) +public class EnderPearlItemMixin { + + @Inject(method = "use", at = @At(value = "HEAD"), cancellable = true) + private void modifyUse(World world, PlayerEntity user, Hand hand, CallbackInfoReturnable> cir) { + ItemStack itemStack = user.getStackInHand(hand); + Claim claim = ClaimManager.INSTANCE.getClaimAt(user.getBlockPos(), user.world.getDimension()); + + if (claim != null && !claim.hasPermission(user.getUuid(), Claim.Permission.USE_ENDER_PEARL)) { + user.sendSystemMessage(Messages.MSG_CANT_USE, user.getUuid()); + cir.setReturnValue(TypedActionResult.fail(itemStack)); + } + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/EntityMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/EntityMixin.java index 3abbc4d..f24ad2e 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/EntityMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/EntityMixin.java @@ -1,16 +1,21 @@ package io.github.indicode.fabric.itsmine.mixin; -import io.github.indicode.fabric.itsmine.Claim; -import io.github.indicode.fabric.itsmine.ClaimManager; -import io.github.indicode.fabric.itsmine.Functions; +import io.github.indicode.fabric.itsmine.*; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.claim.ClaimFlags; +import io.github.indicode.fabric.itsmine.util.ChatColor; +import io.github.indicode.fabric.itsmine.util.ClaimUtil; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.packet.s2c.play.PlaySoundIdS2CPacket; import net.minecraft.network.packet.s2c.play.TitleS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.sound.SoundEvent; +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvents; import net.minecraft.text.LiteralText; -import net.minecraft.text.Texts; -import net.minecraft.util.Formatting; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.registry.Registry; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -22,45 +27,106 @@ public abstract class EntityMixin { @Shadow public World world; - private Claim pclaim = null; - @Inject(method = "setPos", at = @At("HEAD")) - public void doPrePosActions(double x, double y, double z, CallbackInfo ci) { - if (!world.isClient && (Object)this instanceof PlayerEntity) { - PlayerEntity player = (PlayerEntity) (Object) this; - if (player.getSenseCenterPos() == null) return; - pclaim = ClaimManager.INSTANCE.getClaimAt(player.getSenseCenterPos(), player.world.dimension.getType()); - } - } - @Inject(method = "setPos", at = @At("RETURN")) - public void doPostPosActions(double x, double y, double z, CallbackInfo ci) { - if (!world.isClient && (Object)this instanceof PlayerEntity) { - PlayerEntity player = (PlayerEntity) (Object) this; - if (player.getSenseCenterPos() == null) return; - Claim claim = ClaimManager.INSTANCE.getClaimAt(player.getSenseCenterPos(), player.world.dimension.getType()); - if (pclaim != claim && player instanceof ServerPlayerEntity) { - ServerPlayerEntity serverPlayerEntity = (ServerPlayerEntity)player; - if (serverPlayerEntity.networkHandler != null) { - serverPlayerEntity.networkHandler.sendPacket(new TitleS2CPacket(TitleS2CPacket.Action.ACTIONBAR, new LiteralText("Now " + (claim == null ? "leaving" : "entering") + " claim ").formatted(Formatting.YELLOW).append(new LiteralText(claim == null ? pclaim.name : claim.name).formatted(Formatting.GOLD)))); - } - } - } + @Shadow public abstract Vec3d getPos(); + + @Shadow public abstract void tick(); + + @Shadow public boolean removed; + +// private Claim pclaim = null; +// @Inject(method = "setPos", at = @At("HEAD")) +// public void doPrePosActions(double x, double y, double z, CallbackInfo ci) { +// if (!world.isClient && (Object)this instanceof PlayerEntity) { +// PlayerEntity player = (PlayerEntity) (Object) this; +// if (player.getBlockPos() == null) return; +// pclaim = ClaimManager.INSTANCE.getClaimAt(player.getBlockPos(), player.world.getDimension()); +// } +// } +// @Inject(method = "setPos", at = @At("RETURN")) +// public void doPostPosActions(double x, double y, double z, CallbackInfo ci) { +// if (!world.isClient && (Object)this instanceof PlayerEntity) { +// PlayerEntity player = (PlayerEntity) (Object) this; +// if (player.getBlockPos() == null) return; +// Claim claim = ClaimManager.INSTANCE.getClaimAt(player.getBlockPos(), player.world.getDimension()); +// if (pclaim != claim && player instanceof ServerPlayerEntity) { +// ServerPlayerEntity serverPlayerEntity = (ServerPlayerEntity)player; +// if (serverPlayerEntity.networkHandler != null) { +// String message = null; +// if (pclaim != null && claim == null) +// message = getFormattedEventMessage(player, pclaim, false); +// else if (claim != null) +// message = getFormattedEventMessage(player, claim, true); +// +// if (message != null) +// serverPlayerEntity.networkHandler.sendPacket(new TitleS2CPacket(TitleS2CPacket.Action.ACTIONBAR, new LiteralText(ChatColor.translate(message)), -1, ItsMineConfig.main().message().eventStayTicks, -1)); +// +// if (claim != null && claim.flags.getFlag(ClaimFlags.Flag.ENTER_SOUND)) { +// serverPlayerEntity.networkHandler.sendPacket(new PlaySoundIdS2CPacket(Registry.SOUND_EVENT.getId(SoundEvents.BLOCK_CONDUIT_ACTIVATE), SoundCategory.MASTER, this.getPos(), 2, 1.2F)); +// } +// } +// } +// } +// } + + + private String getFormattedEventMessage(PlayerEntity player, Claim claim, boolean enter) { + if (player == null || claim == null) + return ""; + + String str = enter ? claim.enterMessage : claim.leaveMessage; + return ChatColor.translate(str == null ? (enter ? ItsMineConfig.main().message().enterDefault : ItsMineConfig.main().message().leaveDefault) : str).replace("%claim%", claim.name) + .replace("%player%", player.getName().asString()); } + + @Inject(method = "tick", at = @At("RETURN")) public void doTickActions(CallbackInfo ci) { - if (!world.isClient && (Object)this instanceof PlayerEntity) { - PlayerEntity player = (PlayerEntity) (Object)this; - if (player.getSenseCenterPos() == null) return; + if (!world.isClient && (Object) this instanceof PlayerEntity) { + PlayerEntity player = (PlayerEntity) (Object) this; + if (player.getBlockPos() == null) { + return; + } + boolean old = player.abilities.allowFlying; - Claim claim = ClaimManager.INSTANCE.getClaimAt(player.getSenseCenterPos(), player.world.dimension.getType()); + Claim claim = ClaimManager.INSTANCE.getClaimAt(player.getBlockPos(), player.world.getDimension()); + if (player instanceof ServerPlayerEntity) { - if (player.abilities.allowFlying && ((claim == null || !claim.settings.getSetting(Claim.ClaimSettings.Setting.FLIGHT_ALLOWED) || !claim.hasPermission(player.getGameProfile().getId(), Claim.Permission.FLY)) && Functions.isClaimFlying(player.getGameProfile().getId()))) { + if ( + player.abilities.allowFlying && + shouldChange(player) && + ( + ( + !ClaimManager.INSTANCE.flyers.contains(player.getUuid()) || + claim == null || !claim.flags.getFlag(ClaimFlags.Flag.FLIGHT_ALLOWED) || + !claim.hasPermission(player.getGameProfile().getId(), Claim.Permission.FLIGHT) || + !Functions.canFly((ServerPlayerEntity) player) + ) + //&& Functions.isClaimFlying(player.getGameProfile().getId()) + ) + ) { player.abilities.allowFlying = false; player.abilities.flying = false; Functions.setClaimFlying(player.getGameProfile().getId(), false); - } else if (!player.abilities.allowFlying && claim != null && claim.settings.getSetting(Claim.ClaimSettings.Setting.FLIGHT_ALLOWED) && claim.hasPermission(player.getGameProfile().getId(), Claim.Permission.FLY) && Functions.canClaimFly((ServerPlayerEntity) player)) { + + World world = player.getEntityWorld(); + if (world.getBlockState(player.getBlockPos().down(5)).isAir() && !player.isOnGround()) { + BlockPos pos = ClaimUtil.getPosOnGround(player.getBlockPos(), world); + player.teleport(pos.getX(), pos.getY(), pos.getZ()); + } + } else if ( + !player.abilities.allowFlying && + ClaimManager.INSTANCE.flyers.contains(player.getUuid()) && + shouldChange(player) && + claim != null && + claim.flags.getFlag(ClaimFlags.Flag.FLIGHT_ALLOWED) + && claim.hasPermission(player.getUuid(), Claim.Permission.FLIGHT) + && Functions.canFly((ServerPlayerEntity) player) + ///&& Functions.canClaimFly((ServerPlayerEntity) player) + ) { player.abilities.allowFlying = true; - Functions.setClaimFlying(player.getGameProfile().getId(), true); + //Functions.setClaimFlying(player.getGameProfile().getId(), true); } + if (player.abilities.allowFlying != old) { player.sendAbilitiesUpdate(); } @@ -68,4 +134,8 @@ public void doTickActions(CallbackInfo ci) { } } + + private boolean shouldChange(PlayerEntity player) { + return !player.isSpectator() && !player.isCreative(); + } } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/ExplosionMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/ExplosionMixin.java index a4a55a3..4447711 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/ExplosionMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/ExplosionMixin.java @@ -1,14 +1,17 @@ package io.github.indicode.fabric.itsmine.mixin; -import io.github.indicode.fabric.itsmine.Claim; +import io.github.indicode.fabric.itsmine.claim.Claim; import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.claim.ClaimFlags; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.explosion.Explosion; +import org.spongepowered.asm.mixin.Final; 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.Redirect; @@ -17,21 +20,29 @@ */ @Mixin(Explosion.class) public class ExplosionMixin { + @Shadow @Final private World world; + @Redirect(method = "collectBlocksAndDamageEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/BlockState;")) - private BlockState theyCallMeBedrock(World world, BlockPos blockPos_1) { - Claim claim = ClaimManager.INSTANCE.getClaimAt(blockPos_1, world.getDimension().getType()); - if (claim != null && !world.isAir(blockPos_1)) { - if (!(Boolean) claim.settings.getSetting(Claim.ClaimSettings.Setting.EXPLOSIONS)) return Blocks.BEDROCK.getDefaultState(); + private BlockState theyCallMeBedrock(World world, BlockPos pos) { + Claim claim = ClaimManager.INSTANCE.getClaimAt(pos, world.getDimension()); + if (claim != null && !world.isAir(pos) && !world.getBlockState(pos).getBlock().equals(Blocks.TNT)) { + if (!claim.flags.getFlag(ClaimFlags.Flag.EXPLOSION_DESTRUCTION)) { + return Blocks.BEDROCK.getDefaultState(); + } } - return world.getBlockState(blockPos_1); + return world.getBlockState(pos); } + @Redirect(method = "collectBlocksAndDamageEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;isImmuneToExplosion()Z")) private boolean claimDeniesExplosion(Entity entity) { - BlockPos blockPos_1 = entity.getSenseCenterPos(); - Claim claim = ClaimManager.INSTANCE.getClaimAt(blockPos_1, entity.world.getDimension().getType()); + BlockPos blockPos_1 = entity.getBlockPos(); + Claim claim = ClaimManager.INSTANCE.getClaimAt(blockPos_1, entity.world.getDimension()); if (claim != null) { - if (!(Boolean) claim.settings.getSetting(Claim.ClaimSettings.Setting.EXPLOSIONS)) return true; + if (!claim.flags.getFlag(ClaimFlags.Flag.EXPLOSION_DAMAGE)) { + return true; + } } + return entity.isImmuneToExplosion(); } } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/FarmlandBlockMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/FarmlandBlockMixin.java new file mode 100644 index 0000000..d3b3fa8 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/FarmlandBlockMixin.java @@ -0,0 +1,27 @@ +package io.github.indicode.fabric.itsmine.mixin; + +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.claim.ClaimFlags; +import net.minecraft.block.FarmlandBlock; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(FarmlandBlock.class) +public abstract class FarmlandBlockMixin { + + @Inject(method = "onLandedUpon", at = @At(value = "HEAD", target = "Lnet/minecraft/block/FarmlandBlock;onLandedUpon(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/Entity;F)V"), cancellable = true) + private void dontYouDareFarmMe(World world, BlockPos pos, Entity entity, float distance, CallbackInfo ci) { + Claim claim = ClaimManager.INSTANCE.getClaimAt(pos, world.getDimension()); + + if (claim != null && !claim.flags.getFlag(ClaimFlags.Flag.BREAK_FARMLANDS)) { + ci.cancel(); + } + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/FireBlockMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/FireBlockMixin.java index 449dea6..4ec5b1f 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/FireBlockMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/FireBlockMixin.java @@ -1,7 +1,8 @@ package io.github.indicode.fabric.itsmine.mixin; -import io.github.indicode.fabric.itsmine.Claim; +import io.github.indicode.fabric.itsmine.claim.Claim; import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.claim.ClaimFlags; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.FireBlock; @@ -28,35 +29,35 @@ public abstract class FireBlockMixin { @Redirect(method = "scheduledTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/FireBlock;trySpreadingFire(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;ILjava/util/Random;I)V")) private void dontBurnClaims(FireBlock fireBlock, World world, BlockPos newPos, int int_1, Random random_1, int int_2, BlockState blockState_1, ServerWorld serverWorld_1, BlockPos oldPos, Random random_1_) { - Claim oldClaim = ClaimManager.INSTANCE.getClaimAt(oldPos, world.getDimension().getType()); - Claim newClaim = ClaimManager.INSTANCE.getClaimAt(newPos, world.getDimension().getType()); + Claim oldClaim = ClaimManager.INSTANCE.getClaimAt(oldPos, world.getDimension()); + Claim newClaim = ClaimManager.INSTANCE.getClaimAt(newPos, world.getDimension()); if (oldClaim != newClaim) { if (oldClaim == null) { - if (!(Boolean) newClaim.settings.getSetting(Claim.ClaimSettings.Setting.FIRE_CROSSES_BORDERS)) return; + if (!newClaim.flags.getFlag(ClaimFlags.Flag.FIRE_CROSSES_BORDERS)) return; } else if (newClaim == null) { - if (!(Boolean) oldClaim.settings.getSetting(Claim.ClaimSettings.Setting.FIRE_CROSSES_BORDERS)) return; + if (!oldClaim.flags.getFlag(ClaimFlags.Flag.FIRE_CROSSES_BORDERS)) return; } else { - if (!(Boolean) oldClaim.settings.getSetting(Claim.ClaimSettings.Setting.FIRE_CROSSES_BORDERS) || - !(Boolean) newClaim.settings.getSetting(Claim.ClaimSettings.Setting.FIRE_CROSSES_BORDERS)) return; + if (!oldClaim.flags.getFlag(ClaimFlags.Flag.FIRE_CROSSES_BORDERS) || + !newClaim.flags.getFlag(ClaimFlags.Flag.FIRE_CROSSES_BORDERS)) return; } } trySpreadingFire(world, newPos, int_1, random_1, int_2); } @Redirect(method = "scheduledTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z", ordinal = 1)) private boolean dontCauseFire2(ServerWorld world, BlockPos newPos, BlockState blockState_1, int int_1, BlockState blockState_1_, ServerWorld serverWorld_1, BlockPos oldPos, Random random_1_) { - Claim oldClaim = ClaimManager.INSTANCE.getClaimAt(oldPos, world.getDimension().getType()); - Claim newClaim = ClaimManager.INSTANCE.getClaimAt(newPos, world.getDimension().getType()); + Claim oldClaim = ClaimManager.INSTANCE.getClaimAt(oldPos, world.getDimension()); + Claim newClaim = ClaimManager.INSTANCE.getClaimAt(newPos, world.getDimension()); if (oldClaim != newClaim) { if (oldClaim == null) { - if (!(Boolean) newClaim.settings.getSetting(Claim.ClaimSettings.Setting.FIRE_CROSSES_BORDERS)) + if (!newClaim.flags.getFlag(ClaimFlags.Flag.FIRE_CROSSES_BORDERS)) return false; } else if (newClaim == null) { - if (!(Boolean) oldClaim.settings.getSetting(Claim.ClaimSettings.Setting.FIRE_CROSSES_BORDERS)) + if (!oldClaim.flags.getFlag(ClaimFlags.Flag.FIRE_CROSSES_BORDERS)) return false; } else { - if (!(Boolean) oldClaim.settings.getSetting(Claim.ClaimSettings.Setting.FIRE_CROSSES_BORDERS) || - !(Boolean) newClaim.settings.getSetting(Claim.ClaimSettings.Setting.FIRE_CROSSES_BORDERS)) + if (!oldClaim.flags.getFlag(ClaimFlags.Flag.FIRE_CROSSES_BORDERS) || + !newClaim.flags.getFlag(ClaimFlags.Flag.FIRE_CROSSES_BORDERS)) return false; } } @@ -73,20 +74,20 @@ private boolean dontCauseFire(World world, BlockPos oldPos, BlockState blockStat if (directions.isEmpty()) { return world.setBlockState(oldPos, blockState_1, int_1); } - Claim oldClaim = ClaimManager.INSTANCE.getClaimAt(oldPos, world.getDimension().getType()); + Claim oldClaim = ClaimManager.INSTANCE.getClaimAt(oldPos, world.getDimension()); Iterator iterator = directions.iterator(); for (Direction direction = iterator.next(); iterator.hasNext(); direction = iterator.next()) { BlockPos newPos = oldPos.offset(direction); - Claim newClaim = ClaimManager.INSTANCE.getClaimAt(newPos, world.getDimension().getType()); + Claim newClaim = ClaimManager.INSTANCE.getClaimAt(newPos, world.getDimension()); if (oldClaim != newClaim) { if (oldClaim == null) { - if (!(Boolean) newClaim.settings.getSetting(Claim.ClaimSettings.Setting.FIRE_CROSSES_BORDERS)) iterator.remove(); + if (!newClaim.flags.getFlag(ClaimFlags.Flag.FIRE_CROSSES_BORDERS)) iterator.remove(); } else if (newClaim == null) { - if (!(Boolean) oldClaim.settings.getSetting(Claim.ClaimSettings.Setting.FIRE_CROSSES_BORDERS)) iterator.remove(); + if (!oldClaim.flags.getFlag(ClaimFlags.Flag.FIRE_CROSSES_BORDERS)) iterator.remove(); } else { - if (!(Boolean) oldClaim.settings.getSetting(Claim.ClaimSettings.Setting.FIRE_CROSSES_BORDERS) || - !(Boolean) newClaim.settings.getSetting(Claim.ClaimSettings.Setting.FIRE_CROSSES_BORDERS)) iterator.remove(); + if (!oldClaim.flags.getFlag(ClaimFlags.Flag.FIRE_CROSSES_BORDERS) || + !newClaim.flags.getFlag(ClaimFlags.Flag.FIRE_CROSSES_BORDERS)) iterator.remove(); } } } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/FluidMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/FluidMixin.java index d7e54f3..c46ed2f 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/FluidMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/FluidMixin.java @@ -1,38 +1,39 @@ package io.github.indicode.fabric.itsmine.mixin; -import io.github.indicode.fabric.itsmine.Claim; import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.claim.ClaimFlags; import net.minecraft.block.BlockState; -import net.minecraft.fluid.BaseFluid; +import net.minecraft.fluid.FlowableFluid; import net.minecraft.fluid.FluidState; -import net.minecraft.fluid.LavaFluid; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; -import net.minecraft.world.IWorld; +import net.minecraft.world.WorldAccess; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CancellationException; /** * @author Indigo Amann */ -@Mixin(BaseFluid.class) +@Mixin(FlowableFluid.class) public class FluidMixin { @Inject(method = "flow", at = @At("HEAD"), cancellable = true) - private void dontFlow(IWorld world, BlockPos newPos, BlockState blockState_1, Direction direction, FluidState fluidState_1, CallbackInfo ci) { + private void dontFlow(WorldAccess world, BlockPos newPos, BlockState state, Direction direction, FluidState fluidState, CallbackInfo ci) { BlockPos oldPos = newPos.offset(direction.getOpposite()); - Claim oldClaim = ClaimManager.INSTANCE.getClaimAt(oldPos, world.getDimension().getType()); - Claim newClaim = ClaimManager.INSTANCE.getClaimAt(newPos, world.getDimension().getType()); + Claim oldClaim = ClaimManager.INSTANCE.getClaimAt(oldPos, world.getDimension()); + Claim newClaim = ClaimManager.INSTANCE.getClaimAt(newPos, world.getDimension()); if (oldClaim != newClaim) { if (oldClaim == null) { - if (!(Boolean) newClaim.settings.getSetting(Claim.ClaimSettings.Setting.FLUID_CROSSES_BORDERS)) ci.cancel(); + if (!newClaim.flags.getFlag(ClaimFlags.Flag.FLUID_CROSSES_BORDERS)) ci.cancel(); } else if (newClaim == null) { - if (!(Boolean) oldClaim.settings.getSetting(Claim.ClaimSettings.Setting.FLUID_CROSSES_BORDERS)) ci.cancel(); + if (!oldClaim.flags.getFlag(ClaimFlags.Flag.FLUID_CROSSES_BORDERS)) ci.cancel(); } else { - if (!(Boolean) oldClaim.settings.getSetting(Claim.ClaimSettings.Setting.FLUID_CROSSES_BORDERS) || - !(Boolean) newClaim.settings.getSetting(Claim.ClaimSettings.Setting.FLUID_CROSSES_BORDERS)) ci.cancel(); + if (!oldClaim.flags.getFlag(ClaimFlags.Flag.FLUID_CROSSES_BORDERS) || + !newClaim.flags.getFlag(ClaimFlags.Flag.FLUID_CROSSES_BORDERS)) ci.cancel(); } } } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/IntegratedServerMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/IntegratedServerMixin.java deleted file mode 100644 index 8b47ba8..0000000 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/IntegratedServerMixin.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.github.indicode.fabric.itsmine.mixin; - -import com.google.gson.JsonElement; -import io.github.indicode.fabric.itsmine.ClaimManager; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtIo; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.integrated.IntegratedServer; -import net.minecraft.world.level.LevelGeneratorType; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; - -/** - * @author Indigo Amann - */ -@Mixin(IntegratedServer.class) -public class IntegratedServerMixin { - @Inject(method = "loadWorld", at = @At("RETURN")) - private void loadClaims(String string_1, String string_2, long long_1, LevelGeneratorType levelGeneratorType_1, JsonElement jsonElement_1, CallbackInfo ci) { - File claims = new File(((MinecraftServer)(Object)this).getLevelStorage().getSavesDirectory() + "/" + string_1 + "/claims.dat"); - File claims_old = new File(((MinecraftServer)(Object)this).getLevelStorage().getSavesDirectory() + "/" + string_1 + "/claims.dat_old"); - ClaimManager.INSTANCE = new ClaimManager(); - if (!claims.exists()) { - if (claims_old.exists()) {} - else return; - } - try { - if (!claims.exists() && claims_old.exists()) throw new FileNotFoundException(); - ClaimManager.INSTANCE.fromNBT(NbtIo.readCompressed(new FileInputStream(claims))); - } catch (IOException e) { - System.err.println("Could not load claims.dat:"); - e.printStackTrace(); - if (claims_old.exists()) { - System.out.println("Attempting to load backup claims..."); - try { - ClaimManager.INSTANCE.fromNBT(NbtIo.readCompressed(new FileInputStream(claims_old))); - } catch (IOException e2) { - throw new RuntimeException("Could not load claims.dat_old - Crashing server to save data. Remove or fix claims.dat or claims.dat_old to continue"); - - } - } - } - } -} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/LavaMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/LavaMixin.java index 9abcaa1..a85ce70 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/LavaMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/LavaMixin.java @@ -1,14 +1,15 @@ package io.github.indicode.fabric.itsmine.mixin; -import io.github.indicode.fabric.itsmine.Claim; import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.claim.ClaimFlags; import net.minecraft.block.BlockState; import net.minecraft.fluid.FluidState; import net.minecraft.fluid.LavaFluid; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; -import net.minecraft.world.IWorld; import net.minecraft.world.World; +import net.minecraft.world.WorldAccess; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -23,35 +24,38 @@ @Mixin(LavaFluid.class) public class LavaMixin { @Inject(method = "flow", at = @At("HEAD"), cancellable = true) - private void dontFlow(IWorld world, BlockPos newPos, BlockState blockState_1, Direction direction, FluidState fluidState_1, CallbackInfo ci) { + private void dontFlow(WorldAccess world, BlockPos newPos, BlockState state, Direction direction, FluidState fluidState, CallbackInfo ci) { BlockPos oldPos = newPos.offset(direction.getOpposite()); - Claim oldClaim = ClaimManager.INSTANCE.getClaimAt(oldPos, world.getDimension().getType()); - Claim newClaim = ClaimManager.INSTANCE.getClaimAt(newPos, world.getDimension().getType()); + Claim oldClaim = ClaimManager.INSTANCE.getClaimAt(oldPos, world.getDimension()); + Claim newClaim = ClaimManager.INSTANCE.getClaimAt(newPos, world.getDimension()); if (oldClaim != newClaim) { if (oldClaim == null) { - if (!(Boolean) newClaim.settings.getSetting(Claim.ClaimSettings.Setting.FLUID_CROSSES_BORDERS)) ci.cancel(); + if (!newClaim.flags.getFlag(ClaimFlags.Flag.FLUID_CROSSES_BORDERS)) ci.cancel(); } else if (newClaim == null) { - if (!(Boolean) oldClaim.settings.getSetting(Claim.ClaimSettings.Setting.FLUID_CROSSES_BORDERS)) ci.cancel(); + if (!oldClaim.flags.getFlag(ClaimFlags.Flag.FLUID_CROSSES_BORDERS)) ci.cancel(); } else { - if (!(Boolean) oldClaim.settings.getSetting(Claim.ClaimSettings.Setting.FLUID_CROSSES_BORDERS) || - !(Boolean) newClaim.settings.getSetting(Claim.ClaimSettings.Setting.FLUID_CROSSES_BORDERS)) ci.cancel(); + if (!oldClaim.flags.getFlag(ClaimFlags.Flag.FLUID_CROSSES_BORDERS) || + !newClaim.flags.getFlag(ClaimFlags.Flag.FLUID_CROSSES_BORDERS)) ci.cancel(); } } } @Redirect(method = "onRandomTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;)Z")) public boolean neverGonnaBurnMeUp(World world, BlockPos newPos, BlockState blockState_1, World world_1, BlockPos oldPos, FluidState fluidState_1, Random random_1) { - Claim oldClaim = ClaimManager.INSTANCE.getClaimAt(oldPos, world.getDimension().getType()); - Claim newClaim = ClaimManager.INSTANCE.getClaimAt(newPos, world.getDimension().getType()); + Claim oldClaim = ClaimManager.INSTANCE.getClaimAt(oldPos, world.getDimension()); + Claim newClaim = ClaimManager.INSTANCE.getClaimAt(newPos, world.getDimension()); if (oldClaim != newClaim) { if (oldClaim == null) { - if (!(Boolean) newClaim.settings.getSetting(Claim.ClaimSettings.Setting.FLUID_CROSSES_BORDERS)) return false; + if (!newClaim.flags.getFlag(ClaimFlags.Flag.FLUID_CROSSES_BORDERS)) + return false; } else if (newClaim == null) { - if (!(Boolean) oldClaim.settings.getSetting(Claim.ClaimSettings.Setting.FLUID_CROSSES_BORDERS)) return false; + if (!oldClaim.flags.getFlag(ClaimFlags.Flag.FLUID_CROSSES_BORDERS)) + return false; } else { - if (!(Boolean) oldClaim.settings.getSetting(Claim.ClaimSettings.Setting.FLUID_CROSSES_BORDERS) || - !(Boolean) newClaim.settings.getSetting(Claim.ClaimSettings.Setting.FLUID_CROSSES_BORDERS)) return false; + if (!oldClaim.flags.getFlag(ClaimFlags.Flag.FLUID_CROSSES_BORDERS) || + !newClaim.flags.getFlag(ClaimFlags.Flag.FLUID_CROSSES_BORDERS)) + return false; } } return world.setBlockState(newPos, blockState_1); diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/LecternScreenHandlerMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/LecternScreenHandlerMixin.java new file mode 100644 index 0000000..86ae657 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/LecternScreenHandlerMixin.java @@ -0,0 +1,40 @@ +//package io.github.indicode.fabric.itsmine.mixin; +// +//import io.github.indicode.fabric.itsmine.claim.Claim; +//import io.github.indicode.fabric.itsmine.ClaimManager; +//import io.github.indicode.fabric.itsmine.util.ClaimUtil; +//import net.minecraft.entity.player.PlayerEntity; +//import net.minecraft.screen.LecternScreenHandler; +//import net.minecraft.text.LiteralText; +//import net.minecraft.util.Formatting; +//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.callback.CallbackInfoReturnable; +// +//@Mixin(LecternScreenHandler.class) +//public abstract class LecternScreenHandlerMixin { +// +// +// @Inject(method = "onButtonClick", at = @At(value = "HEAD")) +// private void canTake(PlayerEntity player, int id, CallbackInfoReturnable cir){ +// player.sendSystemMessage(new LiteralText("onButtonClick")); +// cir.setReturnValue(true); +// cir.setReturnValue(false); +// Claim claim = ClaimManager.INSTANCE.getClaimAt(player.getBlockPos(), player.dimension); +// if(claim != null){ +// if(claim.isChild) claim = ClaimUtil.getParentClaim(claim); +// if(!claim.hasPermission(player.getUuid(), Claim.Permission.INTERACT_LECTERN)){ +// player.sendSystemMessage(new LiteralText("return true").formatted(Formatting.GREEN)); +// cir.setReturnValue(true); +// } else { +// player.sendSystemMessage(new LiteralText("return false").formatted(Formatting.GREEN)); +// cir.setReturnValue(false); +// } +// } else { +// player.sendSystemMessage(new LiteralText("return true").formatted(Formatting.GREEN)); +// cir.setReturnValue(true); +// } +// } +//} \ No newline at end of file diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/LevelStorageSessionMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/LevelStorageSessionMixin.java new file mode 100644 index 0000000..09380e1 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/LevelStorageSessionMixin.java @@ -0,0 +1,83 @@ +package io.github.indicode.fabric.itsmine.mixin; + +import io.github.indicode.fabric.itsmine.ClaimManager; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.SaveProperties; +import net.minecraft.world.level.storage.LevelStorage; +import org.spongepowered.asm.mixin.Final; +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.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.io.*; +import java.nio.file.Path; + +@Mixin(LevelStorage.Session.class) +public class LevelStorageSessionMixin { + @Shadow + @Final + private Path directory; + + @Inject(method = "readLevelProperties", at = @At("HEAD")) + public void readWorldProperties(CallbackInfoReturnable cir) { + System.out.println("LevelStorage.Session"); + } + + // @Inject(method = "readLevelProperties", at = @At("HEAD")) +// public void readWorldProperties() { +// ClaimManager.INSTANCE = new ClaimManager(); +// File claims = new File(directory.toFile() + "/claims.dat"); +// File claims_old = new File(directory.toFile() + "/claims.dat_old"); +// if (!claims.exists()) { +// if (claims_old.exists()) {} +// else return; +// } +// try { +// if (!claims.exists() && claims_old.exists()) throw new FileNotFoundException(); +// ClaimManager.INSTANCE.fromNBT(NbtIo.readCompressed(new FileInputStream(claims))); +// } catch (IOException e) { +// System.out.println("Could not load " + claims.getName() + ":"); +// e.printStackTrace(); +// if (claims_old.exists()) { +// System.out.println("Attempting to load backup claims..."); +// try { +// ClaimManager.INSTANCE.fromNBT(NbtIo.readCompressed(new FileInputStream(claims_old))); +// } catch (IOException e2) { +// throw new RuntimeException("Could not load claims.dat_old - Crashing server to save data. Remove or fix claims.dat or claims.dat_old to continue"); +// } +// } +// } +// } + + @Inject(method = "method_27426", at = @At("HEAD")) + public void saveWorld(SaveProperties levelProperties, CompoundTag compoundTag, CallbackInfo info) { + if (ClaimManager.INSTANCE != null) { + File claimDataFile = new File(directory.toFile(), "claims.dat"); + if (claimDataFile.exists()) { + File old = new File(directory.toFile(), "claims.dat_old"); + System.out.println("Saving NBT File: " + claimDataFile.getName() + " " + claimDataFile.length()+ "b " + claimDataFile.getAbsolutePath()); + if(claimDataFile.length() > 45){ + System.out.println("Creating backup of NBT File: " + claimDataFile.getName()); + if (old.exists()) old.delete(); + claimDataFile.renameTo(old); + claimDataFile.delete(); + } else { + System.out.println("Aborting backup!" + claimDataFile.getName() + " may be broken, keeping " + old.getName()); + } + } + try { + claimDataFile.createNewFile(); + CompoundTag tag = ClaimManager.INSTANCE.toNBT(); + NbtIo.writeCompressed(tag, new FileOutputStream(claimDataFile)); + } catch (IOException e) { + System.out.println("Could not save " + claimDataFile.getName() + ":"); + e.printStackTrace(); + } + } + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/MinecraftServerMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/MinecraftServerMixin.java index 704137f..1082f6a 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/MinecraftServerMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/MinecraftServerMixin.java @@ -1,54 +1,19 @@ package io.github.indicode.fabric.itsmine.mixin; -import com.google.gson.JsonElement; -import io.github.indicode.fabric.itsmine.Claim; -import io.github.indicode.fabric.itsmine.ClaimManager; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtIo; +import io.github.indicode.fabric.itsmine.util.ClaimUtil; import net.minecraft.server.MinecraftServer; -import net.minecraft.world.level.LevelGeneratorType; +import net.minecraft.server.WorldGenerationProgressListener; 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.callback.CallbackInfo; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; - -/** - * @author Indigo Amann - */ @Mixin(MinecraftServer.class) -public abstract class MinecraftServerMixin { - @Inject(method = "loadWorld", at = @At("RETURN")) - private void loadClaims(String string_1, String string_2, long long_1, LevelGeneratorType levelGeneratorType_1, JsonElement jsonElement_1, CallbackInfo ci) { - ClaimManager.INSTANCE = new ClaimManager(); - File claims = new File(gameDir.getPath() + "/" + string_1 + "/claims.dat"); - File claims_old = new File(gameDir.getPath() + "/" + string_1 + "/claims.dat_old"); - if (!claims.exists()) { - if (claims_old.exists()) {} - else return; - } - try { - if (!claims.exists() && claims_old.exists()) throw new FileNotFoundException(); - ClaimManager.INSTANCE.fromNBT(NbtIo.readCompressed(new FileInputStream(claims))); - } catch (IOException e) { - System.err.println("Could not load claims.dat:"); - e.printStackTrace(); - if (claims_old.exists()) { - System.out.println("Attempting to load backup claims..."); - try { - ClaimManager.INSTANCE.fromNBT(NbtIo.readCompressed(new FileInputStream(claims_old))); - } catch (IOException e2) { - throw new RuntimeException("Could not load claims.dat_old - Crashing server to save data. Remove or fix claims.dat or claims.dat_old to continue"); +public class MinecraftServerMixin { - } - } - } + @Inject(method = "createWorlds", at = @At(value = "RETURN")) + private void loadClaims(WorldGenerationProgressListener worldGenerationProgressListener, CallbackInfo ci){ + ClaimUtil.readWorldProperties(); } - @Shadow - private File gameDir; + } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/OwnedProjectile.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/OwnedProjectile.java index 1af8f84..02bb931 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/OwnedProjectile.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/OwnedProjectile.java @@ -1,12 +1,12 @@ package io.github.indicode.fabric.itsmine.mixin; -import net.minecraft.entity.projectile.Projectile; +import net.minecraft.entity.projectile.ProjectileEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import java.util.UUID; -@Mixin(Projectile.class) +@Mixin(ProjectileEntity.class) public interface OwnedProjectile { @Accessor("ownerUuid") UUID getOwner(); diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/PistonBlockMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/PistonBlockMixin.java index 1322ec6..a9909eb 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/PistonBlockMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/PistonBlockMixin.java @@ -1,12 +1,11 @@ package io.github.indicode.fabric.itsmine.mixin; -import io.github.indicode.fabric.itsmine.Claim; +import io.github.indicode.fabric.itsmine.claim.Claim; import io.github.indicode.fabric.itsmine.ClaimManager; -import net.minecraft.block.Block; +import io.github.indicode.fabric.itsmine.claim.ClaimFlags; import net.minecraft.block.BlockState; import net.minecraft.block.PistonBlock; import net.minecraft.block.piston.PistonHandler; -import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; @@ -16,7 +15,6 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.ArrayList; import java.util.List; /** @@ -29,17 +27,17 @@ public class PistonBlockMixin { private static void youCantMoveMe(BlockState blockState_1, World world, BlockPos newPos, Direction direction, boolean boolean_1, Direction direction_2, CallbackInfoReturnable ci) { boolean pushing = direction == direction_2; BlockPos oldPos = newPos.offset(direction_2.getOpposite()); - Claim oldClaim = ClaimManager.INSTANCE.getClaimAt(oldPos, world.getDimension().getType()); - Claim newClaim = ClaimManager.INSTANCE.getClaimAt(newPos, world.getDimension().getType()); + Claim oldClaim = ClaimManager.INSTANCE.getClaimAt(oldPos, world.getDimension()); + Claim newClaim = ClaimManager.INSTANCE.getClaimAt(newPos, world.getDimension()); if (oldClaim != newClaim) { if (oldClaim == null) { - if (!(Boolean) newClaim.settings.getSetting(Claim.ClaimSettings.Setting.PISTON_FROM_OUTSIDE)) ci.setReturnValue(false); + if (!newClaim.flags.getFlag(ClaimFlags.Flag.PISTON_FROM_OUTSIDE)) ci.setReturnValue(false); } else if (newClaim == null) { - if (!(Boolean) oldClaim.settings.getSetting(Claim.ClaimSettings.Setting.PISTON_FROM_INSIDE)) ci.setReturnValue(false); + if (!oldClaim.flags.getFlag(ClaimFlags.Flag.PISTON_FROM_INSIDE)) ci.setReturnValue(false); } else { - if (!(Boolean) oldClaim.settings.getSetting(Claim.ClaimSettings.Setting.PISTON_FROM_INSIDE) || - !(Boolean) newClaim.settings.getSetting(Claim.ClaimSettings.Setting.PISTON_FROM_OUTSIDE)) ci.setReturnValue(false); + if (!oldClaim.flags.getFlag(ClaimFlags.Flag.PISTON_FROM_INSIDE) || + !newClaim.flags.getFlag(ClaimFlags.Flag.PISTON_FROM_OUTSIDE)) ci.setReturnValue(false); } } } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/PlaceOnUseBlockMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/PlaceOnUseBlockMixin.java index 24e3fbf..4e94c69 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/PlaceOnUseBlockMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/PlaceOnUseBlockMixin.java @@ -1,10 +1,10 @@ package io.github.indicode.fabric.itsmine.mixin; -import io.github.indicode.fabric.itsmine.Claim; +import io.github.indicode.fabric.itsmine.claim.Claim; import io.github.indicode.fabric.itsmine.ClaimManager; -import io.github.indicode.fabric.itsmine.Functions; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.BucketItem; +import net.minecraft.item.Item; import net.minecraft.item.LilyPadItem; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; @@ -17,21 +17,22 @@ * @author Indigo Amann */ @Mixin({BucketItem.class, LilyPadItem.class}) -public class PlaceOnUseBlockMixin { +public class PlaceOnUseBlockMixin extends Item { + public PlaceOnUseBlockMixin(Settings settings) { + super(settings); + } + @Redirect(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;canPlayerModifyAt(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/math/BlockPos;)Z")) public boolean canActuallyModify(World world, PlayerEntity playerEntity_1, BlockPos blockPos_1) { if (!(world instanceof ServerWorld)) return world.canPlayerModifyAt(playerEntity_1, blockPos_1); - Claim claim = ClaimManager.INSTANCE.getClaimAt(blockPos_1, playerEntity_1.world.getDimension().getType()); - if (claim != null && claim.hasPermission(playerEntity_1.getGameProfile().getId(), Claim.Permission.PLACE_BREAK)) - return Functions.canPlayerActuallyModifyAt((ServerWorld) world, playerEntity_1, blockPos_1); - else { - if (Functions.canModifyAtClaimed(playerEntity_1, blockPos_1)) return true; - else { - if ((Object)this instanceof LilyPadItem){ - ((ServerWorld)world).getChunkManager().markForUpdate(blockPos_1); - } - return false; + Claim claim = ClaimManager.INSTANCE.getClaimAt(blockPos_1, playerEntity_1.world.getDimension()); + if (claim != null && !claim.hasPermission(playerEntity_1.getUuid(), Claim.Permission.BUILD)) { + if ((Object) this instanceof LilyPadItem){ + ((ServerWorld)world).getChunkManager().markForUpdate(blockPos_1); } + return false; } + + return world.canPlayerModifyAt(playerEntity_1, blockPos_1); } } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/PlayerEntityMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/PlayerEntityMixin.java index 16f02f0..5fd1736 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/PlayerEntityMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/PlayerEntityMixin.java @@ -1,46 +1,45 @@ package io.github.indicode.fabric.itsmine.mixin; -import io.github.indicode.fabric.itsmine.Claim; -import io.github.indicode.fabric.itsmine.ClaimManager; -import io.github.indicode.fabric.itsmine.ClaimShower; +import io.github.indicode.fabric.itsmine.*; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.util.EntityUtil; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.text.LiteralText; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Formatting; +import net.minecraft.screen.PlayerScreenHandler; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Final; 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; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; /** * @author Indigo Amann */ @Mixin(PlayerEntity.class) -public abstract class PlayerEntityMixin extends LivingEntity implements ClaimShower { +public abstract class PlayerEntityMixin extends LivingEntity implements ClaimShower, ClaimPlayerEntity { + protected PlayerEntityMixin(EntityType entityType_1, World world_1) { super(entityType_1, world_1); } + private int messageCooldown = 0; private Claim shownClaim = null; private BlockPos lastShowPos = null; + private String showmode = null; @Redirect(method = "interact", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;interact(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/Hand;)Z")) private boolean dontYouDareTouchMe(Entity entity, PlayerEntity playerEntity_1, Hand hand_1) { if (entity.world.isClient()) return entity.interact(playerEntity_1, hand_1); - Claim claim = ClaimManager.INSTANCE.getClaimAt(entity.getSenseCenterPos(), entity.world.getDimension().getType()); + Claim claim = ClaimManager.INSTANCE.getClaimAt(entity.getBlockPos(), entity.world.getDimension()); if (claim != null) { - if (!claim.hasPermission(playerEntity_1.getGameProfile().getId(), Claim.Permission.ENTITY_INTERACT)) { - playerEntity_1.sendMessage(new LiteralText("").append(new LiteralText("You are in a claim that does not allow you to interact with entities").formatted(Formatting.RED)).append(new LiteralText("(Use /claim show to see an outline)").formatted(Formatting.YELLOW))); + if (!claim.hasPermission(playerEntity_1.getGameProfile().getId(), Claim.Permission.INTERACT_ENTITY)) { + playerEntity_1.sendSystemMessage(Messages.MSG_INTERACT_ENTITY, playerEntity_1.getUuid()); return false; } } @@ -50,27 +49,45 @@ private boolean dontYouDareTouchMe(Entity entity, PlayerEntity playerEntity_1, H public void hittingIsRude(Entity entity, CallbackInfo ci) { if (entity.world.isClient()) return; PlayerEntity playerEntity_1 = (PlayerEntity)(Object)this; - Claim claim = ClaimManager.INSTANCE.getClaimAt(entity.getSenseCenterPos(), entity.world.getDimension().getType()); - if (claim != null) { - if (!claim.hasPermission(playerEntity_1.getGameProfile().getId(), Claim.Permission.ENTITY_DAMAGE)) { - playerEntity_1.sendMessage(new LiteralText("").append(new LiteralText("You are in a claim that does not allow you to hurt entities").formatted(Formatting.RED)).append(new LiteralText("(Use /claim show to see an outline)").formatted(Formatting.YELLOW))); - ci.cancel(); - } + Claim claim = ClaimManager.INSTANCE.getClaimAt(entity.getBlockPos(), entity.world.getDimension()); + + if (claim != null && !EntityUtil.canAttack(((PlayerEntity) (Object) this).getUuid(), claim, entity)) { + playerEntity_1.sendSystemMessage(Messages.MSG_DAMAGE_ENTITY, playerEntity_1.getUuid()); + ci.cancel(); + } + } + + @Override + public void setMessageCooldown(){ + messageCooldown = ItsMineConfig.main().message().messageCooldown; + } + + @Override + public void setMessageCooldown(int cooldown){ + messageCooldown = cooldown; + } + + @Override + public void tickMessageCooldown(){ + if(messageCooldown > 0){ + messageCooldown--; } } + @Override + public int getMessageCooldown(){ + return messageCooldown; + } + + @Override + public boolean shouldMessage(){ + return messageCooldown == 0; + } + @Override public void setLastShowPos(BlockPos pos) { lastShowPos = pos; } - - /*@Inject(method = "canPlaceOn", at = @At("HEAD")) - public void iDontWantYerStuff(BlockPos blockPos_1, Direction direction_1, ItemStack itemStack_1, CallbackInfoReturnable cir) { - Claim claim = ClaimManager.INSTANCE.getClaimAt(blockPos_1, world.getDimension().getType()); - if (claim != null) { - cir.setReturnValue(false); - } - }*/ // Replace with specific undos on certain methods(buttons, containers, etc) @Override public void setShownClaim(Claim claim) { shownClaim = claim; @@ -79,9 +96,13 @@ public void setShownClaim(Claim claim) { public Claim getShownClaim() { return shownClaim; } - @Override public BlockPos getLastShowPos() { return lastShowPos; } + @Override + public void setShowMode(String mode){showmode = mode;} + @Override + public String getMode(){return showmode;} + } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/ProjectileEntityMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/ProjectileEntityMixin.java index ca499a6..8ae63f0 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/ProjectileEntityMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/ProjectileEntityMixin.java @@ -1,21 +1,16 @@ package io.github.indicode.fabric.itsmine.mixin; -import io.github.indicode.fabric.itsmine.Claim; +import io.github.indicode.fabric.itsmine.claim.Claim; import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.Messages; import net.minecraft.entity.Entity; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.projectile.Projectile; import net.minecraft.entity.projectile.ProjectileEntity; -import net.minecraft.text.LiteralText; -import net.minecraft.util.Formatting; 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.Redirect; -import java.util.UUID; - /** * @author Indigo Amann */ @@ -28,10 +23,10 @@ public boolean imInvincible(Entity entity, DamageSource damageSource_1, float fl if (((ProjectileEntity)(Object)this).getServer().getPlayerManager().getPlayer(((OwnedProjectile)projectile).getOwner()) != null) { PlayerEntity playerEntity_1 = ((ProjectileEntity)(Object)this).getServer().getPlayerManager().getPlayer(((OwnedProjectile)projectile).getOwner()); - Claim claim = ClaimManager.INSTANCE.getClaimAt(entity.getSenseCenterPos(), entity.world.getDimension().getType()); + Claim claim = ClaimManager.INSTANCE.getClaimAt(entity.getBlockPos(), entity.world.getDimension()); if (claim != null && entity != playerEntity_1) { - if (!claim.hasPermission(playerEntity_1.getGameProfile().getId(), Claim.Permission.ENTITY_DAMAGE)) { - playerEntity_1.sendMessage(new LiteralText("").append(new LiteralText("You are in a claim that does not allow you to hurt entities").formatted(Formatting.RED)).append(new LiteralText("(Use /claim show to see an outline)").formatted(Formatting.YELLOW))); + if (!claim.hasPermission(playerEntity_1.getGameProfile().getId(), Claim.Permission.DAMAGE_ENTITY)) { + playerEntity_1.sendSystemMessage(Messages.MSG_DAMAGE_ENTITY, playerEntity_1.getUuid()); projectile.kill(); // You do not want an arrow bouncing between two armor stands return false; } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/ServerCommandOutputMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/ServerCommandOutputMixin.java new file mode 100644 index 0000000..f7be583 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/ServerCommandOutputMixin.java @@ -0,0 +1,21 @@ +package io.github.indicode.fabric.itsmine.mixin; + +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.util.ClaimUtil; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.ServerCommandOutput; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ServerCommandOutput.class) +public abstract class ServerCommandOutputMixin { + + @Inject(method = "", at = @At("RETURN")) + private void saveInstance(MinecraftServer server, CallbackInfo ci) { + System.out.println("ServerCommandOutput"); + ClaimManager.INSTANCE = new ClaimManager(); + ClaimManager.INSTANCE.server = server; + } +} \ No newline at end of file diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/ServerPlayNetworkHandlerMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/ServerPlayNetworkHandlerMixin.java index aa0bba1..164707b 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/ServerPlayNetworkHandlerMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/ServerPlayNetworkHandlerMixin.java @@ -1,20 +1,16 @@ package io.github.indicode.fabric.itsmine.mixin; -import io.github.indicode.fabric.itsmine.Claim; +import io.github.indicode.fabric.itsmine.claim.Claim; import io.github.indicode.fabric.itsmine.ClaimManager; -import io.github.indicode.fabric.itsmine.Functions; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.network.ServerPlayNetworkHandler; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.ActionResult; -import net.minecraft.util.Formatting; import net.minecraft.util.Hand; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; 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.Redirect; @@ -23,20 +19,22 @@ */ @Mixin(ServerPlayNetworkHandler.class) public class ServerPlayNetworkHandlerMixin { + @Shadow public ServerPlayerEntity player; + @Redirect(method = "onPlayerInteractEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;interactAt(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/math/Vec3d;Lnet/minecraft/util/Hand;)Lnet/minecraft/util/ActionResult;")) public ActionResult iSaidDontTouchMe(Entity entity, PlayerEntity playerEntity_1, Vec3d vec3d_1, Hand hand_1) { - Claim claim = ClaimManager.INSTANCE.getClaimAt(entity.getSenseCenterPos(), entity.world.getDimension().getType()); + Claim claim = ClaimManager.INSTANCE.getClaimAt(entity.getBlockPos(), entity.world.getDimension()); if (claim != null) { - if (!claim.hasPermission(playerEntity_1.getGameProfile().getId(), Claim.Permission.ENTITY_INTERACT)) { - playerEntity_1.sendMessage(new LiteralText("").append(new LiteralText("You are in a claim that does not allow you to interact with entities").formatted(Formatting.RED)).append(new LiteralText("(Use /claim show to see an outline)").formatted(Formatting.YELLOW))); + if (!claim.hasPermission(playerEntity_1.getGameProfile().getId(), Claim.Permission.INTERACT_ENTITY)) { +// playerEntity_1.sendSystemMessage(Messages.MSG_INTERACT_ENTITY); return ActionResult.FAIL; } } return entity.interactAt(playerEntity_1, vec3d_1, hand_1); } - - @Redirect(method = "onPlayerInteractBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;canPlayerModifyAt(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/math/BlockPos;)Z")) - private boolean canITouchie(ServerWorld world, PlayerEntity playerEntity_1, BlockPos blockPos_1) { - return Functions.canPlayerActuallyModifyAt(world, playerEntity_1, blockPos_1); - } +// +// @Redirect(method = "onPlayerInteractBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;canPlayerModifyAt(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/math/BlockPos;)Z")) +// private boolean canITouchie(ServerWorld world, PlayerEntity playerEntity_1, BlockPos blockPos_1) { +// return Functions.canPlayerActuallyModifyAt(world, playerEntity_1, blockPos_1); +// } } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/ServerPlayerInteractionManagerMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/ServerPlayerInteractionManagerMixin.java index 188b5fc..86b6089 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/ServerPlayerInteractionManagerMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/ServerPlayerInteractionManagerMixin.java @@ -1,20 +1,14 @@ package io.github.indicode.fabric.itsmine.mixin; -import io.github.indicode.fabric.itsmine.Claim; -import io.github.indicode.fabric.itsmine.ClaimManager; -import io.github.indicode.fabric.itsmine.Config; -import io.github.indicode.fabric.itsmine.Functions; -import net.minecraft.block.AbstractButtonBlock; -import net.minecraft.block.BlockState; -import net.minecraft.block.DoorBlock; -import net.minecraft.block.LeverBlock; -import net.minecraft.block.enums.DoubleBlockHalf; +import io.github.indicode.fabric.itsmine.*; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.util.BlockUtil; +import io.github.indicode.fabric.itsmine.util.MessageUtil; +import net.minecraft.block.*; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.BlockItem; -import net.minecraft.item.BucketItem; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerInteractionManager; import net.minecraft.server.world.ServerWorld; @@ -27,63 +21,76 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; 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; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.UUID; + /** * @author Indigo Amann */ @Mixin(ServerPlayerInteractionManager.class) -public class ServerPlayerInteractionManagerMixin { +public abstract class ServerPlayerInteractionManagerMixin { + @Shadow public ServerPlayerEntity player; + + @Shadow public ServerWorld world; + + public BlockPos blockPos; + + @Shadow private boolean mining; + + @Inject(method = "interactBlock", at = @At(value = "HEAD")) + private void getBlock(ServerPlayerEntity serverPlayerEntity, World world, ItemStack stack, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable cir){ + blockPos = hitResult.getBlockPos(); + } + @Redirect(method = "interactBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;onUse(Lnet/minecraft/world/World;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/Hand;Lnet/minecraft/util/hit/BlockHitResult;)Lnet/minecraft/util/ActionResult;")) - public ActionResult activateIfPossible(BlockState state, World world, PlayerEntity playerEntity_1, Hand hand_1, BlockHitResult blockHitResult_1) { - BlockPos pos = blockHitResult_1.getBlockPos(); - Claim claim = ClaimManager.INSTANCE.getClaimAt(pos, world.getDimension().getType()); +// private ActionResult interactIfPossible(BlockState blockState, World world, PlayerEntity player, Hand hand, BlockHitResult hit, PlayerEntity player1, World world1, ItemStack itemStack, Hand hand1, BlockHitResult hitResult1) { + private ActionResult interactIfPossible(BlockState blockState, World world, PlayerEntity player, Hand hand, BlockHitResult hit){ + BlockPos pos = hit.getBlockPos(); + ItemStack itemStack = player.getMainHandStack(); + Claim claim = ClaimManager.INSTANCE.getClaimAt(pos, player.world.getDimension()); if (claim != null) { - UUID uuid = playerEntity_1.getGameProfile().getId(); - if ( - claim.hasPermission(uuid, Claim.Permission.ACTIVATE_BLOCKS) || - (state.getBlock() instanceof AbstractButtonBlock && claim.hasPermission(uuid, Claim.Permission.PRESS_BUTTONS)) || - (state.getBlock() instanceof LeverBlock && claim.hasPermission(uuid, Claim.Permission.USE_LEVERS)) || - (state.getBlock() instanceof DoorBlock && claim.hasPermission(uuid, Claim.Permission.OPEN_DOORS)) - ) return state.onUse(world, playerEntity_1, hand_1, blockHitResult_1); - else { - if (state.getBlock() instanceof DoorBlock && playerEntity_1 instanceof ServerPlayerEntity) { - DoubleBlockHalf half = state.get(DoorBlock.HALF); - ((ServerPlayerEntity) playerEntity_1).networkHandler.sendPacket(new BlockUpdateS2CPacket(world, half == DoubleBlockHalf.LOWER ? pos.up() : pos.down(1))); + if (!Functions.canInteractWith(claim, blockState.getBlock(), player.getUuid())) { + if (!itemStack.isEmpty() && !(itemStack.getItem() instanceof BlockItem)) { + player.sendSystemMessage(Messages.MSG_INTERACT_BLOCK, player.getUuid()); + } else if (BlockUtil.isContainer(blockState.getBlock())) { + player.sendSystemMessage(Messages.MSG_OPEN_CONTAINER, player.getUuid()); } - //playerEntity_1.sendMessage(new LiteralText("").append(new LiteralText("You are in a claim that does not allow you to use that").formatted(Formatting.RED)).append(new LiteralText("(Use /claim show to see an outline)").formatted(Formatting.YELLOW))); + return ActionResult.FAIL; } +// else { +// if (blockState.getBlock() instanceof DoorBlock && player instanceof ServerPlayerEntity) { +// DoubleBlockHalf blockHalf = blockState.get(DoorBlock.HALF); +// ((ServerPlayerEntity) player).networkHandler.sendPacket(new BlockUpdateS2CPacket(world, blockHalf == DoubleBlockHalf.LOWER ? pos.up() : pos.down(1))); +// } +// } } - return state.onUse(world, playerEntity_1, hand_1, blockHitResult_1); + + return blockState.onUse(world, player, hand, hit); } @Redirect(method = "interactBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;isEmpty()Z", ordinal = 2)) - public boolean allowItemUse(ItemStack stack, PlayerEntity playerEntity_1, World world_1, ItemStack itemStack_1, Hand hand_1, BlockHitResult blockHitResult_1) { - BlockPos pos = blockHitResult_1.getBlockPos().offset(blockHitResult_1.getSide()); - Claim claim = ClaimManager.INSTANCE.getClaimAt(pos, playerEntity_1.world.getDimension().getType()); + private boolean interactWithItemIfPossible(ItemStack stack) { +// BlockPos pos = hitResult.getBlockPos().offset(hitResult.getSide()); +// System.out.println(blockPos.getX() + " " + blockPos.getY() + " " + blockPos.getZ()); + Claim claim = ClaimManager.INSTANCE.getClaimAt(blockPos, world.getDimension()); if (claim != null && !stack.isEmpty()) { - UUID uuid = playerEntity_1.getGameProfile().getId(); - if ( - claim.hasPermission(uuid, Claim.Permission.USE_ITEMS_ON_BLOCKS) || - (stack.getItem() instanceof BlockItem && claim.hasPermission(uuid, Claim.Permission.PLACE_BREAK)) || - (stack.getItem() instanceof BucketItem && claim.hasPermission(uuid, Claim.Permission.PLACE_BREAK)) - ) return false; - if (stack.getItem() instanceof BlockItem) { - playerEntity_1.sendMessage(new LiteralText("").append(new LiteralText("You cannot place blocks in this claim").formatted(Formatting.RED)).append(new LiteralText("(Use /claim show to see an outline)").formatted(Formatting.YELLOW))); + if (Functions.canInteractUsingItem(claim, stack.getItem(), player.getUuid())) { + return false; } - if (stack.getItem() instanceof BucketItem) { - if (!Functions.isBucketEmpty((BucketItem) stack.getItem())) { - playerEntity_1.sendMessage(new LiteralText("").append(new LiteralText("You cannot pick up fluids in this claim").formatted(Formatting.RED)).append(new LiteralText("(Use /claim show to see an outline)").formatted(Formatting.YELLOW))); - } else { - playerEntity_1.sendMessage(new LiteralText("").append(new LiteralText("You cannot place fluids in this claim").formatted(Formatting.RED)).append(new LiteralText("(Use /claim show to see an outline)").formatted(Formatting.YELLOW))); - } + if (stack.getItem() instanceof BlockItem) { + player.sendSystemMessage(Messages.MSG_PLACE_BLOCK, player.getUuid()); } + return true; } + return stack.isEmpty(); } @@ -95,25 +102,27 @@ public boolean canBreak(ServerWorld world, PlayerEntity player, BlockPos pos) { if (posPair != null) { posPair = new Pair<>(posPair.getLeft(), pos); ClaimManager.INSTANCE.stickPositions.put(player, posPair); - player.sendMessage(new LiteralText("Position #2 set: " + pos.getX() + (Config.claims2d ? "" : " " + pos.getY()) + " " + pos.getZ()).formatted(Formatting.GREEN)); + player.sendSystemMessage(new LiteralText("Position #2 set: " + pos.getX() + (ItsMineConfig.main().claims2d ? "" : " " + pos.getY()) + " " + pos.getZ()).formatted(Formatting.GREEN), player.getUuid()); if (posPair.getLeft() != null) { - player.sendMessage(new LiteralText("Area Selected. Type /claim create to create your claim!").formatted(Formatting.GOLD)); - if (!Config.claims2d) - player.sendMessage(new LiteralText("Remember that claims are three dimensional. Don't forget to expand up/down or select a big enough area...").formatted(Formatting.LIGHT_PURPLE, Formatting.ITALIC)); + player.sendSystemMessage(new LiteralText("Area Selected. Type /claim create to create your claim!").formatted(Formatting.GOLD), player.getUuid()); + if (!ItsMineConfig.main().claims2d) + player.sendSystemMessage(new LiteralText("Remember that claims are three dimensional. Don't forget to expand up/down or select a big enough area...").formatted(Formatting.LIGHT_PURPLE).formatted(Formatting.ITALIC), player.getUuid()); } return false; } } } - Claim claim = ClaimManager.INSTANCE.getClaimAt(pos, player.world.getDimension().getType()); + Claim claim = ClaimManager.INSTANCE.getClaimAt(pos, player.world.getDimension()); if (claim != null) { UUID uuid = player.getGameProfile().getId(); - if ( - claim.hasPermission(uuid, Claim.Permission.PLACE_BREAK) - ) return Functions.canPlayerActuallyModifyAt(world, player, pos); - player.sendMessage(new LiteralText("").append(new LiteralText("You cannot break blocks in this claim").formatted(Formatting.RED)).append(new LiteralText("(Use /claim show to see an outline)").formatted(Formatting.YELLOW))); - return false; + if (!claim.hasPermission(uuid, Claim.Permission.BUILD)) { +// MessageUtil.sendText(ItsMineConfig.main().message().breakBlock); + player.sendSystemMessage(Messages.MSG_BREAK_BLOCK, player.getUuid()); + return false; + } + } + return world.canPlayerModifyAt(player, pos); } } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/ServerWorldMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/ServerWorldMixin.java index ebad451..4ed0d03 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/ServerWorldMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/ServerWorldMixin.java @@ -1,41 +1,91 @@ package io.github.indicode.fabric.itsmine.mixin; -import io.github.indicode.fabric.itsmine.Claim; import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.ClaimPlayerEntity; import io.github.indicode.fabric.itsmine.Functions; +import io.github.indicode.fabric.itsmine.MonitorableWorld; +import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.Packet; import net.minecraft.server.PlayerManager; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.text.LiteralText; import net.minecraft.util.Formatting; -import net.minecraft.util.math.BlockPos; +import net.minecraft.util.profiler.Profiler; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.MutableWorldProperties; +import net.minecraft.world.World; import net.minecraft.world.dimension.DimensionType; +import org.spongepowered.asm.mixin.Final; 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; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.BooleanSupplier; +import java.util.function.Supplier; /** * @author Indigo Amann */ @Mixin(ServerWorld.class) -public abstract class ServerWorldMixin { - @Inject(method = "canPlayerModifyAt", at = @At("HEAD"), cancellable = true) - private void canMine(PlayerEntity player, BlockPos blockPos_1, CallbackInfoReturnable ci) { - if (player.world.isClient()) return; - Claim claim = ClaimManager.INSTANCE.getClaimAt(blockPos_1, player.getEntityWorld().getDimension().getType()); - if (claim != null) { - if (!claim.hasPermission(player.getGameProfile().getId(), Claim.Permission.SPAWN_PROTECT)) { - player.sendMessage(new LiteralText("").append(new LiteralText("You can't use that here. This claim is spawn-protected").formatted(Formatting.RED)).append(new LiteralText("(Use /claim show to see an outline)").formatted(Formatting.YELLOW))); - ci.setReturnValue(false); - } - } +public abstract class ServerWorldMixin extends World implements MonitorableWorld { + @Shadow + @Final + private Map entitiesByUuid; + + protected ServerWorldMixin(MutableWorldProperties mutableWorldProperties, DimensionType dimensionType, Supplier supplier, boolean bl, boolean bl2, long l) { + super(mutableWorldProperties, dimensionType, supplier, bl, bl2, l); } - @Redirect(method = "sendBlockActions", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;sendToAround(Lnet/minecraft/entity/player/PlayerEntity;DDDDLnet/minecraft/world/dimension/DimensionType;Lnet/minecraft/network/Packet;)V")) - private void sendPistonUpdate(PlayerManager manager, PlayerEntity playerEntity_1, double double_1, double double_2, double double_3, double double_4, DimensionType dimensionType_1, Packet packet_1) { - manager.sendToAround(playerEntity_1, double_1, double_2, double_3, double_4, dimensionType_1, packet_1); + + + @Shadow public abstract List getPlayers(); + + @Redirect(method = "processSyncedBlockEvents", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;sendToAround(Lnet/minecraft/entity/player/PlayerEntity;DDDDLnet/minecraft/util/registry/RegistryKey;Lnet/minecraft/network/Packet;)V")) + private void sendPistonUpdate(PlayerManager manager, PlayerEntity playerEntity_1, double double_1, double double_2, double double_3, double double_4, RegistryKey dimensionType_1, Packet packet_1) { + manager.sendToAround(playerEntity_1, double_1, double_2, double_3, double_4, this.method_27983(), packet_1); Functions.doPistonUpdate((ServerWorld) (Object)this, packet_1); } + + + + @Inject(method = "tick", at = @At(value = "RETURN")) + public void tickActions(BooleanSupplier shouldKeepTicking, CallbackInfo ci){ + ClaimManager.INSTANCE.claimsByName.forEach((s, claim) ->{ + if(claim.rent.getRentedUntil() != 0){ + if(claim.rent.getRentTimeLeft() < 0){ + System.out.println("Rent expired -> method call"); + this.getPlayers().forEach(serverPlayerEntity -> { + if(serverPlayerEntity.getUuid() == claim.rent.getTenant()){ + serverPlayerEntity.sendSystemMessage(new LiteralText("Rent expired").formatted(Formatting.RED), serverPlayerEntity.getUuid()); + claim.endRent(); + } + }); + } + } + }); + this.getPlayers().forEach(playerEntity -> { + ((ClaimPlayerEntity) playerEntity).tickMessageCooldown(); + }); + + } + + + @Override + public int loadedEntities() { + if (this.entitiesByUuid == null) + return -1; + return this.entitiesByUuid.size(); + } + + @Override + public Map EntityList() { + return entitiesByUuid; + } } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/SpawnRestrictionMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/SpawnRestrictionMixin.java index 74601b8..937804d 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/SpawnRestrictionMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/SpawnRestrictionMixin.java @@ -1,12 +1,13 @@ package io.github.indicode.fabric.itsmine.mixin; -import io.github.indicode.fabric.itsmine.Claim; +import io.github.indicode.fabric.itsmine.claim.Claim; import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.claim.ClaimFlags; import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnReason; import net.minecraft.entity.SpawnRestriction; -import net.minecraft.entity.SpawnType; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IWorld; +import net.minecraft.world.WorldAccess; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -17,13 +18,13 @@ @Mixin(SpawnRestriction.class) public class SpawnRestrictionMixin { @Inject(method = "canSpawn", at = @At("HEAD"), cancellable = true) - private static void canSpawnInClaim(EntityType type, IWorld world, SpawnType spawnType, BlockPos pos, Random random, CallbackInfoReturnable cir) { + private static void canSpawnInClaim(EntityType type, WorldAccess world, SpawnReason spawnReason, BlockPos pos, Random random, CallbackInfoReturnable cir) { if (ClaimManager.INSTANCE == null) { cir.setReturnValue(false); return; } - Claim claim = ClaimManager.INSTANCE.getClaimAt(pos, world.getDimension().getType()); - if (claim != null && !claim.settings.getSetting(Claim.ClaimSettings.Setting.MOB_SPAWNING)) { + Claim claim = ClaimManager.INSTANCE.getClaimAt(pos, world.getDimension()); + if (claim != null && !claim.flags.getFlag(ClaimFlags.Flag.MOB_SPAWNING)) { cir.setReturnValue(false); } } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/StickClaimItemMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/StickClaimItemMixin.java index 18d7b11..3c3ccb5 100644 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/StickClaimItemMixin.java +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/StickClaimItemMixin.java @@ -1,18 +1,17 @@ package io.github.indicode.fabric.itsmine.mixin; import io.github.indicode.fabric.itsmine.ClaimManager; -import io.github.indicode.fabric.itsmine.Config; -import net.minecraft.block.BlockState; +import io.github.indicode.fabric.itsmine.ItsMineConfig; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemUsageContext; import net.minecraft.item.Items; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.LiteralText; import net.minecraft.util.ActionResult; import net.minecraft.util.Formatting; import net.minecraft.util.Pair; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -21,18 +20,20 @@ @Mixin(Item.class) public class StickClaimItemMixin { @Inject(method = "useOnBlock", at = @At("HEAD"), cancellable = true) +// private void setStickPositionFirst(ItemUsageContext context, CallbackInfoReturnable cir) { private void setStickPositionFirst(ItemUsageContext context, CallbackInfoReturnable cir) { + PlayerEntity player = context.getPlayer(); if (context.getWorld().isClient) return; - if (!context.getPlayer().isSneaking()) { + if (!player.isSneaking()) { if ((Object)this == Items.STICK) { Pair posPair = ClaimManager.INSTANCE.stickPositions.get(context.getPlayer()); if (posPair == null) return; else posPair = new Pair<>(context.getBlockPos(), posPair.getRight()); ClaimManager.INSTANCE.stickPositions.put(context.getPlayer(), posPair); - context.getPlayer().sendMessage(new LiteralText("Position #1 set: " + context.getBlockPos().getX() + (Config.claims2d ? "" : " " + context.getBlockPos().getY()) + " " + context.getBlockPos().getZ()).formatted(Formatting.GREEN)); + context.getPlayer().sendSystemMessage(new LiteralText("Position #1 set: " + context.getBlockPos().getX() + (ItsMineConfig.main().claims2d ? "" : " " + context.getBlockPos().getY()) + " " + context.getBlockPos().getZ()).formatted(Formatting.GREEN), player.getUuid()); if (posPair.getRight() != null) { - context.getPlayer().sendMessage(new LiteralText("Area Selected. Type /claim create to create your claim!").formatted(Formatting.GOLD)); - if (!Config.claims2d) context.getPlayer().sendMessage(new LiteralText("Remember that claims are three dimensional. Don't forget to expand up/down or select a big enough area...").formatted(Formatting.LIGHT_PURPLE, Formatting.ITALIC)); + player.sendSystemMessage(new LiteralText("Area Selected. Type /claim create to create your claim!").formatted(Formatting.GOLD), player.getUuid()); + if (!ItsMineConfig.main().claims2d) player.sendSystemMessage(new LiteralText("Remember that claims are three dimensional. Don't forget to expand up/down or select a big enough area...").formatted(Formatting.LIGHT_PURPLE).formatted(Formatting.ITALIC), player.getUuid()); } cir.setReturnValue(ActionResult.SUCCESS); } diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/WorldSaveHandlerMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/WorldSaveHandlerMixin.java deleted file mode 100644 index 16bcdfd..0000000 --- a/src/main/java/io/github/indicode/fabric/itsmine/mixin/WorldSaveHandlerMixin.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.github.indicode.fabric.itsmine.mixin; - -import io.github.indicode.fabric.itsmine.ClaimManager; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtIo; -import net.minecraft.world.WorldSaveHandler; -import net.minecraft.world.level.LevelProperties; -import org.spongepowered.asm.mixin.Final; -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.callback.CallbackInfo; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; - -/** - * @author Indigo Amann - */ -@Mixin(WorldSaveHandler.class) -public class WorldSaveHandlerMixin { - @Inject(method = "saveWorld(Lnet/minecraft/world/level/LevelProperties;Lnet/minecraft/nbt/CompoundTag;)V", at = @At("RETURN")) - private void onSaveWorld(LevelProperties levelProperties_1, CompoundTag compoundTag_1, CallbackInfo ci) { - if (ClaimManager.INSTANCE != null) { - File claimDataFile = new File(worldDir, "claims.dat"); - if (claimDataFile.exists()) { - File old = new File(worldDir, "claims.dat_old"); - if (old.exists()) old.delete(); - claimDataFile.renameTo(old); - claimDataFile.delete(); - } - try { - claimDataFile.createNewFile(); - CompoundTag tag = ClaimManager.INSTANCE.toNBT(); - NbtIo.writeCompressed(tag, new FileOutputStream(claimDataFile)); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - @Shadow - private File worldDir; -} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/OwnedProjectile.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/OwnedProjectile.java new file mode 100644 index 0000000..b987b68 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/OwnedProjectile.java @@ -0,0 +1,13 @@ +package io.github.indicode.fabric.itsmine.mixin.projectile; + +import net.minecraft.entity.projectile.ProjectileEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.UUID; + +@Mixin(ProjectileEntity.class) +public interface OwnedProjectile { + @Accessor("ownerUuid") + UUID getOwner(); +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/ProjectileEntityMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/ProjectileEntityMixin.java new file mode 100644 index 0000000..e6f9c15 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/ProjectileEntityMixin.java @@ -0,0 +1,58 @@ +package io.github.indicode.fabric.itsmine.mixin.projectile; + +import blue.endless.jankson.annotation.Nullable; +import io.github.indicode.fabric.itsmine.Functions; +import io.github.indicode.fabric.itsmine.Messages; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.projectile.ArrowEntity; +import net.minecraft.entity.projectile.ProjectileEntity; +import net.minecraft.util.hit.EntityHitResult; +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.Redirect; + +/** + * @author Indigo Amann + */ +@Mixin(ProjectileEntity.class) +public abstract class ProjectileEntityMixin { + @Shadow protected abstract void onEntityHit(EntityHitResult entityHitResult); + + @Shadow @Nullable + public abstract Entity getOwner(); + + @Redirect(method = "onCollision", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/projectile/ProjectileEntity;onEntityHit(Lnet/minecraft/util/hit/EntityHitResult;)V")) + private void imInvincible(ProjectileEntity projectileEntity, EntityHitResult entityHitResult) { + if (Functions.canDamageWithProjectile((ProjectileEntity) (Object) this, projectileEntity)) { + this.onEntityHit(entityHitResult); + } else { + if (this.getOwner() instanceof PlayerEntity) { + this.getOwner().sendSystemMessage(Messages.MSG_DAMAGE_ENTITY, this.getOwner().getUuid()); + if(projectileEntity.getType() == EntityType.ARROW){ + projectileEntity.kill(); + } + } + } + } + +// public boolean imInvincible(Entity entity, DamageSource damageSource_1, float float_1) { +// if (entity.world.isClient()) return entity.damage(damageSource_1, float_1); +// ProjectileEntity projectile = (ProjectileEntity)(Object)this; +// +// if (((ProjectileEntity)(Object)this).getServer().getPlayerManager().getPlayer(((OwnedProjectile)projectile).getOwner()) != null) { +// PlayerEntity playerEntity_1 = ((ProjectileEntity)(Object)this).getServer().getPlayerManager().getPlayer(((OwnedProjectile)projectile).getOwner()); +// Claim claim = ClaimManager.INSTANCE.getClaimAt(entity.getSenseCenterPos(), entity.world.getDimension()); +// if (claim != null && entity != playerEntity_1) { +// if (!claim.hasPermission(playerEntity_1.getGameProfile().getId(), Claim.Permission.DAMAGE_ENTITY)) { +// playerEntity_1.sendSystemMessage(Messages.MSG_DAMAGE_ENTITY); +// projectile.kill(); // You do not want an arrow bouncing between two armor stands +// return false; +// } +// } +// } +// return entity.damage(damageSource_1, float_1); +// } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/SnowballEntityMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/SnowballEntityMixin.java new file mode 100644 index 0000000..a7669ab --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/SnowballEntityMixin.java @@ -0,0 +1,23 @@ +package io.github.indicode.fabric.itsmine.mixin.projectile; + +import io.github.indicode.fabric.itsmine.Functions; +import net.minecraft.entity.Entity; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.projectile.thrown.SnowballEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(SnowballEntity.class) +public abstract class SnowballEntityMixin { + + @Redirect(method = "onEntityHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;damage(Lnet/minecraft/entity/damage/DamageSource;F)Z")) + private boolean imInvincible(Entity entity, DamageSource source, float amount) { + if (Functions.canDamageWithProjectile((SnowballEntity) (Object) this, entity)) { + return entity.damage(source, amount); + } + + return false; + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/ThrownEggEntityMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/ThrownEggEntityMixin.java new file mode 100644 index 0000000..13351b8 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/ThrownEggEntityMixin.java @@ -0,0 +1,23 @@ +package io.github.indicode.fabric.itsmine.mixin.projectile; + +import io.github.indicode.fabric.itsmine.Functions; +import net.minecraft.entity.Entity; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.projectile.thrown.EggEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(EggEntity.class) +public abstract class ThrownEggEntityMixin { + + @Redirect(method = "onEntityHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;damage(Lnet/minecraft/entity/damage/DamageSource;F)Z")) + private boolean imInvincible(Entity entity, DamageSource source, float amount) { + if (Functions.canDamageWithProjectile((EggEntity) (Object) this, entity)) { + return entity.damage(source, amount); + } + + return false; + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/ThrownEnderpearlEntityMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/ThrownEnderpearlEntityMixin.java new file mode 100644 index 0000000..2718f52 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/ThrownEnderpearlEntityMixin.java @@ -0,0 +1,23 @@ +package io.github.indicode.fabric.itsmine.mixin.projectile; + +import io.github.indicode.fabric.itsmine.Functions; +import net.minecraft.entity.Entity; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.projectile.thrown.EnderPearlEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(EnderPearlEntity.class) +public abstract class ThrownEnderpearlEntityMixin { + + @Redirect(method = "onEntityHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;damage(Lnet/minecraft/entity/damage/DamageSource;F)Z")) + private boolean imInvincible(Entity entity, DamageSource source, float amount) { + if (Functions.canDamageWithProjectile((EnderPearlEntity) (Object) this, entity)) { + return entity.damage(source, amount); + } + + return false; + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/TridentEntityMixin.java b/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/TridentEntityMixin.java new file mode 100644 index 0000000..7cd7cd8 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/mixin/projectile/TridentEntityMixin.java @@ -0,0 +1,24 @@ +package io.github.indicode.fabric.itsmine.mixin.projectile; + +import io.github.indicode.fabric.itsmine.Functions; +import net.minecraft.entity.Entity; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.projectile.ProjectileEntity; +import net.minecraft.entity.projectile.TridentEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(TridentEntity.class) +public abstract class TridentEntityMixin { + + @Redirect(method = "onEntityHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;damage(Lnet/minecraft/entity/damage/DamageSource;F)Z")) + private boolean imInvincible(Entity entity, DamageSource source, float amount) { + if (Functions.canDamageWithProjectile((ProjectileEntity) (Object) this, entity)) { + return entity.damage(source, amount); + } + + return false; + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/util/ArgumentUtil.java b/src/main/java/io/github/indicode/fabric/itsmine/util/ArgumentUtil.java new file mode 100644 index 0000000..60b632d --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/util/ArgumentUtil.java @@ -0,0 +1,204 @@ +package io.github.indicode.fabric.itsmine.util; + +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.SuggestionProvider; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import io.github.indicode.fabric.itsmine.ClaimManager; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.ItsMineConfig; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.claim.ClaimFlags; +import net.minecraft.server.command.CommandSource; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.math.Direction; +import net.minecraft.util.registry.Registry; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import static com.mojang.brigadier.arguments.StringArgumentType.*; +import static net.minecraft.server.command.CommandManager.argument; + +public class ArgumentUtil { + + + public static RequiredArgumentBuilder getSubAndClaims() { + return argument("claim", word()).suggests(ArgumentUtil::claimSubzoneProvider); + } + + public static RequiredArgumentBuilder getClaims() { + return argument("claim", word()).suggests(ArgumentUtil::claimProvider); + } + + public static RequiredArgumentBuilder getSubzones() { + return argument("claim", word()).suggests(ArgumentUtil::subzoneProvider); + } + + public static RequiredArgumentBuilder getDirections() { + return argument("direction", word()).suggests(DIRECTION_PROVIDER); + } + + public static RequiredArgumentBuilder getHelpId() { + return argument("id", word()).suggests(HELPID_PROVIDER); + } + + public static RequiredArgumentBuilder getPlayers(){ + return argument("player", word()).suggests(PLAYERS_PROVIDER); + } + + public static RequiredArgumentBuilder getFlags(){ + return argument("flag", word()).suggests(SETTINGS_PROVIDER); + } + public static RequiredArgumentBuilder getPermissions(){ + return argument("permission", word()).suggests(PERMISSIONS_PROVIDER); + } + + public static RequiredArgumentBuilder getMessageEvent(){ + return argument("messageEvent", word()).suggests(MESSAGE_EVENTS_PROVIDER); + } + + public static RequiredArgumentBuilder getEventMessage(){ + return argument("message", greedyString()).suggests(EVENT_MESSAGE_PROVIDER); + } + + public static RequiredArgumentBuilder getShowMode(){ + return argument("mode", greedyString()).suggests(SHOW_MODE_PROVIDER); + } + + + + private static CompletableFuture claimSubzoneProvider(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { + ServerPlayerEntity player = context.getSource().getPlayer(); + List names = new ArrayList<>(); + Claim current = ClaimManager.INSTANCE.getClaimAt(player.getBlockPos(), player.world.getDimension()); + if (current != null) names.add(current.name); + for (Claim claim : ClaimManager.INSTANCE.getPlayerClaims(player.getGameProfile().getId())) { + if (claim != null) { + names.add(claim.name); + } + } + return CommandSource.suggestMatching(names, builder); + }; + + private static CompletableFuture claimProvider(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { + ServerPlayerEntity player = context.getSource().getPlayer(); + List names = new ArrayList<>(); + Claim current = ClaimManager.INSTANCE.getClaimAt(player.getBlockPos(), player.world.getDimension()); + if (current != null && !current.isChild) names.add(current.name); + for (Claim claim : ClaimManager.INSTANCE.getPlayerClaims(player.getGameProfile().getId())) { + if (claim != null && !claim.isChild) { + names.add(claim.name); + } + } + return CommandSource.suggestMatching(names, builder); + } + + private static CompletableFuture subzoneProvider(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { + ServerPlayerEntity player = context.getSource().getPlayer(); + List names = new ArrayList<>(); + Claim current = ClaimManager.INSTANCE.getClaimAt(player.getBlockPos(), player.world.getDimension()); + if (current != null && current.isChild) names.add(current.name); + for (Claim claim : ClaimManager.INSTANCE.getPlayerClaims(player.getGameProfile().getId())) { + if (claim != null && claim.isChild) { + names.add(claim.name); + } + } + return CommandSource.suggestMatching(names, builder); + } + + + private static final SuggestionProvider DIRECTION_PROVIDER = (source, builder) -> { + List strings = new ArrayList<>(); + for (Direction direction: Direction.values()) { + if (ItsMineConfig.main().claims2d && (direction == Direction.DOWN || direction == Direction.UP)) continue; + strings.add(direction.getName()); + }; + return CommandSource.suggestMatching(strings, builder); + }; + + public static final SuggestionProvider HELPID_PROVIDER = (source, builder) -> { + List strings = new ArrayList<>(); + for (Claim.HelpBook value : Claim.HelpBook.values()) { + strings.add(value.id); + } + return CommandSource.suggestMatching(strings, builder); + }; + + public static CompletableFuture itemsSuggestion(final CommandContext ctx, final SuggestionsBuilder builder) { + List strings = new ArrayList<>(); + Registry.ITEM.forEach((item) -> { + strings.add(Registry.ITEM.getId(item).getPath()); + }); + + return CommandSource.suggestMatching(strings, builder); + } + + public static final SuggestionProvider PLAYERS_PROVIDER = (source, builder) -> { + List strings = new ArrayList<>(); + for (ServerPlayerEntity player : source.getSource().getMinecraftServer().getPlayerManager().getPlayerList()) { + strings.add(player.getEntityName()); + } + return CommandSource.suggestMatching(strings, builder); + }; + + public static final SuggestionProvider SETTINGS_PROVIDER = (source, builder) -> { + List strings = new ArrayList<>(); + for (ClaimFlags.Flag value : ClaimFlags.Flag.values()) { + strings.add(value.id); + } + for (Claim.Permission value : Claim.Permission.values()) { + strings.add(value.id); + } + return CommandSource.suggestMatching(strings, builder); + }; + + public static final SuggestionProvider PERMISSIONS_PROVIDER = (source, builder) -> { + List strings = new ArrayList<>(); + for (Claim.Permission value : Claim.Permission.values()) { + strings.add(value.id); + } + return CommandSource.suggestMatching(strings, builder); + }; + + public static final SuggestionProvider MESSAGE_EVENTS_PROVIDER = (source, builder) -> { + List strings = new ArrayList<>(); + for (Claim.Event value : Claim.Event.values()) { + strings.add(value.id); + } + return CommandSource.suggestMatching(strings, builder); + }; + public static final SuggestionProvider EVENT_MESSAGE_PROVIDER = (source, builder) -> { + if (!builder.getRemaining().isEmpty()) + return builder.buildFuture(); + + List strings = new ArrayList<>(); + strings.add("reset"); + try { + Claim claim = ClaimManager.INSTANCE.claimsByName.get(getString(source, "claim")); + Claim.Event eventType = Claim.Event.getById(getString(source, "messageEvent")); + + if (eventType != null && claim != null) { + String message = eventType == Claim.Event.ENTER_CLAIM ? claim.enterMessage : claim.leaveMessage; + if (message != null) strings.add(message); + } + + } catch (Exception ignored) { + } + + return CommandSource.suggestMatching(strings, builder); + }; + + public static final SuggestionProvider SHOW_MODE_PROVIDER = (source, builder) -> { + List strings = new ArrayList<>(); + strings.add("outline"); + strings.add("corner"); +// strings.add("old"); + return CommandSource.suggestMatching(strings, builder); + }; + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/util/BlockUtil.java b/src/main/java/io/github/indicode/fabric/itsmine/util/BlockUtil.java new file mode 100644 index 0000000..50f85a8 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/util/BlockUtil.java @@ -0,0 +1,38 @@ +package io.github.indicode.fabric.itsmine.util; + +import net.minecraft.block.*; + +public class BlockUtil { + + public static boolean isContainer(Block block) { + return block instanceof AbstractChestBlock || isChest(block) || isEnderchest(block) || isShulkerBox(block); + } + + public static boolean isChest(Block block) { + return block == Blocks.CHEST || block == Blocks.BARREL; + } + + public static boolean isEnderchest(Block block) { + return block == Blocks.ENDER_CHEST; + } + + public static boolean isShulkerBox(Block block) { + return block == Blocks.SHULKER_BOX || block == Blocks.WHITE_SHULKER_BOX || block == Blocks.ORANGE_SHULKER_BOX || block == Blocks.MAGENTA_SHULKER_BOX || block == Blocks.LIGHT_BLUE_SHULKER_BOX || block == Blocks.YELLOW_SHULKER_BOX || block == Blocks.LIME_SHULKER_BOX || block == Blocks.PINK_SHULKER_BOX || block == Blocks.GRAY_SHULKER_BOX || block == Blocks.LIGHT_GRAY_SHULKER_BOX || block == Blocks.CYAN_SHULKER_BOX || block == Blocks.PURPLE_SHULKER_BOX || block == Blocks.BLUE_SHULKER_BOX || block == Blocks.BROWN_SHULKER_BOX || block == Blocks.GREEN_SHULKER_BOX || block == Blocks.RED_SHULKER_BOX || block == Blocks.BLACK_SHULKER_BOX; + } + + public static boolean isButton(Block block) { + return block instanceof AbstractButtonBlock; + } + + public static boolean isLever(Block block) { + return block instanceof LeverBlock; + } + + public static boolean isDoor(Block block) { + return block instanceof DoorBlock || block instanceof TrapdoorBlock; + } + + public static boolean isLectern(Block block) { + return block instanceof LecternBlock; + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/util/ChatColor.java b/src/main/java/io/github/indicode/fabric/itsmine/util/ChatColor.java new file mode 100644 index 0000000..93f665c --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/util/ChatColor.java @@ -0,0 +1,372 @@ +package io.github.indicode.fabric.itsmine.util; + +import com.google.common.collect.Maps; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import net.minecraft.text.LiteralText; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import org.apache.commons.lang3.Validate; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Map; +import java.util.regex.Pattern; + +public enum ChatColor { + /** + * Represents black + */ + BLACK('0', 0x00, Formatting.BLACK, "\\u001b[30m"), + /** + * Represents dark blue + */ + DARK_BLUE('1', 0x1, Formatting.DARK_BLUE, "\\u001b[34m"), + /** + * Represents dark green + */ + DARK_GREEN('2', 0x2, Formatting.DARK_GREEN, "\\u001b[32m"), + /** + * Represents dark blue (aqua) + */ + DARK_AQUA('3', 0x3, Formatting.DARK_AQUA, "\\u001b[36m"), + /** + * Represents dark red + */ + DARK_RED('4', 0x4, Formatting.DARK_RED, "\\u001b[31m"), + /** + * Represents dark purple + */ + DARK_PURPLE('5', 0x5, Formatting.DARK_PURPLE, "\\u001b[35m"), + /** + * Represents gold + */ + GOLD('6', 0x6, Formatting.GOLD, "\\u001b[33m"), + /** + * Represents gray + */ + GRAY('7', 0x7, Formatting.GRAY), + /** + * Represents dark gray + */ + DARK_GRAY('8', 0x8, Formatting.DARK_GRAY), + /** + * Represents blue + */ + BLUE('9', 0x9, Formatting.BLUE, "\\u001b[34;1m"), + /** + * Represents green + */ + GREEN('a', 0xA, Formatting.GREEN, "\\u001b[32;1m"), + /** + * Represents aqua + */ + AQUA('b', 0xB, Formatting.AQUA, "\\u001b[36;1m"), + /** + * Represents red + */ + RED('c', 0xC, Formatting.RED, "\\u001b[31;1m"), + /** + * Represents light purple + */ + LIGHT_PURPLE('d', 0xD, Formatting.LIGHT_PURPLE, "\\u001b[35;1m"), + /** + * Represents yellow + */ + YELLOW('e', 0xE, Formatting.YELLOW, "\\u001b[33;1m"), + /** + * Represents white + */ + WHITE('f', 0xF, Formatting.WHITE, "\\u001b[37;1m"), + /** + * Represents magical characters that change around randomly + */ + OBFUSCATED('k', 0x10, Formatting.OBFUSCATED, true), + /** + * Makes the text bold. + */ + BOLD('l', 0x11, Formatting.BOLD ,true, "\\u001b[1m"), + /** + * Makes a line appear through the text. + */ + STRIKETHROUGH('m', 0x12, Formatting.STRIKETHROUGH, true), + /** + * Makes the text appear underlined. + */ + UNDERLINE('n', 0x13, Formatting.UNDERLINE,true, "\\u001b[4m"), + /** + * Makes the text italic. + */ + ITALIC('o', 0x14, Formatting.ITALIC,true), + /** + * Resets all previous events colors or formats. + */ + RESET('r', 0x15, Formatting.RESET), + /** + * Reverses the Text and background color + * @apiNote Console Only + */ + REVERSED('s', 0, null, "\\u001b[7m"); + + private static String[] list() { + return new String[] {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", + "a", "b", "c", "d", "e", "f", "i", "k", "l", "m", "o", "r"}; + } + + public static final char COLOR_CHAR = '\u00A7'; + private static final Pattern STRIP_COLOR_PATTERN = Pattern.compile("(?i)" + COLOR_CHAR + "[0-9A-FK-OR]"); + + private final int intCode; + private final char code; + private final boolean isFormat; + private final Formatting formatting; + private final String toString; + private final String ansi; + private static final Map BY_ID = Maps.newHashMap(); + private static final Map BY_CHAR = Maps.newHashMap(); + + ChatColor(char code, int intCode, Formatting formatting, boolean isFormat, String ansi) { + this.code = code; + this.intCode = intCode; + this.isFormat = isFormat; + this.formatting = formatting; + this.toString = new String(new char[] {COLOR_CHAR, code}); + this.ansi = ansi; + } + + ChatColor(char code, int intCode, Formatting formatting, String ansi) { + this(code, intCode, formatting, false, ansi); + } + + ChatColor(char code, int intCode, Formatting formatting) { + this(code, intCode, formatting, false); + } + + ChatColor(char code, int intCode, Formatting formatting, boolean isFormat) { + this(code, intCode, formatting, isFormat, null); + } + + + /** + * Gets the char value associated with this color + * + * @return A char value of this color code + */ + public char getChar() { + return code; + } + + public static String[] getList() { + return ChatColor.list(); + } + + public Formatting getFormattingByChar(char code) { + return formatting; + } + + @NotNull + @Override + public String toString() { + return toString; + } + + /** + * Checks if this code is a format code as opposed to a color code. + * + * @return whether this ChatColor is a format code + */ + public boolean isFormat() { + return isFormat; + } + + /** + * Checks if this code is a color code as opposed to a format code. + * + * @return whether this ChatColor is a color code + */ + public boolean isColor() { + return !isFormat && this != RESET; + } + + /** + * Gets the ANSI code for a TextFormat + * + * @return ANSI Formatting code + */ + public String getAnsiCode() { + return ansi; + } + + /** + * Strips the given message of all color codes + * + * @param input String to strip of color + * @return A copy of the input string, without any coloring + */ + @Contract("!null -> !null; null -> null") + @Nullable + public static String stripColor(@Nullable final String input) { + if (input == null) { + return null; + } + + return STRIP_COLOR_PATTERN.matcher(input).replaceAll(""); + } + + public static Text translateToNMSText(String jsonString) { + return Text.Serializer.fromJson(jsonString); + } + + /** + * Translates a string using an alternate color code character into a + * string that uses the internal ChatColor.COLOR_CODE color code + * character. The alternate color code character will only be replaced if + * it is immediately followed by 0-9, A-F, a-f, K-O, k-o, R or r. + * + * @param altColorChar The alternate color code character to replace. Ex: {@literal &} + * @param textToTranslate Text containing the alternate color code character. + * @return Text containing the ChatColor.COLOR_CODE color code character. + */ + + @NotNull + public static String translateAlternateColorCodes(char altColorChar, @NotNull String textToTranslate) { + Validate.notNull(textToTranslate, "Cannot translate null text"); + char[] b = textToTranslate.toCharArray(); + + for (int i = 0; i < b.length - 1; i++) { + if (b[i] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i+1]) > -1) { + b[i] = ChatColor.COLOR_CHAR; + b[i+1] = Character.toLowerCase(b[i+1]); + } + } + return new String(b); + } + + public static Text translateStringToText(char altColorChar, String input) { + String[] strings = input.split("(?=(((\\&([0-9]|[a-f])){1}(\\&(k|l|m|n|o|r)){0,5}))|^(\\&([0-9]|[a-f]))?(\\&(k|l|m|n|o|r)){1,5})"); + MutableText text = new LiteralText(""); + for(String string : strings) { + System.out.println(string); + char[] b = string.toCharArray(); + ArrayList formattings = new ArrayList<>(); + for (int i = 0; i < b.length - 1; i++) { + if(b[i] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i+1]) > -1){ + ChatColor color = getByChar(b[i+1]); + formattings.add(color.getFormattingByChar(b[i+1])); + } + } + MutableText part = new LiteralText(removeAlternateColorCodes('&', string))/*.formatted(formattings.get(0))*/; + for(Formatting formatting : formattings){ + part.formatted(formatting); + } + text.append(part/*new LiteralText(removeAlternateColorCodes('&', string)).formatted(formattings.toArray(new Formatting[formattings.size()]))*/); + } + return text; + } + + public static String reverseTranslate(String textToTranslate, char altColorChar) { + Validate.notNull(textToTranslate, "Cannot translate null text"); + char[] b = textToTranslate.toCharArray(); + + for (int i = 0; i < b.length - 1; i++) { + if (b[i] == COLOR_CHAR && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i+1]) > -1) { + b[i] = altColorChar; + b[i+1] = Character.toLowerCase(b[i+1]); + } + } + return new String(b); + } + + @NotNull + public static String translate(String string) { + return translateAlternateColorCodes('&', string); + } + + @NotNull + public static String translate(String string, boolean allowFormats) { + return allowFormats ? translate(string) : ChatColor.removeAlternateColorCodes('&', string); + } + + public static LiteralText translateToLiteralText(char altColorChar, @NotNull String textToTranslate) { + return new LiteralText(translateAlternateColorCodes(altColorChar, textToTranslate)); + } + + public static String removeAlternateColorCodes(char altColorChar, @NotNull String textToTranslate) { + Validate.notNull(textToTranslate, "Cannot translate null text"); + for (char c : "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".toCharArray()) { + textToTranslate = textToTranslate.replace(String.valueOf(ChatColor.COLOR_CHAR) + c, ""); + textToTranslate = textToTranslate.replace(String.valueOf(altColorChar) + c, ""); + } + return textToTranslate; + } + + public static LiteralText removeAlternateToLiteralText(char altColorChar, @NotNull String textToTranslate) { + return new LiteralText(removeAlternateColorCodes(altColorChar, textToTranslate)); + } + + @Nullable + public static ChatColor getByChar(char code) { + return BY_CHAR.get(code); + } + + /** + * Gets the ChatColors used at the end of the given input string. + * + * @param input Input string to retrieve the colors from. + * @return Any remaining ChatColors to pass onto the next line. + */ + @NotNull + public static String getLastColors(@NotNull String input) { + Validate.notNull(input, "Cannot get last colors from null text"); + + String result = ""; + int length = input.length(); + + // Search backwards from the end as it is faster + for (int index = length - 1; index > -1; index--) { + char section = input.charAt(index); + if (section == COLOR_CHAR && index < length - 1) { + char c = input.charAt(index + 1); + ChatColor color = getByChar(c); + + if (color != null) { + result = color.toString() + result; + + // Once we find a color or reset we can stop searching + if (color.isColor() || color.equals(RESET)) { + break; + } + } + } + } + + return result; + } + + public static String getFormattedPing(int i) { + if (i < 200) + return "&a" + i; + if (i > 200 && i < 400) + return "&e" + i; + + return "&c" + i; + } + + public static char getFormattedTPS(double tps) { + if (tps > 15) + return 'a'; + if (tps > 10) + return 'e'; + + return 'c'; + } + + static { + for (ChatColor color : values()) { + BY_ID.put(color.intCode, color); + BY_CHAR.put(color.code, color); + } + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/util/ClaimUtil.java b/src/main/java/io/github/indicode/fabric/itsmine/util/ClaimUtil.java new file mode 100644 index 0000000..8b7a0e9 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/util/ClaimUtil.java @@ -0,0 +1,230 @@ +package io.github.indicode.fabric.itsmine.util; + +import blue.endless.jankson.annotation.Nullable; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import io.github.indicode.fabric.itsmine.*; +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.claim.ClaimFlags; +import net.minecraft.nbt.NbtIo; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.concurrent.atomic.AtomicReference; + +public class ClaimUtil { + public static BlockPos getPosOnGround(BlockPos pos, World world) { + BlockPos blockPos = new BlockPos(pos.getX(), 256, pos.getZ()); + + do { + blockPos = blockPos.down(); + if(blockPos.getY() < 1){ + return pos; + } + } while (!world.getBlockState(blockPos).isFullCube(world, pos)); + + return blockPos.up(); + } + + public static Claim getParentClaim(Claim subzone){ + AtomicReference parentClaim = new AtomicReference<>(); + if(subzone.isChild){ + ClaimManager.INSTANCE.claimsByName.forEach((name, claim) -> { + for(Claim subzone2 : claim.children){ + if(subzone2 == subzone){ + parentClaim.set(claim); + } + } + }); + return parentClaim.get(); + } + return subzone; + } + + public static void validateClaim(Claim claim) throws CommandSyntaxException { + if (claim == null) throw new SimpleCommandExceptionType(Messages.INVALID_CLAIM).create(); + } + + public static boolean verifyPermission(Claim claim, Claim.Permission permission, CommandContext context, boolean admin) throws CommandSyntaxException { + if (verifyExists(claim, context)) { + if (claim.permissionManager.hasPermission(context.getSource().getPlayer().getGameProfile().getId(), permission)) { + return true; + } else { + context.getSource().sendFeedback(new LiteralText(admin ? "You are modifying a claim using admin privileges" : "You cannot modify exceptions for this claim").formatted(admin ? Formatting.DARK_RED : Formatting.RED), false); + return admin; + } + } else { + return false; + } + } + private static boolean verifyExists(Claim claim, CommandContext context) { + if (claim == null) { + context.getSource().sendFeedback(new LiteralText("That claim does not exist").formatted(Formatting.RED), false); + return false; + } else { + return true; + } + } + + public static ArrayList getClaims(){ + ArrayList claims = new ArrayList<>(); + ClaimManager.INSTANCE.claimsByName.forEach((s, claim) -> { + claims.add(claim); + }); + return claims; + } + + public static void validateCanAccess(ServerPlayerEntity player, Claim claim, boolean admin) throws CommandSyntaxException { + if (claim == null) { + throw new SimpleCommandExceptionType(Messages.INVALID_CLAIM).create(); + } + + if (!admin && !claim.permissionManager.hasPermission(player.getGameProfile().getId(), Claim.Permission.MODIFY_SETTINGS)) { + throw new SimpleCommandExceptionType(Messages.NO_PERMISSION).create(); + } + } + + public static int queryFlag(ServerCommandSource source, Claim claim, ClaimFlags.Flag flag) { + boolean enabled = claim.flags.getFlag(flag); + source.sendFeedback(new LiteralText(ChatColor.translate("&eFlag &6" + flag.name + " &e is set to " + (enabled ? "&a" : "&c") + enabled + "&e for &6" + claim.name)), false); + return 1; + } + public static int setFlag(ServerCommandSource source, Claim claim, ClaimFlags.Flag flag, boolean set) { + claim.flags.flags.put(flag, set); + source.sendFeedback(new LiteralText(ChatColor.translate("&eSet flag &6" + flag.name + "&e to " + (set ? "&a" : "&c") + set + "&e for &6" + claim.name)), false); + return 0; + } + public static int queryPermission(ServerCommandSource source, Claim claim, Claim.Permission permission) { + boolean defaultPerm = claim.permissionManager.defaults.hasPermission(permission); + source.sendFeedback(new LiteralText(ChatColor.translate("&ePermission &6" + permission.id + "&e is set to " + (defaultPerm ? "&a" : "&c") + defaultPerm + "&e for &6" + claim.name)), false); + return 1; + } + public static int setPermission(ServerCommandSource source, Claim claim, Claim.Permission permission, boolean set) { + claim.permissionManager.defaults.setPermission(permission, set); + source.sendFeedback(new LiteralText(ChatColor.translate("&eSet permission &6" + permission.id + "&e to " + (set ? "&a" : "&c") + set + "&e for &6" + claim.name)), false); + return 1; + } + public static int queryFlags(ServerCommandSource source, Claim claim) { + source.sendFeedback(new LiteralText("\n").append(new LiteralText("Flags: " + claim.name).formatted(Formatting.YELLOW)).append(new LiteralText("\n")) + .append(Messages.Command.getFlags(claim)).append(new LiteralText("\n")), false); + return 1; + } + public static int executeFlag(ServerCommandSource source, String input, @Nullable String claimName, boolean isQuery, boolean value, boolean admin) throws CommandSyntaxException { + ServerPlayerEntity player = source.getPlayer(); + Claim claim1 = claimName == null || claimName.isEmpty() ? ClaimManager.INSTANCE.getClaimAt(player.getBlockPos(), player.world.getDimension()) : + ClaimManager.INSTANCE.claimsByName.get(claimName); + if (claim1 == null) { + source.sendError(Messages.INVALID_CLAIM); + return -1; + } + + if (input == null) { + return queryFlags(source, claim1); + } + + validateCanAccess(player, claim1, admin); + ClaimFlags.Flag flag = ClaimFlags.Flag.byId(input); + Claim.Permission permission = Claim.Permission.byId(input); + + if (flag != null && permission == null) + return isQuery ? queryFlag(source, claim1, flag) : setFlag(source, claim1, flag, value); + + if (flag == null && permission != null) + return isQuery ? queryPermission(source, claim1, permission) : setPermission(source, claim1, permission, value); + + source.sendError(Messages.INVALID_SETTING); + return -1; + } + public static int executePermission(ServerCommandSource source, String input, @Nullable String claimName, boolean isQuery, boolean value, boolean admin) throws CommandSyntaxException { + ServerPlayerEntity player = source.getPlayer(); + Claim claim1 = claimName == null ? ClaimManager.INSTANCE.getClaimAt(player.getBlockPos(), player.world.getDimension()) : + ClaimManager.INSTANCE.claimsByName.get(claimName); + if (claim1 == null) { + source.sendError(Messages.INVALID_CLAIM); + return -1; + } + + validateCanAccess(player, claim1, admin); + Claim.Permission permission = Claim.Permission.byId(input); + if (permission != null) + return !isQuery ? setPermission(source, claim1, permission, value) : queryPermission(source, claim1, permission); + + source.sendError(Messages.INVALID_SETTING); + return -1; + } + + public static int modifyException(Claim claim, ServerPlayerEntity exception, Claim.Permission permission, boolean allowed) { + claim.permissionManager.setPermission(exception.getGameProfile().getId(), permission, allowed); + return 0; + } + private static int modifyException(Claim claim, String exception, Claim.Permission permission, boolean allowed) { + claim.permissionManager.setPermission(exception, permission, allowed); + return 0; + } + + public static boolean hasPermission(Claim claim, ServerPlayerEntity exception, Claim.Permission permission) { + return claim.permissionManager.hasPermission(exception.getGameProfile().getId(), permission); + } + + public static int setEventMessage(ServerCommandSource source, Claim claim, Claim.Event event, String message) { + switch (event) { + case ENTER_CLAIM: + claim.enterMessage = message.equalsIgnoreCase("reset") ? null : message; + break; + case LEAVE_CLAIM: + claim.leaveMessage = message.equalsIgnoreCase("reset") ? null : message; + break; + } + + if (message.equalsIgnoreCase("reset")) { + source.sendFeedback(new LiteralText("Reset ").append(new LiteralText(event.id).formatted(Formatting.GOLD) + .append(new LiteralText(" Event Message for claim ").formatted(Formatting.YELLOW)) + .append(new LiteralText(claim.name).formatted(Formatting.GOLD))).formatted(Formatting.YELLOW) + , false); + return -1; + } + + source.sendFeedback(new LiteralText("Set ").append(new LiteralText(event.id).formatted(Formatting.GOLD) + .append(new LiteralText(" Event Message for claim ").formatted(Formatting.YELLOW)) + .append(new LiteralText(claim.name).formatted(Formatting.GOLD)).append(new LiteralText(" to:").formatted(Formatting.YELLOW))) + .append(new LiteralText("\n")).append(new LiteralText(ChatColor.translate(message))) + .formatted(Formatting.YELLOW) + , false); + return 1; + } + + public static void readWorldProperties() { + File claims = new File(ItsMine.getDirectory() + "/world/claims.dat"); + File claims_old = new File(ItsMine.getDirectory() + "/world/claims.dat_old"); + if (!claims.exists()) { + if (claims_old.exists()) {} + else return; + } + try { + if (!claims.exists() && claims_old.exists()) throw new FileNotFoundException(); + ClaimManager.INSTANCE.fromNBT(NbtIo.readCompressed(new FileInputStream(claims))); + } catch (IOException e) { + System.out.println("Could not load " + claims.getName() + ":"); + e.printStackTrace(); + if (claims_old.exists()) { + System.out.println("Attempting to load backup claims..."); + try { + ClaimManager.INSTANCE.fromNBT(NbtIo.readCompressed(new FileInputStream(claims_old))); + } catch (IOException e2) { + throw new RuntimeException("Could not load claims.dat_old - Crashing server to save data. Remove or fix claims.dat or claims.dat_old to continue"); + } + } + } + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/util/DirectionUtil.java b/src/main/java/io/github/indicode/fabric/itsmine/util/DirectionUtil.java new file mode 100644 index 0000000..0663353 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/util/DirectionUtil.java @@ -0,0 +1,12 @@ +package io.github.indicode.fabric.itsmine.util; + +import net.minecraft.util.math.Direction; + +public class DirectionUtil { + public static Direction directionByName(String name) { + for (Direction direction : Direction.values()) { + if (name.equals(direction.getName())) return direction; + } + return null; + } +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/util/EntityUtil.java b/src/main/java/io/github/indicode/fabric/itsmine/util/EntityUtil.java new file mode 100644 index 0000000..36ddcc7 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/util/EntityUtil.java @@ -0,0 +1,64 @@ +package io.github.indicode.fabric.itsmine.util; + +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.Functions; +import io.github.indicode.fabric.itsmine.MonitorableWorld; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; +import net.minecraft.server.world.ServerWorld; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + + +public class EntityUtil { + + public static boolean canAttack(UUID player, Claim claim, Entity entity) { + return claim.hasPermission(player, Claim.Permission.DAMAGE_ENTITY) || + (isPassive(entity) && claim.hasPermission(player, Claim.Permission.DAMAGE_ENTITY_PASSIVE) || + (isHostile(entity) && claim.hasPermission(player, Claim.Permission.DAMAGE_ENTITY_HOSTILE))); + } + + public static boolean isPassive(Entity entity) { + return entity.getType().getSpawnGroup().isPeaceful(); + } + + public static boolean isHostile(Entity entity) { + return !isPassive(entity); + } + + public static ArrayList getEntities(Claim claim){ + ArrayList entityList = new ArrayList<>(); + ServerWorld world = WorldUtil.getServerWorld(claim.dimension); + MonitorableWorld monitorableWorld = (MonitorableWorld) world; + monitorableWorld.EntityList().forEach((uuid, entity) -> { + if(claim.includesPosition(entity.getBlockPos())) entityList.add(entity); + }); + return entityList; + } + + public static ArrayList filterByCategory(ArrayList entityList, SpawnGroup spawnGroup){ + ArrayList filteredEntityList = new ArrayList<>(); + for(Entity entity : entityList) if(entity.getType().getSpawnGroup() == spawnGroup) filteredEntityList.add(entity); + return filteredEntityList; + } + + public static Map sortByType(ArrayList entityList){ + Map entityMap = new HashMap<>(); + for(Entity entity : entityList) { + EntityType entityType = entity.getType(); + if (entityMap.containsKey(entityType)) { + entityMap.put(entityType, entityMap.get(entityType)+1); + } else { + entityMap.put(entityType, 1); + } + } + return Functions.sortByValue(entityMap); + } + + + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/util/MessageUtil.java b/src/main/java/io/github/indicode/fabric/itsmine/util/MessageUtil.java new file mode 100644 index 0000000..8b16bf5 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/util/MessageUtil.java @@ -0,0 +1,76 @@ +package io.github.indicode.fabric.itsmine.util; + +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.ClickEvent; +import net.minecraft.text.HoverEvent; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +import java.util.ArrayList; + +public class MessageUtil { + + public static void sendPage(ServerCommandSource source, Text header, int entries, int page, String command, ArrayList content) { + + for (int i=0; i < content.size(); i += entries) { + System.out.println(content.subList(i, Math.min(content.size(), i + entries))); + } + + int pages = Math.floorDiv(content.size(), entries); + if(content.size() % entries != 0) pages++; + if(page < 1) return; + if(page > pages) return; + LiteralText message = new LiteralText(""); + message.append(header).append(new LiteralText("\n\n")); + for (int i = 0; i < content.size(); i += entries) { + content.subList(i, Math.min(content.size(), i + entries)).forEach(text -> { + message.append(text).append(new LiteralText("\n")); + }); + } + + message.append(new LiteralText("\n")); + Text button_prev = new LiteralText("") + .append(new LiteralText("<-").formatted(Formatting.WHITE).formatted(Formatting.BOLD)) + .append(new LiteralText(" ")).append(new LiteralText("Prev").formatted(Formatting.GOLD)) + .styled((style) -> { + if (page - 1 >= 0) { + return style.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new LiteralText((page - 1 >= 0) ? "<<<" : "|<").formatted(Formatting.GRAY))).withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command.replace("%page%", String.valueOf(page - 1)))); + } + return style.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new LiteralText((page - 1 >= 0) ? "<<<" : "|<").formatted(Formatting.GRAY))); + + }).append(new LiteralText(" ")); + int finalPages = pages; + Text button_next = new LiteralText(" ") + .append(new LiteralText("Next").formatted(Formatting.GOLD)) + .append(new LiteralText(" ")).append(new LiteralText("->").formatted(Formatting.WHITE).formatted(Formatting.BOLD)).append(new LiteralText(" ")) + .styled((style) -> { + if (page + 1 <= finalPages){ + return style.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new LiteralText((page + 1 <= finalPages) ? ">>>" : ">|").formatted(Formatting.GRAY))).withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command.replace("%page%", String.valueOf(page + 1)))); + } + return style.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new LiteralText((page + 1 <= finalPages) ? ">>>" : ">|").formatted(Formatting.GRAY))); + }); + Text center = new LiteralText("").append(new LiteralText(String.valueOf(page)).formatted(Formatting.GREEN).append(new LiteralText("/").formatted(Formatting.GRAY)).append(new LiteralText(String.valueOf(pages)).formatted(Formatting.GREEN))); + System.out.println(8); + if(page > 1) message.append(button_prev); + message.append(center); + if(page < pages) message.append(button_next); + System.out.println(10); + sendText(source, message); + } + + public static void sendText(ServerCommandSource source, LiteralText text) { +// if(((ClaimPlayerEntity) source.getPlayer()).shouldMessage()){ + source.sendFeedback(text, false); +// ((ClaimPlayerEntity) source.getPlayer()).setMessageCooldown(); +// } + } + +// public static void sendText(PlayerEntity player, LiteralText text) throws CommandSyntaxException { +// if(((ClaimPlayerEntity) player).shouldMessage()){ +// player.sendSystemMessage(new LiteralText(ItsMineConfig.main().prefix).append(text)); +// ((ClaimPlayerEntity) player).setMessageCooldown(); +// } +// } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/util/Messenger.java b/src/main/java/io/github/indicode/fabric/itsmine/util/Messenger.java new file mode 100644 index 0000000..a918c9a --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/util/Messenger.java @@ -0,0 +1,12 @@ +package io.github.indicode.fabric.itsmine.util; + +import net.minecraft.text.LiteralText; +import net.minecraft.text.MutableText; + +public class Messenger { + + public static MutableText toText(String text) { + return new LiteralText(ChatColor.translate(text)); + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/util/NbtUtil.java b/src/main/java/io/github/indicode/fabric/itsmine/util/NbtUtil.java new file mode 100644 index 0000000..99d44db --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/util/NbtUtil.java @@ -0,0 +1,24 @@ +package io.github.indicode.fabric.itsmine.util; + + +import net.minecraft.nbt.CompoundTag; + +import java.util.UUID; + +public class NbtUtil { + + public static UUID getUUID(CompoundTag tag, String key){ + if (tag.contains(key + "Least") && tag.contains(key + "Most")) { + final long least = tag.getLong(key + "Least"); + final long most = tag.getLong(key + "Most"); + return new UUID (most, least); + } + + return tag.getUuidNew(key); + } + + public static boolean containsUUID(CompoundTag tag, String key){ + return (tag.contains(key + "Least") && tag.contains(key + "Most")) || tag.containsUuidNew(key); + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/util/PermissionUtil.java b/src/main/java/io/github/indicode/fabric/itsmine/util/PermissionUtil.java new file mode 100644 index 0000000..fefba5b --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/util/PermissionUtil.java @@ -0,0 +1,224 @@ +package io.github.indicode.fabric.itsmine.util; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.indicode.fabric.itsmine.ItsMine; +import io.github.indicode.fabric.itsmine.ItsMineConfig; +import io.github.indicode.fabric.permissions.PermChangeBehavior; +import io.github.indicode.fabric.permissions.Thimble; +import net.fabricmc.loader.api.FabricLoader; +import net.luckperms.api.LuckPerms; +import net.luckperms.api.LuckPermsProvider; +import net.luckperms.api.model.user.User; +import net.luckperms.api.query.QueryOptions; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Logger; +import org.jetbrains.annotations.NotNull; + +import java.util.Locale; +import java.util.UUID; +import java.util.function.Predicate; + +public class PermissionUtil { + private Manager manager; + private boolean present; + + public PermissionUtil() { + Logger logger = (Logger) LogManager.getLogger("ItsMine"); + logger.info("Setting up Permissions..."); + this.manager = Manager.fromString(ItsMineConfig.main().permissionManager); + + if (manager == Manager.VANILLA) { + this.present = false; + logger.info("Using Vanilla Permissions for Claims"); + return; + } + + logger.info("Checking " + manager.getName() + " for Availability"); + + this.present = this.checkPresent(); + + if (!this.present) { + logger.warn("**** " + manager.getName() + " is not present! Switching to vanilla operator system"); + logger.warn(" You need to install either LuckPerms for Fabric Or Thimble to manage the permissions"); + this.manager = Manager.NONE; + return; + } + + logger.info("Using " + manager.getName() + " as the Permission Manager"); + + + if (manager == Manager.THIMBLE) { + Thimble.permissionWriters.add((map, server) -> { + for (Command value : Command.values()) { + map.registerPermission(value.getNode(), PermChangeBehavior.UPDATE_COMMAND_TREE); + } + }); + } + } + + public static void reload(){ + new PermissionUtil(); + } + + public boolean hasPermission(ServerCommandSource src, Command permission, int opLevel) { + if (present) { + if (manager == Manager.LUCKPERMS) { + return fromLuckPerms(src, permission.getNode(), opLevel); + } + + if (manager == Manager.THIMBLE) { + return fromThimble(src, permission.getNode(), opLevel); + } + } + + return src.hasPermissionLevel(opLevel); + } + + public boolean hasPermission(ServerCommandSource src, String permission, int opLevel) { + if (present) { + if (manager == Manager.LUCKPERMS) { + return fromLuckPerms(src, permission, opLevel); + } + + if (manager == Manager.THIMBLE) { + return fromThimble(src, permission, opLevel); + } + } + + return src.hasPermissionLevel(opLevel); + } + + public boolean hasPermission(UUID uuid, String permission) { + if (present) { + if (manager == Manager.LUCKPERMS) { + LuckPerms luckPerms = LuckPermsProvider.get(); + + User user = luckPerms.getUserManager().getUser(uuid); + + if (user != null) { + QueryOptions options = luckPerms.getContextManager().getStaticQueryOptions(); + return user.getCachedData().getPermissionData(options).checkPermission(permission).asBoolean(); + } + } + + if (manager == Manager.THIMBLE) { + return Thimble.PERMISSIONS.hasPermission(permission, uuid); + } + } + + return false; + } + + private boolean fromLuckPerms(ServerCommandSource src, String perm, int op) { + LuckPerms luckPerms = LuckPermsProvider.get(); + + try { + ServerPlayerEntity player = src.getPlayer(); + User user = luckPerms.getUserManager().getUser(player.getUuid()); + + if (user != null) { + QueryOptions options = luckPerms.getContextManager().getQueryOptions(player); + return user.getCachedData().getPermissionData(options).checkPermission(perm).asBoolean(); + } + + } catch (CommandSyntaxException ignored) { + } + + return src.hasPermissionLevel(op); + } + + private boolean fromThimble(ServerCommandSource src, String perm, int op) { + return Thimble.hasPermissionOrOp(src, perm, op); + } + + private boolean checkPresent() { + if (manager == Manager.NONE) { + return false; + } + + try { + if (manager == Manager.LUCKPERMS) { + try { + LuckPermsProvider.get(); + return true; + } catch (Throwable ignored) { + } + } + + if (manager == Manager.THIMBLE) { + return true; + } + + return FabricLoader.getInstance().getModContainer(manager.getName().toLowerCase(Locale.ROOT)).isPresent(); + } catch (Exception ignored) { + return false; + } + } + + public boolean managerPresent() { + return this.present; + } + + public Manager getManager() { + return this.manager; + } + + public enum Manager { + VANILLA("Vanilla", ""), + NONE("none", ""), + LUCKPERMS("LuckPerms", "net.luckperms.api.LuckPerms"), + THIMBLE("Thimble", "io.github.indicode.fabric.permissions.Thimble"); + + private final String name; + private final String classPath; + + Manager(final String name, final String classPath) { + this.name = name; + this.classPath = classPath; + } + + public String getName() { + return this.name; + } + + public final String getClassPath() { + return this.classPath; + } + + @NotNull + public static Manager fromString(String str) { + for (Manager value : Manager.values()) { + if (value.name.equalsIgnoreCase(str)) { + return value; + } + } + + return Manager.NONE; + } + } + + public enum Command { + SPECIFY_GROUPS("specify_groups"), + CLAIM_FLY("claim_fly"), + INFINITE_BLOCKS("infinite_blocks"), + ADMIN_INFINITE_CLAIM("admin.infinite_claim"), + ADMIN_CHECK_OTHERS("admin.check_others"), + ADMIN_MODIFY_BALANCE("admin.modify_balance"), + ADMIN_MODIFY("admin.modify"), + ADMIN_MODIFY_PERMISSIONS("admin.modify_permissions"), + ADMIN_IGNORE_CLAIMS("admin.ignore_claims"); + + private final String NODE; + Command(final String node) { + this.NODE = node; + } + + public String getNode() { + return "itsmine." + this.NODE; + } + } + + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/util/ShowerUtil.java b/src/main/java/io/github/indicode/fabric/itsmine/util/ShowerUtil.java new file mode 100644 index 0000000..2526cd9 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/util/ShowerUtil.java @@ -0,0 +1,101 @@ +package io.github.indicode.fabric.itsmine.util; + +import io.github.indicode.fabric.itsmine.claim.Claim; +import io.github.indicode.fabric.itsmine.ClaimShower; +import io.github.indicode.fabric.itsmine.mixin.BlockUpdatePacketMixin; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; +import net.minecraft.util.math.BlockPos; + +public class ShowerUtil { + + + public static void update(Claim claim, ServerWorld world, boolean hide){ + world.getPlayers().forEach(playerEntity -> { + ClaimUtil.getParentClaim(claim); + if (((ClaimShower)playerEntity).getShownClaim() != null && ((ClaimShower)playerEntity).getShownClaim().name.equals(claim.name)) silentHideShow(playerEntity, claim, hide, false, ((ClaimShower) playerEntity).getMode()); + }); + } + + public static void silentHideShow(ServerPlayerEntity player, Claim claim, boolean hide, boolean updateStatus, String mode) { + if (updateStatus) { + if (!hide) { + ((ClaimShower) player).setShownClaim(claim); + ((ClaimShower) player).setShowMode(mode); + } + else ((ClaimShower) player).setShownClaim(null); + } + BlockState block = hide ? null : Blocks.GOLD_BLOCK.getDefaultState(); + show(player, claim, hide, block, mode); + if(!claim.isChild){ + block = hide ? null : Blocks.DIAMOND_BLOCK.getDefaultState(); + for(Claim subzone : claim.children){ + show(player, subzone, hide, block, mode); + } + } + + } + + private static void show(ServerPlayerEntity player, Claim claim, boolean hide, BlockState state, String mode){ + state = hide ? null : state; + if(mode == null) mode = ((ClaimShower)player).getMode() == null ? "outline" : ((ClaimShower)player).getMode(); + + switch (mode){ + case "outline": { + showOutline(player, claim, state);break; + } + case "corner": { + showCorner(player, claim, state);break; + } + default: { + player.sendSystemMessage(new LiteralText("Unknown mode").formatted(Formatting.RED), player.getUuid()); + } + } + } + + private static void showOutline(ServerPlayerEntity player, Claim claim, BlockState state){ + int y = player.getBlockPos().getY(); + for(int i = claim.min.getX(); i < claim.max.getX(); i++){ + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(i, y, claim.min.getZ()), player.getEntityWorld())).down(), state); + } + for(int i = claim.min.getZ(); i < claim.max.getZ(); i++){ + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(claim.max.getX(), y, i), player.getEntityWorld())).down(), state); + } + for(int i = claim.max.getX(); i > claim.min.getX(); i--){ + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(i, y, claim.max.getZ()), player.getEntityWorld())).down(), state); + } + for(int i = claim.max.getZ(); i > claim.min.getZ(); i--){ + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(claim.min.getX(), y, i), player.getEntityWorld())).down(), state); + } + } + + private static void showCorner(ServerPlayerEntity player, Claim claim, BlockState state){ + int y = player.getBlockPos().getY(); + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(claim.min.getX(), y, claim.min.getZ()), player.getEntityWorld())).down(), state); + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(claim.min.getX(), y, claim.max.getZ()), player.getEntityWorld())).down(), state); + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(claim.max.getX(), y, claim.min.getZ()), player.getEntityWorld())).down(), state); + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(claim.max.getX(), y, claim.max.getZ()), player.getEntityWorld())).down(), state); + + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(claim.min.getX(), y, claim.min.getZ()).south(), player.getEntityWorld())).down(), state); + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(claim.min.getX(), y, claim.max.getZ()).east(), player.getEntityWorld())).down(), state); + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(claim.max.getX(), y, claim.min.getZ()).south(), player.getEntityWorld())).down(), state); + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(claim.max.getX(), y, claim.max.getZ()).north(), player.getEntityWorld())).down(), state); + + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(claim.min.getX(), y, claim.min.getZ()).east(), player.getEntityWorld())).down(), state); + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(claim.min.getX(), y, claim.max.getZ()).north(), player.getEntityWorld())).down(), state); + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(claim.max.getX(), y, claim.min.getZ()).west(), player.getEntityWorld())).down(), state); + sendBlockPacket(player, new BlockPos(ClaimUtil.getPosOnGround(new BlockPos(claim.max.getX(), y, claim.max.getZ()).west(), player.getEntityWorld())).down(), state); + } + + private static void sendBlockPacket(ServerPlayerEntity player, BlockPos pos, BlockState state) { + BlockUpdateS2CPacket packet = new BlockUpdateS2CPacket(player.world, pos); + if (state != null) ((BlockUpdatePacketMixin)packet).setState(state); + player.networkHandler.sendPacket(packet); + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/util/TimeUtil.java b/src/main/java/io/github/indicode/fabric/itsmine/util/TimeUtil.java new file mode 100644 index 0000000..35005d6 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/util/TimeUtil.java @@ -0,0 +1,130 @@ +package io.github.indicode.fabric.itsmine.util; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class TimeUtil { + + private static Pattern timePattern = Pattern.compile("(?:([0-9]+)\\s*y[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*mo[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*w[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*d[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*h[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*m[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*(?:s[a-z]*)?)?", Pattern.CASE_INSENSITIVE); + private static final int maxYears = 100000; + private static SimpleCommandExceptionType TIME_ARGUMENT_INVALID = new SimpleCommandExceptionType(new LiteralText("Invalid time argument").formatted(Formatting.RED)); + + + public static String convertSecondsToString(int seconds, char numFormat, char typeFormat) { + int day = seconds / (24 * 3600); + seconds = seconds % (24 * 3600); + int hour = seconds / 3600; + seconds %= 3600; + int min = seconds / 60; + seconds %= 60; + + return ((day != 0) ? "§" + numFormat + day + "§" + typeFormat + " Days " : "") + + ((hour != 0) ? "§" + numFormat + hour + "§" + typeFormat + " Hours " : "") + + ((min != 0) ? "§" + numFormat + min + "§" + typeFormat + " Minutes " : "") + + ((seconds != 0) ? "§" + numFormat + seconds + "§" + typeFormat + " Seconds " : ""); + } + + public static int convertStringtoSeconds(String time) throws CommandSyntaxException { + Calendar c = new GregorianCalendar(); + int current = (int) (c.getTimeInMillis() / 1000); + int until = convertStringtoUnix(time); + return until - current; + } + + public static int convertStringtoUnix(String time) throws CommandSyntaxException { + Date date = new Date(); + Matcher matcher = timePattern.matcher(time); + int years = 0; + int months = 0; + int weeks = 0; + int days = 0; + int hours = 0; + int minutes = 0; + int seconds = 0; + boolean found = false; + while (matcher.find()) { + if (matcher.group() == null || matcher.group().isEmpty()) + continue; + + for (int i = 0; i < matcher.groupCount(); i++) { + if (matcher.group(i) != null && !matcher.group(i).isEmpty()) { + found = true; + break; + } + } + + if (!found) { + throw TIME_ARGUMENT_INVALID.create(); + } + + if (matcher.group(1) != null && !matcher.group(1).isEmpty()) { + years = Integer.parseInt(matcher.group(1)); + } + if (matcher.group(2) != null && !matcher.group(2).isEmpty()) { + months = Integer.parseInt(matcher.group(2)); + } + if (matcher.group(3) != null && !matcher.group(3).isEmpty()) { + weeks = Integer.parseInt(matcher.group(3)); + } + if (matcher.group(4) != null && !matcher.group(4).isEmpty()) { + days = Integer.parseInt(matcher.group(4)); + } + if (matcher.group(5) != null && !matcher.group(5).isEmpty()) { + hours = Integer.parseInt(matcher.group(5)); + } + if (matcher.group(6) != null && !matcher.group(6).isEmpty()) { + minutes = Integer.parseInt(matcher.group(6)); + } + if (matcher.group(7) != null && !matcher.group(7).isEmpty()) { + seconds = Integer.parseInt(matcher.group(7)); + } + break; + } + + Calendar c = new GregorianCalendar(); + if (years > 0) { + if (years > maxYears) { + years = maxYears; + } + c.add(Calendar.YEAR, years); + } + if (months > 0) { + c.add(Calendar.MONTH, months); + } + if (weeks > 0) { + c.add(Calendar.WEEK_OF_YEAR, weeks); + } + if (days > 0) { + c.add(Calendar.DAY_OF_MONTH, days); + } + if (hours > 0) { + c.add(Calendar.HOUR_OF_DAY, hours); + } + if (minutes > 0) { + c.add(Calendar.MINUTE, minutes); + } + if (seconds > 0) { + c.add(Calendar.SECOND, seconds); + } + Calendar max = new GregorianCalendar(); + max.add(Calendar.YEAR, 10); + if (c.after(max)) { + return (int) max.getTimeInMillis() / 1000; + } + + if (date.getTime() == c.getTimeInMillis()) { + throw TIME_ARGUMENT_INVALID.create(); + } + + return (int) (c.getTimeInMillis() / 1000); + } + +} diff --git a/src/main/java/io/github/indicode/fabric/itsmine/util/WorldUtil.java b/src/main/java/io/github/indicode/fabric/itsmine/util/WorldUtil.java new file mode 100644 index 0000000..7613530 --- /dev/null +++ b/src/main/java/io/github/indicode/fabric/itsmine/util/WorldUtil.java @@ -0,0 +1,90 @@ +package io.github.indicode.fabric.itsmine.util; + +import com.google.common.collect.Lists; +import io.github.indicode.fabric.itsmine.ClaimManager; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.dimension.DimensionType; + +import java.util.ArrayList; +import java.util.List; + +public class WorldUtil { + + private static MinecraftServer server(){ + return ClaimManager.INSTANCE.server; + } + private static final List> registryKeys = Lists.newArrayList(); + + private static RegistryKey DEFAULT = DimensionType.OVERWORLD_REGISTRY_KEY; + private static DimensionType DEFAULT_DIMENSION = DimensionType.getDefaultDimensionType(); + + public static ServerWorld getServerWorld(DimensionType dimensionType){ + return server().getWorld(getRegistry(dimensionType)); + } + + + public static String getDimensionName(DimensionType dimensionType){ + return getRegistry(dimensionType).getValue().getPath(); + } + + public static String getDimensionNameWithNameSpace(DimensionType dimensionType){ + return getRegistry(dimensionType).getValue().getNamespace() + ":" + getDimensionName(dimensionType); + } + + public static String[] getNameSpaceAndName(String string){ + return string.split(":"); + } + + + public static DimensionType getDimensionType(String dimension){ +/* if(dimension.matches("[a-z_]+:[a-z_]+")){ + System.out.println("Trying to convert " + dimension); + return getDimensionType(getNameSpaceAndName(dimension)[1]); + } else {*/ + for(RegistryKey registryKey : getDimensionKeys()){ + System.out.println(registryKey); + if(dimension.equalsIgnoreCase(registryKey.getValue().getNamespace() + ":" + registryKey.getValue().getPath())){ + DimensionType dimensionType = server().getWorld(registryKey).getDimension(); + return dimensionType; + } else { + } + } + /*}*/ + return DEFAULT_DIMENSION; + } + + public static RegistryKey getRegistry(DimensionType dimensionType){ + for(RegistryKey registryKey : getDimensionKeys()){ + DimensionType dimension = server().getWorld(registryKey).getDimension(); + if(dimension.equals(dimensionType)){ + return registryKey; + } + } + return DEFAULT; + } + +/* public static ArrayList> getRegistries(){ + ArrayList> registryKeys = new ArrayList<>(); + System.out.println("getRegistries"); + server().method_29174().getRegistry().getIds().forEach(identifier -> { + System.out.println("Identfier " + identifier); + registryKeys.add(RegistryKey.of(Registry.DIMENSION_TYPE_KEY, identifier)); + }); + return registryKeys; + }*/ + + public static List> getDimensionKeys() { + return registryKeys; + } + + static { + for (Identifier id : server().method_29174().getRegistry().getIds()) { + registryKeys.add(RegistryKey.of(Registry.DIMENSION_TYPE_KEY, id)); + } + } + +} diff --git a/src/main/resources/assets/modid/icon.png b/src/main/resources/assets/modid/icon.png deleted file mode 100644 index 047b91f..0000000 Binary files a/src/main/resources/assets/modid/icon.png and /dev/null differ diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index c65b390..5e4eba0 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -6,15 +6,15 @@ "name": "Its Mine!", "description": "Land claims.", "authors": [ - "Indicode" + "Indicode", + "CODY_AI", + "Maintained by DrexHD" ], "contact": { - "homepage": "https://fabricmc.net/", - "sources": "https://github.com/FabricMC/fabric-example-mod" + "sources": "https://github.com/GiantNuker/NoGrief/" }, "license": "CC0-1.0", - "icon": "assets/itsmine/icon.png", "environment": "*", "entrypoints": { @@ -27,9 +27,11 @@ ], "depends": { - "fabricloader": ">=0.4.0" + "fabricloader": ">=0.7.1+build.174", + "thimble": "*" }, "suggests": { - "flamingo": "*" + "luckperms": "*", + "thimble": "*" } } diff --git a/src/main/resources/itsmine.mixins.json b/src/main/resources/itsmine.mixins.json index f1db7a0..89a17cb 100644 --- a/src/main/resources/itsmine.mixins.json +++ b/src/main/resources/itsmine.mixins.json @@ -3,8 +3,7 @@ "package": "io.github.indicode.fabric.itsmine.mixin", "compatibilityLevel": "JAVA_8", "mixins": [ - "MinecraftServerMixin", - "WorldSaveHandlerMixin", + "LevelStorageSessionMixin", "CommandManagerMixin", "BlockUpdatePacketMixin", "BucketItemMixin", @@ -13,21 +12,28 @@ "ExplosionMixin", "PlayerEntityMixin", "ServerPlayNetworkHandlerMixin", - "ProjectileEntityMixin", "FluidMixin", "LavaMixin", "PistonBlockMixin", "ServerPlayerInteractionManagerMixin", "PlaceOnUseBlockMixin", "FireBlockMixin", + "AbstractFireBlockMixin", "SpawnRestrictionMixin", - "OwnedProjectile", - + "projectile.OwnedProjectile", + "projectile.ProjectileEntityMixin", + "projectile.TridentEntityMixin", + "projectile.ThrownEggEntityMixin", + "projectile.SnowballEntityMixin", + "projectile.ThrownEnderpearlEntityMixin", + "EnderPearlItemMixin", "StickClaimItemMixin", - "EntityMixin" - ], - "client": [ - "IntegratedServerMixin" + "EntityMixin", + "EnderDragonEntityMixin", + "FarmlandBlockMixin", + "BoatItemMixin", + "ServerCommandOutputMixin", + "MinecraftServerMixin" ], "injectors": { "defaultRequire": 1