1package com.osroyale.content.store;
3import com.osroyale.content.store.currency.CurrencyType;
4import com.osroyale.content.store.impl.PersonalStore;
5import com.osroyale.game.world.entity.mob.player.Player;
6import com.osroyale.game.world.entity.mob.player.PlayerRight;
7import com.osroyale.game.world.items.Item;
8import com.osroyale.game.world.items.containers.ItemContainer;
9import com.osroyale.net.packet.out.SendMessage;
10import com.osroyale.util.Utility;
52* The
class which holds support for further abstraction for shops.
54 * @author <a href=
"http://www.rune-server.org/members/stand+up/">Stand Up</a>
57public abstract class Store {
60 public static Map<String, Store> STORES =
new HashMap<>();
63 public final String name;
66 public ItemContainer container;
69 protected final CurrencyType currencyType;
72 public Map<Integer, Integer> itemCache;
75 public final Set<Player> players =
new HashSet<>();
77 public Store(String name, ItemContainer.StackPolicy policy, CurrencyType currencyType,
int capacity) {
79 this.currencyType = currencyType;
80 this.container =
new ItemContainer(capacity, policy,
new StoreItem[capacity]);
81 this.itemCache =
new HashMap<>(container.capacity());
84 public static void closeShop(Player player) {
85 if (!player.interfaceManager.isInterfaceOpen(StoreConstant.INTERFACE_ID) || !player.attributes.has(
"SHOP")) {
89 Store store = STORES.get(player.attributes.get(
"SHOP"));
98 public static void exchange(Player player,
int id,
int slot,
int action,
boolean purchase) {
99 if (!player.interfaceManager.isInterfaceOpen(StoreConstant.INTERFACE_ID) || !player.attributes.has(
"SHOP")) {
103 Store store = STORES.get(player.attributes.get(
"SHOP"));
109 store.itemContainerAction(player,
id, slot, action, purchase);
112 protected static List<PersonalStore> getPersonalShops() {
113 List<PersonalStore> personal_shops =
new ArrayList<>();
114 STORES.values().stream().filter(s -> s.type().equals(StoreType.PERSONAL)).forEach(s -> personal_shops.add((PersonalStore) s));
115 return personal_shops;
118 protected static List<PersonalStore> getFeaturedShops() {
119 List<PersonalStore> featured_shops =
new ArrayList<>();
120 STORES.values().stream().filter(s -> s.type().equals(StoreType.PERSONAL) && ((PersonalStore) s).rank > 0).forEach(s -> featured_shops.add((PersonalStore) s));
121 return featured_shops;
124 public abstract void itemContainerAction(Player player,
int id,
int slot,
int action,
boolean purchase);
126 public boolean purchase(Player player, Item item,
int slot) {
127 if (item ==
null || !Item.valid(item)) {
131 Optional<Item> find = container.
retrieve(slot);
133 if (!find.isPresent()) {
137 Item found = find.get();
139 if (!(found instanceof StoreItem)) {
143 if (!found.matchesId(item.getId())) {
144 player.send(
new SendMessage(
"Something went wrong."));
148 StoreItem storeItem = (StoreItem) find.get();
150 if (storeItem.getAmount() < 1) {
151 player.send(
new SendMessage(
"There is none of this item left in stock!"));
154 if(PlayerRight.isIronman(player)) {
155 player.send(
new SendMessage(
"Ironman-players cannot buy items sold by players."));
159 if (item.getAmount() > storeItem.getAmount())
160 item.setAmount(storeItem.getAmount());
161 if (!player.inventory.hasCapacityFor(item)) {
162 item.setAmount(player.inventory.remaining());
164 if (item.getAmount() == 0) {
165 player.send(
new SendMessage(
"You do not have enough space in your inventory to buy this item!"));
170 final int value = storeItem.getShopValue();
172 if (!(currencyType.currency.
currencyAmount(player) >= (value * item.getAmount()))) {
173 player.send(
new SendMessage(
"You do not have enough " + currencyType.toString() +
" to buy this item."));
177 if (player.inventory.remaining() >= item.getAmount() && !item.isStackable()
178 || player.inventory.remaining() >= 1 && item.isStackable()
179 || player.inventory.contains(item.getId()) && item.isStackable()) {
181 if (value > 0 && !currencyType.currency.
takeCurrency(player, item.getAmount() * value)) {
185 if (type().equals(StoreType.PERSONAL) && container.
retrieve(slot).isPresent() && (container.
retrieve(slot).get().getAmount() - item.getAmount() > 0)) {
186 container.
retrieve(slot).get().decrementAmountBy(item.getAmount());
187 }
else if (itemCache.containsKey(item.getId()) && container.
retrieve(slot).isPresent()) {
188 if (decrementStock()) {
189 container.
retrieve(slot).get().decrementAmountBy(item.getAmount());
191 }
else if (!itemCache.containsKey(item.getId())) {
192 if (decrementStock()) {
195 if (type().equals(StoreType.PERSONAL)) {
199 player.inventory.add(
new Item(item.getId(), item.getAmount()));
201 player.send(
new SendMessage(
"You don't have enough space in your inventory."));
204 onPurchase(player,
new Item(item.getId(), item.getAmount() * value));
209 public void onPurchase(Player player, Item item) {
213 protected final void sell(Player player, Item item,
int slot,
boolean addX) {
214 if (item ==
null || !Item.valid(item)) {
218 final Item inventoryItem = player.inventory.get(slot);
220 if (inventoryItem ==
null) {
221 player.send(
new SendMessage(
"This item does not exist."));
225 if (sellType() == SellType.
NONE) {
226 player.send(
new SendMessage(
"This store won't buy any items."));
230 if (!item.isTradeable()) {
231 player.send(
new SendMessage(
"This item can't be sold to shops."));
235 final boolean contains = container.
contains(item.getId());
237 if (!contains && sellType() == SellType.
CONTAINS) {
238 player.send(
new SendMessage(
"You can't sell " + item.getName() +
" to this shop."));
242 player.send(
new SendMessage(
"There is no room in this store for the item you are trying to sell!"));
246 if (player.inventory.remaining() == 0 && !currencyType.currency.
canRecieveCurrency(player) && inventoryItem.getAmount() > 1) {
247 player.send(
new SendMessage(
"You do not have enough space in your inventory to sell this item!"));
251 if (CurrencyType.isCurrency(item.getId())) {
252 player.send(
new SendMessage(
"You can not sell currency to this shop!"));
256 final int sellValue = item.getSellValue();
258 if (sellValue >= StoreConstant.MAXIMUM_SELL_VALUE) {
259 player.send(
new SendMessage(
"This item can not be sold as it has a value greater than 500,000 coins!"));
263 final int amount = player.inventory.computeAmountForId(item.getId());
265 if (item.getAmount() > amount && !item.isStackable()) {
266 item.setAmount(amount);
267 }
else if (item.getAmount() > inventoryItem.getAmount() && item.isStackable()) {
268 item.setAmount(inventoryItem.getAmount());
271 player.inventory.remove(item, slot);
274 currencyType.currency.
recieveCurrency(player, item.getAmount() * sellValue);
277 final StoreItem converted =
new StoreItem(item.getId(), item.getAmount());
279 container.
add(converted);
284 public abstract void refresh(Player player);
286 protected final void sendSellValue(Player player,
int slot) {
287 Item item = player.inventory.get(slot);
293 if (!item.isTradeable()) {
294 player.send(
new SendMessage(
"This item can't be sold to shops."));
298 if (CurrencyType.isCurrency(item.getId())) {
299 player.send(
new SendMessage(
"You can not sell currency to this shop!"));
303 final int value = item.getSellValue();
306 player.send(
new SendMessage(String.format(
"This store will buy %s for free!", item.getName())));
310 final String message = this.sellType() != SellType.NONE ? String.format(
"This store will buy %s for %s %s.", item.getName(), Utility.formatDigits(value), currencyType.toString()) : String.format(
"[%s] will not buy any items.", name);
311 player.send(
new SendMessage(message));
314 protected void sendPurchaseValue(Player player,
int slot) {
315 Optional<Item> find = container.
retrieve(slot);
317 if (!find.isPresent()) {
321 Item item = find.get();
323 if (item instanceof StoreItem) {
324 StoreItem storeItem = (StoreItem) item;
325 final int value = storeItem.getShopValue();
326 String message =
"This store will sell " + item.getName() +
" for " + (value <= 0 ?
"free!" : Utility.formatDigits(value) +
" " + storeItem.getShopCurrency(
this).toString() +
".");
327 player.message(message);
332 public abstract void open(Player player);
334 public abstract void close(Player player);
336 public abstract StoreType type();
338 public abstract SellType sellType();
340 public boolean decrementStock() {
345 public final int hashCode() {
346 final int prime = 31;
348 result = prime * result + ((name ==
null) ? 0 : name.hashCode());
353 public final boolean equals(Object obj) {
358 if (!(obj instanceof Store))
360 Store other = (Store) obj;
362 if (other.name !=
null)
364 }
else if (!name.equals(other.name))
final Optional< Item > retrieve(int index)
boolean remove(Item item)
final boolean hasCapacityFor(Item... item)
boolean takeCurrency(Player player, int amount)
int currencyAmount(Player player)
boolean canRecieveCurrency(Player player)
void recieveCurrency(Player player, int amount)