mirror of
https://github.com/array-in-a-matrix/brainwine.git
synced 2025-04-02 11:11:58 -04:00
Player appearance rework
This commit is contained in:
parent
c5ff0ba62e
commit
39f75f8322
11 changed files with 254 additions and 158 deletions
|
@ -30,6 +30,7 @@ public class EntityConfig {
|
|||
private float maxHealth = Entity.DEFAULT_HEALTH;
|
||||
private float baseSpeed = 3;
|
||||
private boolean character;
|
||||
private boolean human;
|
||||
private boolean named;
|
||||
private Vector2i size = new Vector2i(1, 1);
|
||||
private EntityGroup group = EntityGroup.NONE;
|
||||
|
@ -85,6 +86,10 @@ public class EntityConfig {
|
|||
return character;
|
||||
}
|
||||
|
||||
public boolean isHuman() {
|
||||
return human;
|
||||
}
|
||||
|
||||
public boolean isNamed() {
|
||||
return named;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import brainwine.gameserver.entity.EntityLoot;
|
|||
import brainwine.gameserver.entity.EntityRegistry;
|
||||
import brainwine.gameserver.entity.FacingDirection;
|
||||
import brainwine.gameserver.entity.npc.behavior.SequenceBehavior;
|
||||
import brainwine.gameserver.entity.player.Appearance;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.item.DamageType;
|
||||
import brainwine.gameserver.item.Item;
|
||||
|
@ -104,6 +105,11 @@ public class Npc extends Entity {
|
|||
this.name = Naming.getRandomEntityName();
|
||||
}
|
||||
|
||||
// Generate random appearance
|
||||
if(config.isHuman()) {
|
||||
properties.putAll(Appearance.getRandomAppearance());
|
||||
}
|
||||
|
||||
this.config = config;
|
||||
this.typeName = config.getName();
|
||||
this.type = config.getType();
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
package brainwine.gameserver.entity.player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import brainwine.gameserver.GameConfiguration;
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.item.ItemRegistry;
|
||||
import brainwine.gameserver.util.MapHelper;
|
||||
|
||||
/**
|
||||
* Utility class for player appearance related stuff.
|
||||
* Ghosts also have a random appearance, which is why it's here instead of in the player class.
|
||||
*/
|
||||
public class Appearance {
|
||||
|
||||
public static Map<String, Object> getRandomAppearance() {
|
||||
return getRandomAppearance(null);
|
||||
}
|
||||
|
||||
public static Map<String, Object> getRandomAppearance(Player player) {
|
||||
Map<String, Object> appearance = new HashMap<>();
|
||||
|
||||
for(AppearanceSlot slot : AppearanceSlot.values()) {
|
||||
// Skip if slot cannot be changed by players
|
||||
if(!slot.isChangeable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String category = slot.getCategory();
|
||||
|
||||
// Color handling
|
||||
if(slot.isColor()) {
|
||||
List<String> colors = getAvailableColors(slot, player);
|
||||
|
||||
// Change appearance to random color
|
||||
if(!colors.isEmpty()) {
|
||||
appearance.put(slot.getId(), colors.get((int)(Math.random() * colors.size())));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fetch list of items in this slot's category that the player owns
|
||||
List<Item> items = ItemRegistry.getItemsByCategory(category).stream()
|
||||
.filter(item -> item.isBase() || (player != null && player.getInventory().hasItem(item)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// Change appearance to random clothing item
|
||||
if(!items.isEmpty()) {
|
||||
appearance.put(slot.getId(), items.get((int)(Math.random() * items.size())).getCode());
|
||||
}
|
||||
}
|
||||
|
||||
return appearance;
|
||||
}
|
||||
|
||||
public static List<String> getAvailableColors(AppearanceSlot slot) {
|
||||
return getAvailableColors(null);
|
||||
}
|
||||
|
||||
public static List<String> getAvailableColors(AppearanceSlot slot, Player player) {
|
||||
List<String> colors = new ArrayList<>();
|
||||
|
||||
// Return empty list if slot is not valid
|
||||
if(!slot.isColor()) {
|
||||
return colors;
|
||||
}
|
||||
|
||||
Map<String, Object> wardrobe = MapHelper.getMap(GameConfiguration.getBaseConfig(), "wardrobe", Collections.emptyMap());
|
||||
String category = slot.getCategory();
|
||||
|
||||
// Add base colors
|
||||
colors.addAll(MapHelper.getList(wardrobe, category, Collections.emptyList()));
|
||||
|
||||
// Add bonus colors
|
||||
if(player != null && player.getInventory().hasItem(ItemRegistry.getItem("accessories/makeup"))) {
|
||||
colors.addAll(MapHelper.getList(wardrobe, String.format("%s-bonus", category), Collections.emptyList()));
|
||||
}
|
||||
|
||||
return colors;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package brainwine.gameserver.entity.player;
|
||||
|
||||
public enum AppearanceSlot {
|
||||
|
||||
SKIN_COLOR("c*", "skin-color", true),
|
||||
HAIR_COLOR("h*", "hair-color", true),
|
||||
HAIR("h", "hair", true),
|
||||
FACIAL_HAIR("fh", "facialhair", true),
|
||||
TOPS("t", "tops", true),
|
||||
BOTTOMS("b", "bottoms", true),
|
||||
FOOTWEAR("fw", "footwear", true),
|
||||
HEADGEAR("hg", "headgear", true),
|
||||
FACIAL_GEAR("fg", "facialgear", true),
|
||||
FACIAL_GEAR_GLOW("fg*", "facialgear-glow"),
|
||||
SUIT("u", "suit"),
|
||||
TOPS_OVERLAY("to", "tops-overlay"),
|
||||
TOPS_OVERLAY_GLOW("to*", "tops-overlay-glow"),
|
||||
ARMS_OVERLAY("ao", "arms-overlay"),
|
||||
LEGS_OVERLAY("lo", "legs-overlay"),
|
||||
FOOTWEAR_OVERLAY("fo", "footwear-overlay");
|
||||
|
||||
private final String id;
|
||||
private final String category;
|
||||
private final boolean changeable;
|
||||
|
||||
private AppearanceSlot(String id, String category) {
|
||||
this(id, category, false);
|
||||
}
|
||||
|
||||
private AppearanceSlot(String id, String category, boolean changeable) {
|
||||
this.id = id;
|
||||
this.category = category;
|
||||
this.changeable = changeable;
|
||||
}
|
||||
|
||||
public static AppearanceSlot fromId(String id) {
|
||||
for(AppearanceSlot value : values()) {
|
||||
if(value.getId().equals(id)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public boolean isChangeable() {
|
||||
return changeable;
|
||||
}
|
||||
|
||||
public boolean isColor() {
|
||||
return id.endsWith("*");
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package brainwine.gameserver.entity.player;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
public enum ClothingSlot {
|
||||
|
||||
HAIR("h"),
|
||||
FACIAL_HAIR("fh"),
|
||||
TOPS("t"),
|
||||
BOTTOMS("b"),
|
||||
FOOTWEAR("fw"),
|
||||
HEADGEAR("hg"),
|
||||
FACIAL_GEAR("fg"),
|
||||
SUIT("u"),
|
||||
TOPS_OVERLAY("to"),
|
||||
ARMS_OVERLAY("ao"),
|
||||
LEGS_OVERLAY("lo"),
|
||||
FOOTWEAR_OVERLAY("fo");
|
||||
|
||||
private final String id;
|
||||
|
||||
private ClothingSlot(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public static ClothingSlot fromId(String id) {
|
||||
for(ClothingSlot value : values()) {
|
||||
if(value.getId().equals(id)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package brainwine.gameserver.entity.player;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
public enum ColorSlot {
|
||||
|
||||
SKIN_COLOR("c*"),
|
||||
HAIR_COLOR("h*");
|
||||
|
||||
private final String id;
|
||||
|
||||
private ColorSlot(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public static ColorSlot fromId(String id) {
|
||||
for(ColorSlot value : values()) {
|
||||
if(value.getId().equals(id)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -10,7 +10,6 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -103,8 +102,7 @@ public class Player extends Entity implements CommandExecutor {
|
|||
private Map<String, Float> ignoredHints;
|
||||
private Map<Skill, Integer> skills;
|
||||
private Map<Item, List<Skill>> bumpedSkills;
|
||||
private Map<ClothingSlot, Item> equippedClothing;
|
||||
private Map<ColorSlot, String> equippedColors;
|
||||
private Map<String, Object> appearance;
|
||||
private final Map<String, Object> settings = new HashMap<>();
|
||||
private final Set<Integer> activeChunks = new HashSet<>();
|
||||
private final Map<Integer, Consumer<Object[]>> dialogs = new HashMap<>();
|
||||
|
@ -147,8 +145,7 @@ public class Player extends Entity implements CommandExecutor {
|
|||
this.ignoredHints = config.getIgnoredHints();
|
||||
this.skills = config.getSkills();
|
||||
this.bumpedSkills = config.getBumpedSkills();
|
||||
this.equippedClothing = config.getEquippedClothing();
|
||||
this.equippedColors = config.getEquippedColors();
|
||||
this.appearance = config.getAppearance();
|
||||
health = getMaxHealth();
|
||||
inventory.setPlayer(this);
|
||||
statistics.setPlayer(this);
|
||||
|
@ -169,8 +166,7 @@ public class Player extends Entity implements CommandExecutor {
|
|||
this.ignoredHints = new HashMap<>();
|
||||
this.skills = new HashMap<>();
|
||||
this.bumpedSkills = new HashMap<>();
|
||||
this.equippedClothing = new HashMap<>();
|
||||
this.equippedColors = new HashMap<>();
|
||||
this.appearance = Appearance.getRandomAppearance();
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
|
@ -271,7 +267,8 @@ public class Player extends Entity implements CommandExecutor {
|
|||
public Map<String, Object> getStatusConfig() {
|
||||
Map<String, Object> config = super.getStatusConfig();
|
||||
config.put("id", documentId);
|
||||
config.putAll(getAppearanceConfig());
|
||||
config.putAll(appearance);
|
||||
config.put("u", inventory.findJetpack().getCode());
|
||||
return config;
|
||||
}
|
||||
|
||||
|
@ -1061,27 +1058,18 @@ public class Player extends Entity implements CommandExecutor {
|
|||
return Collections.unmodifiableSet(achievements);
|
||||
}
|
||||
|
||||
public void setClothing(ClothingSlot slot, Item item) {
|
||||
if(!item.isClothing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
equippedClothing.put(slot, item);
|
||||
zone.sendMessage(new EntityChangeMessage(id, getAppearanceConfig()));
|
||||
public void randomizeAppearance() {
|
||||
appearance.putAll(Appearance.getRandomAppearance(this));
|
||||
zone.sendMessage(new EntityChangeMessage(id, appearance));
|
||||
}
|
||||
|
||||
public Map<ClothingSlot, Item> getEquippedClothing() {
|
||||
return Collections.unmodifiableMap(equippedClothing);
|
||||
public void updateAppearance(Map<String, Object> appearance) {
|
||||
this.appearance = appearance;
|
||||
zone.sendMessage(new EntityChangeMessage(id, appearance));
|
||||
}
|
||||
|
||||
public void setColor(ColorSlot slot, String hex) {
|
||||
// TODO check if the string is actually a valid hex color
|
||||
equippedColors.put(slot, hex);
|
||||
zone.sendMessage(new EntityChangeMessage(id, getAppearanceConfig()));
|
||||
}
|
||||
|
||||
public Map<ColorSlot, String> getEquippedColors() {
|
||||
return Collections.unmodifiableMap(equippedColors);
|
||||
public Map<String, Object> getAppearance() {
|
||||
return Collections.unmodifiableMap(appearance);
|
||||
}
|
||||
|
||||
public void setSkillLevel(Skill skill, int level) {
|
||||
|
@ -1309,21 +1297,6 @@ public class Player extends Entity implements CommandExecutor {
|
|||
return connection != null && connection.isOpen();
|
||||
}
|
||||
|
||||
private Map<String, Object> getAppearanceConfig() {
|
||||
Map<String, Object> appearance = new HashMap<>();
|
||||
|
||||
for(Entry<ClothingSlot, Item> entry : equippedClothing.entrySet()) {
|
||||
appearance.put(entry.getKey().getId(), entry.getValue().getCode());
|
||||
}
|
||||
|
||||
for(Entry<ColorSlot, String> entry : equippedColors.entrySet()) {
|
||||
appearance.put(entry.getKey().getId(), entry.getValue());
|
||||
}
|
||||
|
||||
appearance.put(ClothingSlot.SUIT.getId(), inventory.findJetpack().getCode()); // Jetpack
|
||||
return appearance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A {@link Map} containing all the data necessary for use in {@link ConfigurationMessage}.
|
||||
*/
|
||||
|
@ -1345,7 +1318,7 @@ public class Player extends Entity implements CommandExecutor {
|
|||
config.put("items_crafted", statistics.getTotalItemsCrafted());
|
||||
config.put("play_time", (int)(statistics.getPlayTime()));
|
||||
config.put("deaths", statistics.getDeaths());
|
||||
config.put("appearance", getAppearanceConfig());
|
||||
config.put("appearance", appearance);
|
||||
config.put("settings", settings);
|
||||
return config;
|
||||
}
|
||||
|
|
|
@ -39,8 +39,7 @@ public class PlayerConfigFile {
|
|||
private Map<String, Float> ignoredHints = new HashMap<>();
|
||||
private Map<Skill, Integer> skills = new HashMap<>();
|
||||
private Map<Item, List<Skill>> bumpedSkills = new HashMap<>();
|
||||
private Map<ClothingSlot, Item> equippedClothing = new HashMap<>();
|
||||
private Map<ColorSlot, String> equippedColors = new HashMap<>();
|
||||
private Map<String, Object> appearance = new HashMap<>();
|
||||
|
||||
public PlayerConfigFile(Player player) {
|
||||
this.name = player.getName();
|
||||
|
@ -63,8 +62,7 @@ public class PlayerConfigFile {
|
|||
this.ignoredHints = player.getIgnoredHints();
|
||||
this.skills = player.getSkills();
|
||||
this.bumpedSkills = player.getBumpedSkills();
|
||||
this.equippedClothing = player.getEquippedClothing();
|
||||
this.equippedColors = player.getEquippedColors();
|
||||
this.appearance = player.getAppearance();
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
|
@ -163,12 +161,7 @@ public class PlayerConfigFile {
|
|||
}
|
||||
|
||||
@JsonSetter(nulls = Nulls.SKIP, contentNulls = Nulls.SKIP)
|
||||
public Map<ClothingSlot, Item> getEquippedClothing() {
|
||||
return equippedClothing;
|
||||
}
|
||||
|
||||
@JsonSetter(nulls = Nulls.SKIP, contentNulls = Nulls.SKIP)
|
||||
public Map<ColorSlot, String> getEquippedColors() {
|
||||
return equippedColors;
|
||||
public Map<String, Object> getAppearance() {
|
||||
return appearance;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@ public class Item {
|
|||
@JsonProperty("code")
|
||||
private int code;
|
||||
|
||||
@JsonProperty("category")
|
||||
private String category;
|
||||
|
||||
@JsonProperty("title")
|
||||
private String title;
|
||||
|
||||
|
@ -237,6 +240,15 @@ public class Item {
|
|||
return code;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
if(category != null) {
|
||||
return category;
|
||||
}
|
||||
|
||||
int index = id.indexOf('/');
|
||||
return index > 1 ? id.substring(0, index) : null;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,11 @@ package brainwine.gameserver.item;
|
|||
|
||||
import static brainwine.shared.LogMarkers.SERVER_MARKER;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
@ -15,6 +17,7 @@ public class ItemRegistry {
|
|||
private static final Logger logger = LogManager.getLogger();
|
||||
private static final Map<String, Item> items = new HashMap<>();
|
||||
private static final Map<Integer, Item> itemsByCode = new HashMap<>();
|
||||
private static final Map<String, List<Item>> itemsByCategory = new HashMap<>();
|
||||
|
||||
// TODO maybe just move the registry stuff here
|
||||
public static void clear() {
|
||||
|
@ -36,6 +39,15 @@ public class ItemRegistry {
|
|||
return false;
|
||||
}
|
||||
|
||||
String category = item.getCategory();
|
||||
List<Item> categorizedItems = itemsByCategory.get(category);
|
||||
|
||||
if(categorizedItems == null) {
|
||||
categorizedItems = new ArrayList<>();
|
||||
itemsByCategory.put(category, categorizedItems);
|
||||
}
|
||||
|
||||
categorizedItems.add(item);
|
||||
items.put(id, item);
|
||||
itemsByCode.put(code, item);
|
||||
return true;
|
||||
|
@ -52,4 +64,8 @@ public class ItemRegistry {
|
|||
public static Collection<Item> getItems() {
|
||||
return Collections.unmodifiableCollection(items.values());
|
||||
}
|
||||
|
||||
public static List<Item> getItemsByCategory(String category) {
|
||||
return Collections.unmodifiableList(itemsByCategory.getOrDefault(category, Collections.emptyList()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,29 +5,28 @@ import java.util.Map.Entry;
|
|||
|
||||
import brainwine.gameserver.annotations.RequestInfo;
|
||||
import brainwine.gameserver.dialog.DialogHelper;
|
||||
import brainwine.gameserver.entity.player.ClothingSlot;
|
||||
import brainwine.gameserver.entity.player.ColorSlot;
|
||||
import brainwine.gameserver.entity.player.Appearance;
|
||||
import brainwine.gameserver.entity.player.AppearanceSlot;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.item.ItemRegistry;
|
||||
import brainwine.gameserver.server.PlayerRequest;
|
||||
import brainwine.gameserver.server.messages.EntityChangeMessage;
|
||||
import brainwine.gameserver.util.MapHelper;
|
||||
|
||||
/**
|
||||
* TODO we should actually check if the sent value is even compatible with the slot.
|
||||
* We wouldn't want to allow players to equip pants for hats!
|
||||
*/
|
||||
@RequestInfo(id = 22)
|
||||
public class ChangeAppearanceRequest extends PlayerRequest {
|
||||
|
||||
public Map<String, Object> data;
|
||||
public Map<String, Object> appearance;
|
||||
|
||||
@Override
|
||||
public void process(Player player) {
|
||||
if(data.containsKey("meta")) {
|
||||
String meta = "" + data.get("meta");
|
||||
// Handle special cases
|
||||
if(appearance.containsKey("meta")) {
|
||||
String meta = MapHelper.getString(appearance, "meta", "");
|
||||
|
||||
if(meta.equals("randomize")) {
|
||||
player.notify("Sorry, you can't randomize your appearance yet.");
|
||||
player.randomizeAppearance();
|
||||
} else {
|
||||
player.showDialog(DialogHelper.getWardrobeDialog(meta));
|
||||
}
|
||||
|
@ -35,36 +34,54 @@ public class ChangeAppearanceRequest extends PlayerRequest {
|
|||
return;
|
||||
}
|
||||
|
||||
for(Entry<String, Object> entry : data.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
// Validate appearance data
|
||||
for(Entry<String, Object> entry : appearance.entrySet()) {
|
||||
AppearanceSlot slot = AppearanceSlot.fromId(entry.getKey());
|
||||
Object value = entry.getValue();
|
||||
|
||||
if(value instanceof Integer) {
|
||||
ClothingSlot slot = ClothingSlot.fromId(key);
|
||||
|
||||
if(slot == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Item item = ItemRegistry.getItem((int)value);
|
||||
|
||||
if(!item.isBase() && !player.getInventory().hasItem(item)) {
|
||||
player.notify("Sorry, but you do not own this.");
|
||||
// Fail if slot is not valid
|
||||
if(slot == null || !slot.isChangeable()) {
|
||||
fail(player);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle color data
|
||||
if(slot.isColor()) {
|
||||
// Fail if color value is not a string
|
||||
if(!(value instanceof String)) {
|
||||
fail(player);
|
||||
return;
|
||||
}
|
||||
|
||||
player.setClothing(slot, item);
|
||||
} else if(value instanceof String) {
|
||||
// TODO check if player owns color
|
||||
ColorSlot slot = ColorSlot.fromId(key);
|
||||
String color = (String)value;
|
||||
|
||||
if(slot == null) {
|
||||
continue;
|
||||
// Fail if player doesn't own color
|
||||
if(!Appearance.getAvailableColors(slot, player).contains((String)value)) {
|
||||
fail(player);
|
||||
return;
|
||||
}
|
||||
|
||||
player.setColor(slot, color);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fail if item value is not an integer (item code)
|
||||
if(!(value instanceof Integer)) {
|
||||
fail(player);
|
||||
return;
|
||||
}
|
||||
|
||||
Item item = ItemRegistry.getItem((int)value);
|
||||
|
||||
// Do nothing if item isn't valid clothing or player doesn't own it
|
||||
if(!item.isClothing() || !slot.getCategory().equals(item.getCategory()) || (!item.isBase() && !player.getInventory().hasItem(item))) {
|
||||
fail(player);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Update player appearance
|
||||
player.updateAppearance(appearance);
|
||||
}
|
||||
|
||||
private void fail(Player player) {
|
||||
player.sendMessage(new EntityChangeMessage(player.getId(), player.getAppearance()));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue