Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,36 @@
# against bad commits.

name: build
on: [pull_request, push]

on:
pull_request:
paths: &build_paths
- '.github/workflows/build.yml'
- 'build.gradle'
- 'gradle.properties'
- 'gradle/**'
- 'gradlew'
- 'gradlew.bat'
- 'settings.gradle'
- 'src/**'

push:
branches: [main]
paths: *build_paths

concurrency:
group: "java-build-${{ github.ref }}"
cancel-in-progress: true

jobs:
build:
strategy:
matrix:
# Use these Java versions
java: [
21, # Current Java LTS
25, # Current Java LTS
]
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v4
Expand All @@ -30,8 +49,8 @@ jobs:
- name: build
run: ./gradlew build
- name: capture build artifacts
if: ${{ matrix.java == '21' }} # Only upload artifacts built from latest java
if: ${{ matrix.java == '25' }} # Only upload artefacts built from latest java
uses: actions/upload-artifact@v4
with:
name: Artifacts
path: build/libs/
path: build/libs/
15 changes: 7 additions & 8 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id 'fabric-loom' version "${loom_version}"
id 'net.fabricmc.fabric-loom' version "${loom_version}"
id 'maven-publish'
}

Expand All @@ -21,11 +21,10 @@ repositories {
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"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
implementation "net.fabricmc:fabric-loader:${project.loader_version}"

// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}"

}

Expand All @@ -38,7 +37,7 @@ processResources {
}

tasks.withType(JavaCompile).configureEach {
it.options.release = 21
it.options.release = 25
}

java {
Expand All @@ -47,8 +46,8 @@ java {
// If you remove this line, sources will not be generated.
withSourcesJar()

sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
sourceCompatibility = JavaVersion.VERSION_25
targetCompatibility = JavaVersion.VERSION_25
}

jar {
Expand All @@ -75,4 +74,4 @@ publishing {
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
}
}
}
7 changes: 3 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ org.gradle.parallel=true

# Fabric Properties
# check these on https://fabricmc.net/develop
minecraft_version=1.21.11
yarn_mappings=1.21.11+build.3
minecraft_version=26.1-snapshot-3
loader_version=0.18.4
loom_version=1.14-SNAPSHOT

# Mod Properties
mod_version=1.0.4+1.21.11
mod_version=1.0.5-beta+26.1-snapshots
maven_group=me.imgalvin.playerfinder
archives_base_name=player-finder

# Dependencies
fabric_version=0.140.2+1.21.11
fabric_api_version=0.142.0+26.1
109 changes: 66 additions & 43 deletions src/main/java/me/imgalvin/playerfinder/PlayerFinder.java
Original file line number Diff line number Diff line change
@@ -1,55 +1,78 @@
package me.imgalvin.playerfinder;

