diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..b033007 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,39 @@ +name: Build + +on: + push: + branches: + - main + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + name: Build and analyze + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - name: Set up JDK 17 + uses: actions/setup-java@v1 + with: + java-version: 17 + - name: Cache SonarQube packages + uses: actions/cache@v1 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + - name: Cache Gradle packages + uses: actions/cache@v1 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: ${{ runner.os }}-gradle + - name: Build and analyze + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + run: ./gradlew build sonar --info \ No newline at end of file diff --git a/.gitignore b/.gitignore index b36088e..1f22ff1 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,3 @@ run/ img/ # ignore github workflow for now, might use later -.github/ \ No newline at end of file diff --git a/build.gradle b/build.gradle index 15ba42c..f9d2d3b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ plugins { id 'fabric-loom' version '1.5.1' id 'maven-publish' + id "org.sonarqube" version "5.0.0.4638" } sourceCompatibility = JavaVersion.VERSION_17 @@ -82,3 +83,10 @@ publishing { // retrieving dependencies. } } + +sonar { + properties { + property "sonar.projectKey", "PasVegan_teamcmd_74e72b11-6df8-4ab9-aaf3-6260773756be" + property "sonar.projectName", "teamcmd" + } +} diff --git a/gradle.properties b/gradle.properties index d0389b2..31ca3ca 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,8 +8,8 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.15.7 # Mod Properties - mod_version = 1.1.3 - maven_group = io.github.beabfc + mod_version = 2.0.0 + maven_group = io.github.PasVegan archives_base_name = teamcommand # Dependencies diff --git a/src/main/java/io/github/beabfc/teamcmd/CommandBuilder.java b/src/main/java/io/github/PasVegan/teamcmd/CommandBuilder.java similarity index 85% rename from src/main/java/io/github/beabfc/teamcmd/CommandBuilder.java rename to src/main/java/io/github/PasVegan/teamcmd/CommandBuilder.java index c49775a..8cf1b5d 100644 --- a/src/main/java/io/github/beabfc/teamcmd/CommandBuilder.java +++ b/src/main/java/io/github/PasVegan/teamcmd/CommandBuilder.java @@ -1,4 +1,4 @@ -package io.github.beabfc.teamcmd; +package io.github.PasVegan.teamcmd; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.BoolArgumentType; @@ -14,12 +14,15 @@ import net.minecraft.command.argument.EntityArgumentType; import net.minecraft.command.argument.TeamArgumentType; +import net.minecraft.registry.RegistryKey; import net.minecraft.scoreboard.Scoreboard; import net.minecraft.scoreboard.Team; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; import net.minecraft.text.*; import net.minecraft.util.Formatting; +import net.minecraft.world.World; import java.util.Collection; @@ -51,6 +54,8 @@ public class CommandBuilder { new SimpleCommandExceptionType(Text.translatable("commands.teamcmd.fail.not_invited")); private static final SimpleCommandExceptionType DUPLICATE_COLOR = new SimpleCommandExceptionType(Text.translatable("commands.teamcmd.fail.duplicate_color")); + private static final SimpleCommandExceptionType NO_HOME_SET = + new SimpleCommandExceptionType(Text.translatable("commands.teamcmd.fail.tp_to_home")); private static final DynamicCommandExceptionType TEAM_NOT_FOUND = new DynamicCommandExceptionType(option -> Text.translatable("team.notFound", option)); @@ -66,14 +71,16 @@ public static void register(CommandDispatcher dispatcher) { TeamArgumentType.getTeam(ctx, "team"))))) .then(literal("leave").executes(ctx -> executeLeave(ctx.getSource()))) .then(literal("invite").then(argument("player", EntityArgumentType.player()).executes(ctx -> executeInvitePlayer(ctx.getSource(), EntityArgumentType.getPlayer(ctx, "player"))))) - .then(literal("accept").executes(ctx -> executeAcceptInvite(ctx.getSource()))); + .then(literal("accept").executes(ctx -> executeAcceptInvite(ctx.getSource()))) + .then(literal("home").executes(ctx -> executeGoHome(ctx.getSource()))); LiteralArgumentBuilder setCommand = literal("set") .then(literal("color").then(argument("color", ColorArgumentType.color()).executes(ctx -> executeSetColor(ctx.getSource(), ColorArgumentType.getColor(ctx, "color"))))) .then(literal("friendlyFire").then(argument("allowed", BoolArgumentType.bool()).executes(ctx -> executeSetFriendlyFire(ctx.getSource(), BoolArgumentType.getBool(ctx, "allowed"))))) .then(literal("seeInvisibles").then(argument("allowed", BoolArgumentType.bool()).executes(ctx -> executeSetShowFriendlyInvisibles(ctx.getSource(), BoolArgumentType.getBool(ctx, "allowed"))))) - .then(literal("displayName").then(argument("displayName", StringArgumentType.word()).executes(ctx -> executeSetDisplayName(ctx.getSource(), StringArgumentType.getString(ctx, "displayName"))))); + .then(literal("displayName").then(argument("displayName", StringArgumentType.word()).executes(ctx -> executeSetDisplayName(ctx.getSource(), StringArgumentType.getString(ctx, "displayName"))))) + .then(literal("home").executes(ctx -> executeSetHome(ctx.getSource()))); teamCmd.then(setCommand); dispatcher.register(teamCmd); @@ -240,7 +247,11 @@ private static int executeLeave(ServerCommandSource source) throws CommandSyntax TeamUtil.sendToTeammates(player, Text.translatable("commands.teamcmd.teammates.left", player.getDisplayName())); player.getScoreboard().clearPlayerTeam(player.getEntityName()); - if (team.getPlayerList().size() == 0) player.getScoreboard().removeTeam(team); + if (team.getPlayerList().isEmpty()) { + TeamCommand.HOMES.deleteTeamHome(team.getName()); + TeamCommand.HOMES.save("teamhomes.dat"); + player.getScoreboard().removeTeam(team); + } source.sendFeedback(() -> Text.translatable("commands.teamcmd.left", team.getFormattedName()), false); return 1; } @@ -268,6 +279,54 @@ private static int executeListTeams(ServerCommandSource source) { return collection.size(); } + private static int executeSetHome(ServerCommandSource source) throws CommandSyntaxException { + ServerPlayerEntity player = source.getPlayerOrThrow(); + Team team = (Team) player.getScoreboardTeam(); + int dimension; + if (team == null) { + throw NOT_IN_TEAM.create(); + } + + TeamUtil.sendToTeammates(player, Text.translatable("commands.teamcmd.teamates.created_home", + player.getDisplayName())); + RegistryKey dimensionType = player.getWorld().getRegistryKey(); + if (dimensionType.equals(World.OVERWORLD)) { + dimension = 0; + } else if (dimensionType.equals(World.NETHER)) { + dimension = 1; + } else if (dimensionType.equals(World.END)) { + dimension = 2; + } else { + dimension = 0; + } + TeamCommand.HOMES.setHome(team.getName(), player.getPos(), player.getRotationClient(), dimension); + TeamCommand.HOMES.save("teamhomes.dat"); + source.sendFeedback(() -> Text.translatable("commands.teamcmd.created_home"), false); + return 1; + } + + private static int executeGoHome(ServerCommandSource source) throws CommandSyntaxException { + ServerPlayerEntity player = source.getPlayerOrThrow(); + Team team = (Team) player.getScoreboardTeam(); + ServerWorld world; + + if (team == null) { + throw NOT_IN_TEAM.create(); + } + TeamHomes.TeamHome home = TeamCommand.HOMES.getHome(team.getName()); + if (home == null) { + throw NO_HOME_SET.create(); + } + switch (home.dimension) { + case 1 -> world = source.getServer().getWorld(World.NETHER); + case 2 -> world = source.getServer().getWorld(World.END); + default -> world = source.getServer().getWorld(World.OVERWORLD); + } + player.teleport(world, home.posX, home.posY, home.posZ, home.yaw, home.pitch); + source.sendFeedback(() -> Text.translatable("commands.teamcmd.tp_to_home"), false); + return 1; + } + private static boolean duplicateName(Collection teams, String name) { return !TeamCommand.CONFIG.allowDuplicateDisplaynames && teams.stream().anyMatch(other -> other .getDisplayName() diff --git a/src/main/java/io/github/beabfc/teamcmd/Config.java b/src/main/java/io/github/PasVegan/teamcmd/Config.java similarity index 96% rename from src/main/java/io/github/beabfc/teamcmd/Config.java rename to src/main/java/io/github/PasVegan/teamcmd/Config.java index 636e30d..3189d1b 100644 --- a/src/main/java/io/github/beabfc/teamcmd/Config.java +++ b/src/main/java/io/github/PasVegan/teamcmd/Config.java @@ -1,4 +1,4 @@ -package io.github.beabfc.teamcmd; +package io.github.PasVegan.teamcmd; import com.moandjiezana.toml.Toml; import com.moandjiezana.toml.TomlWriter; diff --git a/src/main/java/io/github/beabfc/teamcmd/TeamCommand.java b/src/main/java/io/github/PasVegan/teamcmd/TeamCommand.java similarity index 84% rename from src/main/java/io/github/beabfc/teamcmd/TeamCommand.java rename to src/main/java/io/github/PasVegan/teamcmd/TeamCommand.java index 83e1db8..24c6a7f 100644 --- a/src/main/java/io/github/beabfc/teamcmd/TeamCommand.java +++ b/src/main/java/io/github/PasVegan/teamcmd/TeamCommand.java @@ -1,4 +1,4 @@ -package io.github.beabfc.teamcmd; +package io.github.PasVegan.teamcmd; import net.fabricmc.api.DedicatedServerModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; @@ -6,6 +6,7 @@ public class TeamCommand implements DedicatedServerModInitializer { public static final Config CONFIG = Config.load("teamcommand.toml"); + public static final TeamHomes HOMES = TeamHomes.load("teamhomes.dat"); @Override public void onInitializeServer() { diff --git a/src/main/java/io/github/PasVegan/teamcmd/TeamHomes.java b/src/main/java/io/github/PasVegan/teamcmd/TeamHomes.java new file mode 100644 index 0000000..9524799 --- /dev/null +++ b/src/main/java/io/github/PasVegan/teamcmd/TeamHomes.java @@ -0,0 +1,71 @@ +package io.github.PasVegan.teamcmd; + +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.util.math.Vec2f; +import net.minecraft.util.math.Vec3d; + +import java.io.*; +import java.util.HashMap; + +public class TeamHomes implements Serializable { + private final HashMap homes = new HashMap<>(); + + public static TeamHomes load(String fileName) { + try { + File dataFile = FabricLoader.getInstance().getConfigDir().resolve(fileName).toFile(); + if (dataFile.exists()) { + FileInputStream fileIn = new FileInputStream(dataFile); + ObjectInputStream objectIn = new ObjectInputStream(fileIn); + TeamHomes teamHomes = (TeamHomes) objectIn.readObject(); + objectIn.close(); + fileIn.close(); + return teamHomes; + } else { + return new TeamHomes(); + } + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + public void save(String fileName) { + try { + File dataFile = FabricLoader.getInstance().getConfigDir().resolve(fileName).toFile(); + FileOutputStream fileOut = new FileOutputStream(dataFile); + ObjectOutputStream objectOut = new ObjectOutputStream(fileOut); + objectOut.writeObject(this); + objectOut.close(); + fileOut.close(); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public TeamHome getHome(String teamName) { + return homes.get(teamName); + } + + public void setHome(String teamName, Vec3d position, Vec2f rotation, int dimension) { + TeamHome home = new TeamHome(); + home.posX = position.x; + home.posY = position.y; + home.posZ = position.z; + home.pitch = rotation.x; + home.yaw = rotation.y; + home.dimension = dimension; + homes.put(teamName, home); + } + + public void deleteTeamHome(String teamName) { + homes.remove(teamName); + } + + public static class TeamHome implements Serializable { + public double posX; + public double posY; + public double posZ; + public float yaw; + public float pitch; + public int dimension; + } +} \ No newline at end of file diff --git a/src/main/java/io/github/beabfc/teamcmd/TeamUtil.java b/src/main/java/io/github/PasVegan/teamcmd/TeamUtil.java similarity index 98% rename from src/main/java/io/github/beabfc/teamcmd/TeamUtil.java rename to src/main/java/io/github/PasVegan/teamcmd/TeamUtil.java index ff42e3b..d955495 100644 --- a/src/main/java/io/github/beabfc/teamcmd/TeamUtil.java +++ b/src/main/java/io/github/PasVegan/teamcmd/TeamUtil.java @@ -1,4 +1,4 @@ -package io.github.beabfc.teamcmd; +package io.github.PasVegan.teamcmd; import net.minecraft.scoreboard.Team; import net.minecraft.server.MinecraftServer; @@ -22,7 +22,6 @@ public static void sendToTeammates(ServerPlayerEntity player, Text message) { otherPlayer.sendMessage(message); } } - } public static void addInvite(ServerPlayerEntity player, String teamName) { diff --git a/src/main/resources/data/teamcmd/lang/de_de.json b/src/main/resources/data/teamcmd/lang/de_de.json index 51417c9..333ea9c 100644 --- a/src/main/resources/data/teamcmd/lang/de_de.json +++ b/src/main/resources/data/teamcmd/lang/de_de.json @@ -11,5 +11,9 @@ "commands.teamcmd.left": "Du hast das Team %s verlassen", "commands.teamcmd.teammates.left": "%s hat dein team verlassen", "commands.teamcmd.invite_expired": "Deine Einladung dem Team %s beizutreten ist ausgelaufen", - "commands.teamcmd.fail.duplicate_color": "Ein Team mit dieser Farbe existiert bereits" + "commands.teamcmd.fail.duplicate_color": "Ein Team mit dieser Farbe existiert bereits", + "commands.teamcmd.teamates.created_home": "%s set a new home for your team", + "commands.teamcmd.created_home": "You set a new home for your team", + "commands.teamcmd.tp_to_home": "Teleport to team home", + "commands.teamcmd.fail.tp_to_home": "Your team has no home" } \ No newline at end of file diff --git a/src/main/resources/data/teamcmd/lang/en_us.json b/src/main/resources/data/teamcmd/lang/en_us.json index f8d8824..91988b1 100644 --- a/src/main/resources/data/teamcmd/lang/en_us.json +++ b/src/main/resources/data/teamcmd/lang/en_us.json @@ -11,5 +11,9 @@ "commands.teamcmd.left": "You left the team %s", "commands.teamcmd.teammates.left": "%s left your team", "commands.teamcmd.invite_expired": "Your invite to join the team %s has expired", - "commands.teamcmd.fail.duplicate_color": "A team with this color already exists" + "commands.teamcmd.fail.duplicate_color": "A team with this color already exists", + "commands.teamcmd.teamates.created_home": "%s set a new home for your team", + "commands.teamcmd.created_home": "You set a new home for your team", + "commands.teamcmd.tp_to_home": "Teleport to team home", + "commands.teamcmd.fail.tp_to_home": "Your team has no home" } \ No newline at end of file diff --git a/src/main/resources/data/teamcmd/lang/fr_fr.json b/src/main/resources/data/teamcmd/lang/fr_fr.json new file mode 100644 index 0000000..ee8d7ba --- /dev/null +++ b/src/main/resources/data/teamcmd/lang/fr_fr.json @@ -0,0 +1,19 @@ +{ + "commands.teamcmd.fail.in_team": "Vous êtes déjà dans une équipe", + "commands.teamcmd.fail.no_team": "Vous n'êtes dans aucune équipe", + "commands.teamcmd.fail.already_teammate": "Ce joueur est déjà dans votre équipe", + "commands.teamcmd.fail.not_invited": "Vous n'êtes invité dans aucune équipe", + "commands.teamcmd.invite.success": "%s à été invité a rejoindre votre équipe", + "commands.teamcmd.invite": "%s vous à invité a rejoindre l'équipe %s", + "commands.teamcmd.teammates.invite": "%s à invité %s dans votre équipe", + "commands.teamcmd.joined": "Vous avez rejoint l'équipe %s", + "commands.teamcmd.teammates.joined": "%s à rejoint votre équipe", + "commands.teamcmd.left": "Vous avez quitté l'équipe %s", + "commands.teamcmd.teammates.left": "%s à quitté votre équipe", + "commands.teamcmd.invite_expired": "Votre invitation pour rejoindre l'équipe %s à expiré", + "commands.teamcmd.fail.duplicate_color": "Une équipe avec cette couleur existe déjà", + "commands.teamcmd.teamates.created_home": "%s à défini une nouvelle demeure pour votre équipe", + "commands.teamcmd.created_home": "Vous avez défini une nouvelle demeure pour votre équipe", + "commands.teamcmd.tp_to_home": "Téléportation à la demeure de votre équipe", + "commands.teamcmd.fail.tp_to_home": "Votre équipe n'a pas de demeure" +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 151ff73..04bce61 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -6,11 +6,11 @@ "name": "TeamCommand", "description": "A command for players to create and manage teams. Similar to factions but based on Vanilla scoreboard teams.", "authors": [ - "beabfc" + "PasVegan" ], "contact": { "homepage": "", - "sources": "https://github.com/beabfc/teamcommand" + "sources": "https://github.com/PasVegan/teamcmd" }, "license": "MIT", @@ -19,7 +19,7 @@ "environment": "server", "entrypoints": { "server": [ - "io.github.beabfc.teamcmd.TeamCommand" + "io.github.PasVegan.teamcmd.TeamCommand" ] }, "mixins": [