Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public final class EntitlementResolver {
public static final String KEY_WARDROBE_SLOTS = "wardrobe-skin-slots";
public static final String KEY_MAX_3D_PAIR = "max-3d-pair-bytes";
public static final String KEY_SKIN_COOLDOWN = "skin-token-cooldown-days";
/** Most swappable wardrobe skins per character; the website and RPCharacters use the same cap. */
public static final int MAX_WARDROBE_SKIN_SLOTS = 5;

private EntitlementResolver() {}

Expand Down Expand Up @@ -71,7 +73,7 @@ public static ResolvedMeta resolve(Player player) {
int maxAlive = maxInt(player, Cache.rpcMetaGroups, Cache.rpcMetaDefaults, KEY_MAX_ALIVE);
int wardrobeSlots = Math.max(
1,
Math.min(3, maxInt(player, Cache.rpcMetaGroups, Cache.rpcMetaDefaults, KEY_WARDROBE_SLOTS))
Math.min(MAX_WARDROBE_SKIN_SLOTS, maxInt(player, Cache.rpcMetaGroups, Cache.rpcMetaDefaults, KEY_WARDROBE_SLOTS))
);

int pairBytes = maxInt(player, Cache.skinsMetaGroups, Cache.skinsMetaDefaults, KEY_MAX_3D_PAIR);
Expand Down
14 changes: 10 additions & 4 deletions src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ token-cooldowns:
# armourshop/src/main/resources/permission-groups.yml
# drinkbuilder/src/main/resources/permission-groups.yml
# TFMCWeb only posts values; plugins still own in-game unlock semantics.
# wardrobe-skin-slots is 1 to 5 swappable skins per character (base + Skin 2 … Skin 5).
# Optional per-realm overrides (falls back to top-level rpc/skins/drinks):
# player-meta.by-realm.dev.rpc: { defaults: ..., groups: [...] }
player-meta:
Expand Down Expand Up @@ -72,22 +73,27 @@ player-meta:
tier: 1
name-colour-stops: 1
max-alive-characters: 3
wardrobe-skin-slots: 1
wardrobe-skin-slots: 2
- permission: rpchar.group.gilded
tier: 2
name-colour-stops: 2
max-alive-characters: 4
wardrobe-skin-slots: 2
wardrobe-skin-slots: 3
- permission: rpchar.group.ascended
tier: 3
name-colour-stops: 20
max-alive-characters: 5
wardrobe-skin-slots: 3
wardrobe-skin-slots: 5
- permission: rpchar.group.legacy
tier: 4
name-colour-stops: 20
max-alive-characters: 5
wardrobe-skin-slots: 3
wardrobe-skin-slots: 5
# Staff and helpers (RPCharacters' hidden staff group), on and off duty.
- permission: rpchar.group.staff
tier: 100
max-alive-characters: 8
wardrobe-skin-slots: 5

skins:
defaults:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,22 @@ MetaGroupDefinition group(String permission, int tier, Map<String,Integer> perks
Cache.drinksMetaGroups=Arrays.asList(null,blank,low,high,higher);
Cache.playerMetaSyncPermissions=Arrays.asList(null," "," allowed ","denied");
var meta=EntitlementResolver.resolve(player);
assertEquals(4,meta.nameColourStops);assertEquals(8,meta.maxAliveCharacters);assertEquals(3,meta.wardrobeSkinSlots);assertEquals(60000,meta.max3dPairBytes);
assertEquals(4,meta.nameColourStops);assertEquals(8,meta.maxAliveCharacters);assertEquals(EntitlementResolver.MAX_WARDROBE_SKIN_SLOTS,meta.wardrobeSkinSlots);assertEquals(5,meta.wardrobeSkinSlots);assertEquals(60000,meta.max3dPairBytes);
assertEquals(5,meta.skinTokenCooldownDays);assertEquals(List.of("item","book","armor"),meta.skinKinds);assertTrue(meta.allowArmor3dHelmet && meta.allowDrinkTexture && meta.allowDrinkMessage);
assertEquals(Map.of("allowed",true,"denied",false),meta.permissionFlags);
Cache.skinsMetaGroups=List.of(high); assertEquals(-1,EntitlementResolver.resolve(player).skinTokenCooldownDays); assertFalse(EntitlementResolver.resolve(player).allowArmor3dHelmet);
Cache.drinksMetaGroups=List.of(low);when(player.hasPermission("rank.low")).thenReturn(true);assertFalse(EntitlementResolver.resolve(player).allowDrinkTexture);assertFalse(EntitlementResolver.resolve(player).allowDrinkMessage);
}
@Test void wardrobeSlotsUpToTheCapResolveAsConfigured() {
Cache.rpcMetaDefaults=Map.of(); Cache.skinsMetaDefaults=Map.of(); Cache.drinksMetaDefaults=Map.of();
Cache.skinsMetaGroups=List.of(); Cache.drinksMetaGroups=List.of(); Cache.playerMetaSyncPermissions=List.of();
Cache.rpcMetaGroups=List.of(group("rank.four",2,Map.of("wardrobe-skin-slots",4),null,null,null,null),
group("rank.five",3,Map.of("wardrobe-skin-slots",5),null,null,null,null));
Player four=mock(Player.class); when(four.hasPermission("rank.four")).thenReturn(true);
Player five=mock(Player.class); when(five.hasPermission("rank.five")).thenReturn(true);
assertEquals(4,EntitlementResolver.resolve(four).wardrobeSkinSlots);
assertEquals(5,EntitlementResolver.resolve(five).wardrobeSkinSlots);
}
@Test void syncJsonCopiesValuesAndSkipsBlankKeys() {
UUID id=UUID.randomUUID(); Cache.realmId="dev";
var meta=new EntitlementResolver.ResolvedMeta(3,true,false,8,2,40000,5,List.of(" BOOK "," ","item"),true,Map.of("p\"\\",true,"q",false," ",true));
Expand Down