package cactusServer.entities; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import cactusServer.models.Instances; import cactusServer.utils.RandomStringGenerator; import framework.model3D.Position3D; import net.arnx.jsonic.JSONHint; public class Character extends Entity { private String accountURI; private String name; private Position3D position; private Angle angle; private CharacterModel model; private String areaURI; private HashMap<String, Item> itemMap = new HashMap<>(); @JSONHint(ignore = true) public static final int UNIQUE_ID_LENGTH = 12; private Character() { // JSONDecode時の呼び出し用 } public Character(String accountURI, String name, Position3D position, Angle angle, CharacterModel model) { setAccountURI(accountURI); setName(name); setPosition(position); setAngle(angle); setModel(model); updateAreaURI(); } public Character(String instanceId, String accountURI, String name, Position3D position, Angle angle, CharacterModel model) { setAccountURI(accountURI); setName(name); setPosition(position); setAngle(angle); setModel(model); updateAreaURI(); } public String getAccountURI() { return accountURI; } public String getName() { return name; } public Position3D getPosition() { return position; } public Angle getAngle() { return angle; } public CharacterModel getModel() { return model; } public String getAreaURI() { return areaURI; } @JSONHint(ignore = true) public Item getItem(String itemId) { return itemMap.get(itemId); } @JSONHint(ignore = true) public List<Item> getItems() { List<Item> itemList = new ArrayList<>(); for (Item item : itemMap.values()) { itemList.add(item); } return itemList; } public void setAccountURI(String accountURI) { this.accountURI = accountURI; } public void setName(String name) { this.name = name; } public void setPosition(Position3D position) { this.position = position; } public void setAngle(Angle angle) { this.angle = angle; } public void setModel(CharacterModel model) { this.model = model; } public void setAreaURI(String areaURI) { this.areaURI = areaURI; } public AddressedEntity createItem(String name, int amount) { Item item = new Item(name, amount); if (!hasItem(item)) { String id = RandomStringGenerator.generateUniqueString(Item.UNIQUE_ID_LENGTH, RandomStringGenerator.ALPHA_NUMERIC, itemMap.keySet()); itemMap.put(id, item); return new IDAddressedEntity(id, item); } return null; } public boolean hasItem(Item item) { for (Map.Entry<String, Item> entry : itemMap.entrySet()) { if (entry.getValue().equals(item)) { return true; } } return false; } public Item changeAmountOfItem(String itemId, int amountOfChange) { Item item = itemMap.get(itemId).changeAmount(amountOfChange); if (item.isEmpty()) { destroyItem(itemId); } return item; } private void initAreaURI(String instanceId) { Instance instance = Instances.getInstance().getInstance(instanceId); areaURI = findAreaURI(instance); } private String findAreaURI(Instance instance) { // キャラクターのポジションを用いてどのエリア内にいるかを判定して当該エリアのURIに更新する for (String areaId : instance.getAreaIdSet()) { if (isInTheArea(instance.getArea(areaId))) { int subStringStartIndex = areaURI.length() - Character.UNIQUE_ID_LENGTH; StringBuilder newAreaURI = new StringBuilder(); return newAreaURI.append(areaURI.substring(0, subStringStartIndex)).append(areaId).toString(); } } throw new IllegalStateException("Character is in the unknown area"); } private boolean isInTheArea(Area area) { boolean inTheArea = false; for (Plain plain : area.getRegion()) { // double equation = (plain.getA() * position.getX()) + (plain.getB() * // position.getY()) // + (plain.getC() * position.getZ()) + plain.getD(); // inTheArea = (equation < 0); } return inTheArea; } private void updateAreaURI() { String[] areaURISplit = areaURI.split("/"); // ……/instances/{instanceId}/areas/{areaId} int splitSize = areaURISplit.length; String instanceId = areaURISplit[splitSize - 3]; String previousAreaId = areaURISplit[splitSize - 1]; Instance instance = Instances.getInstance().getInstance(instanceId); Area previousArea = instance.getArea(previousAreaId); // 現在のキャラクターのポジションが更新前にいたエリア内にいるかどうかを判定 if (isInTheArea(previousArea)) { return; // 更新前にいたエリア内にいればエリアURIを変更する必要はない } // キャラクターのポジションを用いてどのエリア内にいるかを判定して当該エリアのURIに更新する areaURI = findAreaURI(instance); } public Item destroyItem(String itemId) { return itemMap.remove(itemId); } }