Skip to content

Commit

Permalink
Config option to chose claim color based on owner instead of hashed l…
Browse files Browse the repository at this point in the history
…ocation (#52)

* configurable per-player claim color

* add command to update color on dynmap after coloring strategy was switched: `/goml admin updateallclaims`

* update README: document `claimColorSource` config option

---------

Co-authored-by: Jonas Maier <>
  • Loading branch information
JM4ier committed Jul 21, 2024
1 parent 11fe5d7 commit 7f6e87f
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 13 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ You can find config file in `./config/getoffmylawn.json`. To reload it, just typ
"placeholderNoClaimOwners": "<gray><italic>Nobody",
"placeholderNoClaimTrusted": "<gray><italic>Nobody",
"placeholderClaimCanBuildInfo": "${owners} <gray>(<green>${anchor}</green>)",
"placeholderClaimCantBuildInfo": "${owners} <gray>(<red>${anchor}</red>)"
"placeholderClaimCantBuildInfo": "${owners} <gray>(<red>${anchor}</red>)",
"claimColorSource": "location" // either "location" or "player" - "location" will chose the color based on the location of the claim (hash of coordinates), "player" will chose the color based on the owner of the claim (hash of UUID).
}
```

Expand Down
47 changes: 47 additions & 0 deletions src/main/java/draylar/goml/api/ClaimUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import draylar.goml.other.StatusEnum;
import draylar.goml.registry.GOMLBlocks;
import me.lucko.fabric.api.permissions.v0.Permissions;
import net.minecraft.block.BlockState;
import net.minecraft.entity.AreaEffectCloudEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.damage.DamageSource;
Expand All @@ -21,6 +22,7 @@
import net.minecraft.entity.passive.TameableEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.registry.Registries;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
Expand All @@ -35,6 +37,7 @@
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.stream.Collectors;

public class ClaimUtils {

Expand Down Expand Up @@ -121,6 +124,10 @@ public static Selection<Entry<ClaimBox, Claim>> getClaimsInOpenBox(WorldView wor
return GetOffMyLawn.CLAIM.get(world).getClaims().entries(box -> box.intersectsOpen(checkBox));
}

public static Selection<Entry<ClaimBox, Claim>> getClaimsInDimension(WorldView world) {
return GetOffMyLawn.CLAIM.get(world).getClaims().entries(a -> true);
}

public static Box createBox(int x1, int y1, int z1, int x2, int y2, int z2) {
return Box.create(Math.min(x1, x2), Math.min(y1, y2), Math.min(z1, z2), Math.max(x1, x2), Math.max(y1, y2), Math.max(z1, z2));
}
Expand Down Expand Up @@ -465,4 +472,44 @@ public static boolean hasMatchingClaims(World world, BlockPos target, BlockPos o
return claims.anyMatch(x -> x.getValue().hasPermission(trusted));

}

private static int claimColorIndex(Claim claim) {
int hash = 0;

if (GetOffMyLawn.CONFIG.usePlayerForColor()) {
// get lexicographically smallest UUID because set order is not stable
UUID min = null;

for (UUID id : claim.getOwners()) {
if (min == null || id.compareTo(min) < 0) {
min = id;
}
}

if (min != null) {
hash = min.hashCode();
}
} else {
hash = claim.getOrigin().hashCode();
}

return hash & 0xF;
}

// From https://lospec.com/palette-list/minecraft-concrete (matches block order so matches goggles).
private static final int[] CLAIM_COLORS_RGB = new int[]{0xcfd5d6, 0xe06101, 0xa9309f, 0x2489c7, 0xf1af15, 0x5ea918, 0xd5658f, 0x373a3e, 0x7d7d73, 0x157788, 0x64209c, 0x2d2f8f, 0x603c20, 0x495b24, 0x8e2121, 0x080a0f};

private static final BlockState[] CLAIM_COLORS_BLOCKS = Registries.BLOCK.stream().filter((b) -> {
var id = Registries.BLOCK.getId(b);

return id.getNamespace().equals("minecraft") && id.getPath().endsWith("_concrete");
}).map((b) -> b.getDefaultState()).collect(Collectors.toList()).toArray(new BlockState[0]);

public static int dynmapClaimColor(Claim claim) {
return CLAIM_COLORS_RGB[claimColorIndex(claim)];
}

public static BlockState gogglesClaimColor(Claim claim) {
return CLAIM_COLORS_BLOCKS[claimColorIndex(claim)];
}
}
8 changes: 3 additions & 5 deletions src/main/java/draylar/goml/compat/DynmapCompat.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@
public class DynmapCompat {
private static final String gomlMarkerSetId = "gomlMarkerSet";

// From https://lospec.com/palette-list/minecraft-concrete (matches block order so matches goggles).
private static final int[] COLORS = new int[]{0xcfd5d6, 0xe06101, 0xa9309f, 0x2489c7, 0xf1af15, 0x5ea918, 0xd5658f, 0x373a3e, 0x7d7d73, 0x157788, 0x64209c, 0x2d2f8f, 0x603c20, 0x495b24, 0x8e2121, 0x080a0f};

public static void init(final MinecraftServer server) {
DynmapCommonAPIListener.register(new DynmapCommonAPIListener() {
@Override
Expand Down Expand Up @@ -60,7 +57,7 @@ private static void renderClaimArea(Claim claim, MinecraftServer server, MarkerA
ClaimCorners corners = getClaimCorners(claim);
AreaMarker marker = markerApi.getMarkerSet(gomlMarkerSetId).createAreaMarker(getClaimId(claim), getClaimLabel(claim, server), true, worldName, corners.x, corners.z, true);
// marker.setRangeY(corners.y[0], corners.y[1]);
int color = COLORS[(claim.getOrigin().hashCode() & 0xFFFF) % COLORS.length];
int color = ClaimUtils.dynmapClaimColor(claim);
marker.setFillStyle(0.25, color);
marker.setLineStyle(2, 1, color);
}
Expand All @@ -71,7 +68,8 @@ private static void resizeClaimArea(Claim claim, MinecraftServer server, MarkerA
}

private static void updateClaimArea(Claim claim, MinecraftServer server, MarkerAPI markerApi) {
handleClaimAreaUpdate(claim, server, markerApi, claimArea -> claimArea.setLabel(getClaimLabel(claim, server), true));
deleteClaimArea(claim, markerApi);
renderClaimArea(claim, server, markerApi);
}

private static void deleteClaimArea(Claim claim, MarkerAPI markerApi) {
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/draylar/goml/config/GOMLConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ public class GOMLConfig {
public WrappedText placeholderClaimCanBuildInfo = WrappedText.of("${owners} <gray>(<green>${anchor}</green>)");
public WrappedText placeholderClaimCantBuildInfo = WrappedText.of("${owners} <gray>(<red>${anchor}</red>)");

public String claimColorSource = "location";

public boolean canInteract(Block block) {
return this.allowedBlockInteraction.contains(block);
}
Expand All @@ -85,6 +87,14 @@ public boolean isBlacklisted(World world, Box claimBox) {
return false;
}

public boolean useLocationForColor() {
return !usePlayerForColor();
}

public boolean usePlayerForColor() {
return "player".equalsIgnoreCase(claimColorSource);
}

public MutableText prefix(Text text) {
return Text.empty().append(messagePrefix.text()).append(Text.literal(" ")).append(text);
}
Expand Down
10 changes: 3 additions & 7 deletions src/main/java/draylar/goml/item/GogglesItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@
import java.util.stream.Collectors;

public class GogglesItem extends ArmorItem implements PolymerItem {
private static final BlockState[] STATES = Registries.BLOCK.stream().filter((b) -> {
var id = Registries.BLOCK.getId(b);

return id.getNamespace().equals("minecraft") && id.getPath().endsWith("_concrete");
}).map((b) -> b.getDefaultState()).collect(Collectors.toList()).toArray(new BlockState[0]);

public GogglesItem() {
super(ArmorMaterials.IRON, Type.HELMET, new Item.Settings().maxDamage(-1));
}
Expand All @@ -47,9 +41,11 @@ public void inventoryTick(ItemStack stack, World world, Entity entity, int slot,
var minPos = new BlockPos(box.x1(), Math.max(box.y1(), world.getBottomY()), box.z1());
var maxPos = new BlockPos(box.x2() - 1, Math.min(box.y2() - 1, world.getTopY()), box.z2() - 1);

BlockState state = ClaimUtils.gogglesClaimColor(claim.getValue());

WorldParticleUtils.render(player, minPos, maxPos,
//new DustParticleEffect(new Vec3f(0.8f, 0.8f, 0.8f), 2)
new BlockStateParticleEffect(ParticleTypes.BLOCK_MARKER, STATES[(claim.getValue().getOrigin().hashCode() & 0xFFFF) % STATES.length])
new BlockStateParticleEffect(ParticleTypes.BLOCK_MARKER, state)
);
});
}
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/draylar/goml/other/ClaimCommand.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package draylar.goml.other;

import java.security.Permission;

import com.jamieswhiteshirt.rtree3i.RTreeMap;
import com.mojang.authlib.GameProfile;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;

import draylar.goml.GetOffMyLawn;
import draylar.goml.api.Claim;
import draylar.goml.api.ClaimBox;
import draylar.goml.api.ClaimUtils;
import draylar.goml.api.DataKey;
import draylar.goml.api.event.ClaimEvents;
import draylar.goml.config.GOMLConfig;
import draylar.goml.registry.GOMLEntities;
import draylar.goml.ui.ClaimListGui;
Expand All @@ -32,6 +36,7 @@
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.Heightmap;

import org.jetbrains.annotations.ApiStatus;

import java.util.ArrayList;
Expand Down Expand Up @@ -143,6 +148,10 @@ public static void init() {
})
)
)
.then(literal("updateallclaims")
.requires(Permissions.require("goml.command.command.admin.updateallclaims", 4))
.executes(ClaimCommand::updateAllClaims)
)
)
);
});
Expand Down Expand Up @@ -485,6 +494,15 @@ private static int reload(CommandContext<ServerCommandSource> context) {
return 1;
}

private static int updateAllClaims(CommandContext<ServerCommandSource> context) {
ServerWorld world = context.getSource().getWorld();
ClaimUtils.getClaimsInDimension(world).forEach(claim -> {
ClaimEvents.CLAIM_UPDATED.invoker().onEvent(claim.getValue());
});
context.getSource().sendFeedback(() -> prefix(Text.literal("Updated all claims")), false);
return 1;
}

private static void bumpChat(ServerPlayerEntity player) {
player.sendMessage(Text.literal(" "), false);
}
Expand Down

0 comments on commit 7f6e87f

Please sign in to comment.