import com.mojang.brigadier.arguments.StringArgumentType;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.registry.RegistryKey;
import net.minecraft.server.command.CommandManager;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.ChatFormatting;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.Level;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PlayerFinder implements ModInitializer {
PlayerFinderUtils utils = new PlayerFinderUtils();

public static final Logger LOGGER = LoggerFactory.getLogger("PlayerFinder");

@Override
public void onInitialize() {
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(CommandManager.literal("findplayer")
.then(CommandManager.argument("player", StringArgumentType.string())
.suggests(new PlayerSuggestionProvider())
.executes(context -> {
String playerName = StringArgumentType.getString(context, "player");
PlayerEntity targetPlayer = context.getSource().getServer().getPlayerManager().getPlayer(playerName);
PlayerEntity sourcePlayer = context.getSource().getPlayer();

assert targetPlayer != null;
assert sourcePlayer != null;

BlockPos targetBlockPos = targetPlayer.getBlockPos();
BlockPos sourceBlockPos = sourcePlayer.getBlockPos();
RegistryKey<World> playerDimension = targetPlayer.getEntityWorld().getRegistryKey();
RegistryKey<World> sourceDimension = sourcePlayer.getEntityWorld().getRegistryKey();

boolean isSameDimension = sourceDimension == playerDimension;

context.getSource().sendFeedback(() -> (Text) Text.literal(playerName + " is at ")
.append(Text.literal(targetBlockPos.getX() + ", " + targetBlockPos.getY() + ", " + targetBlockPos.getZ())
.formatted(utils.getDimensionColor(playerDimension)))
.append(Text.literal(" in the ")
.formatted(Formatting.WHITE))
.append(Text.literal(utils.getDimensionText(playerDimension))
.formatted(utils.getDimensionColor(playerDimension)))
.append(Text.literal(isSameDimension
? " (" + utils.getDistance(sourceBlockPos, targetBlockPos) + " blocks away)"
: " (Player is in a different dimension)")
.formatted(isSameDimension ? Formatting.GREEN : Formatting.RED)), false);
return 1;
})
)
);
});
LOGGER.info("PlayerFinder initialized!");
// _ previously registryAccess, environment
CommandRegistrationCallback.EVENT.register((dispatcher, _, _) -> dispatcher.register(Commands.literal("findplayer")
.then(Commands.argument("player", EntityArgument.player())
.executes(context -> {
LOGGER.info("Executing /findplayer command");

ServerPlayer targetPlayerName = EntityArgument.getPlayer(context, "player");
String playerName = targetPlayerName.getGameProfile().name();

ServerPlayer targetPlayer = context.getSource().getServer().getPlayerList().getPlayer(playerName);
ServerPlayer sourcePlayer = context.getSource().getServer().getPlayerList().getPlayer(context.getSource().getTextName());

if (targetPlayer == null) {
context.getSource().sendSystemMessage(Component.literal("[PlayerFinder ERROR] Player " + playerName + " not found").withStyle(ChatFormatting.RED));
return 0;
}
if (sourcePlayer == null) {
context.getSource().sendSystemMessage(Component.literal("[PlayerFinder ERROR] Could not determine command source player").withStyle(ChatFormatting.RED));
return 0;
}

BlockPos targetBlockPos = targetPlayer.blockPosition();
BlockPos sourceBlockPos = sourcePlayer.blockPosition();

LOGGER.info("Target player position: {}", targetBlockPos);
LOGGER.info("Source player position: {}", sourceBlockPos);

ResourceKey<Level> playerDimension = targetPlayer.level().getLevel().dimension();
ResourceKey<Level> sourceDimension = sourcePlayer.level().getLevel().dimension();

LOGGER.info("Target player dimension: {}", playerDimension);
LOGGER.info("Source player dimension: {}", sourceDimension);

boolean isSameDimension = sourceDimension == playerDimension;

Component message = Component.literal(playerName + " is at ")
.append(Component.literal(targetBlockPos.getX() + ", " + targetBlockPos.getY() + ", " + targetBlockPos.getZ())
.withStyle(utils.getDimensionColor(playerDimension)))
.append(Component.literal(" in the ").withStyle(ChatFormatting.WHITE))
.append(Component.literal(utils.getDimensionText(playerDimension))
.withStyle(utils.getDimensionColor(playerDimension)))
.append(Component.literal(isSameDimension
? " (" + utils.getDistance(sourceBlockPos, targetBlockPos) + " blocks away)"
: " (Player is in a different dimension)")
.withStyle(isSameDimension ? ChatFormatting.GREEN : ChatFormatting.RED));

// Send it as a system message to the source
context.getSource().sendSystemMessage(message);

return 1;
})
)
));
}
}
25 changes: 13 additions & 12 deletions src/main/java/me/imgalvin/playerfinder/PlayerFinderUtils.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
package me.imgalvin.playerfinder;

import net.minecraft.registry.RegistryKey;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;

public class PlayerFinderUtils {
public Formatting getDimensionColor(@NotNull RegistryKey<World> playerDimension) {
return playerDimension.equals(World.OVERWORLD) ? Formatting.GREEN :
playerDimension.equals(World.NETHER) ? Formatting.RED :
playerDimension.equals(World.END) ? Formatting.LIGHT_PURPLE :
Formatting.GRAY; // Fallback color for custom or unknown dimensions
public ChatFormatting getDimensionColor(@NotNull ResourceKey<Level> playerDimension) {
return playerDimension.equals(ServerLevel.OVERWORLD) ? ChatFormatting.GREEN :
playerDimension.equals(ServerLevel.NETHER) ? ChatFormatting.RED :
playerDimension.equals(ServerLevel.END) ? ChatFormatting.LIGHT_PURPLE :
ChatFormatting.GRAY; // Fallback colour for custom or unknown dimensions
}

public String getDimensionText(@NotNull RegistryKey<World> playerDimension) {
// note: this function only works for vanilla dimensions. custom dimensions will have a slight issue
return playerDimension.getValue().toString().split(":")[1].replace("the_", "");
public String getDimensionText(@NotNull ResourceKey<Level> playerDimension) {
return playerDimension.identifier().getPath().replace("the_", "");
}

public int getDistance(@NotNull BlockPos playerPos, @NotNull BlockPos targetPos) {
System.out.println("Calculating distance between " + playerPos + " and " + targetPos);
return (int) Math.sqrt(Math.pow(playerPos.getX() - targetPos.getX(), 2) + Math.pow(playerPos.getY() - targetPos.getY(), 2) + Math.pow(playerPos.getZ() - targetPos.getZ(), 2));
}
}

This file was deleted.

4 changes: 2 additions & 2 deletions src/main/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
},
"depends": {
"fabricloader": ">=0.17.3",
"minecraft": "1.21.11",
"java": ">=21",
"minecraft": "26.1-alpha.3",
"java": ">=25",
"fabric-api": ">=0.139.5"
}
}
Loading