RuneHive-Game
Loading...
Searching...
No Matches
Store.java
Go to the documentation of this file.
1package com.runehive.content.store;
2
3import com.runehive.content.store.currency.CurrencyType;
4import com.runehive.content.store.impl.PersonalStore;
5import com.runehive.game.world.entity.mob.player.Player;
6import com.runehive.game.world.entity.mob.player.PlayerRight;
7import com.runehive.game.world.items.Item;
8import com.runehive.game.world.items.containers.ItemContainer;
9import com.runehive.net.packet.out.SendMessage;
10import com.runehive.util.Utility;
11
12import java.util.*;
13
14/**
15 * The class which holds support for further abstraction for shops.
16 *
17 * @author <a href="http://www.rune-server.org/members/stand+up/">Stand Up</a>
18 * @since 4-1-2017.
19 */
20public abstract class Store {
21
22 /** A mapping of each shop by it's name. */
23 public static Map<String, Store> STORES = new HashMap<>();
24
25 /** The name of this shop. */
26 public final String name;
27
28 /** The current item container which contains the current items from this shop. */
30
31 /** The currency for this shop. */
32 protected final CurrencyType currencyType;
33
34 /** The map of cached shop item identifications and their amounts. */
35 public Map<Integer, Integer> itemCache;
36
37 /** The set of players that are currently viewing this shop. */
38 public final Set<Player> players = new HashSet<>();
39
40 public Store(String name, ItemContainer.StackPolicy policy, CurrencyType currencyType, int capacity) {
41 this.name = name;
42 this.currencyType = currencyType;
43 this.container = new ItemContainer(capacity, policy, new StoreItem[capacity]);
44 this.itemCache = new HashMap<>(container.capacity());
45 }
46
47 public static void closeShop(Player player) {
49 return;
50 }
51
52 Store store = STORES.get(player.attributes.get("SHOP"));
53
54 if (store == null) {
55 return;
56 }
57
58 store.close(player);
59 }
60
61 public static void exchange(Player player, int id, int slot, int action, boolean purchase) {
63 return;
64 }
65
66 Store store = STORES.get(player.attributes.get("SHOP"));
67
68 if (store == null) {
69 return;
70 }
71
72 store.itemContainerAction(player, id, slot, action, purchase);
73 }
74
75 protected static List<PersonalStore> getPersonalShops() {
76 List<PersonalStore> personal_shops = new ArrayList<>();
77 STORES.values().stream().filter(s -> s.type().equals(StoreType.PERSONAL)).forEach(s -> personal_shops.add((PersonalStore) s));
78 return personal_shops;
79 }
80
81 protected static List<PersonalStore> getFeaturedShops() {
82 List<PersonalStore> featured_shops = new ArrayList<>();
83 STORES.values().stream().filter(s -> s.type().equals(StoreType.PERSONAL) && ((PersonalStore) s).rank > 0).forEach(s -> featured_shops.add((PersonalStore) s));
84 return featured_shops;
85 }
86
87 public abstract void itemContainerAction(Player player, int id, int slot, int action, boolean purchase);
88
89 public boolean purchase(Player player, Item item, int slot) {
90 if (item == null || !Item.valid(item)) {
91 return false;
92 }
93
94 Optional<Item> find = container.retrieve(slot);
95
96 if (!find.isPresent()) {
97 return false;
98 }
99
100 Item found = find.get();
101
102 if (!(found instanceof StoreItem)) {
103 return false;
104 }
105
106 if (!found.matchesId(item.getId())) {
107 player.send(new SendMessage("Something went wrong."));
108 return false;
109 }
110
111 StoreItem storeItem = (StoreItem) find.get();
112
113 if (storeItem.getAmount() < 1) {
114 player.send(new SendMessage("There is none of this item left in stock!"));
115 return false;
116 }
117 if(PlayerRight.isIronman(player)) {
118 player.send(new SendMessage("Ironman-players cannot buy items sold by players."));
119 return false;
120 }
121
122 if (item.getAmount() > storeItem.getAmount())
123 item.setAmount(storeItem.getAmount());
124 if (!player.inventory.hasCapacityFor(item)) {
125 item.setAmount(player.inventory.remaining());
126
127 if (item.getAmount() == 0) {
128 player.send(new SendMessage("You do not have enough space in your inventory to buy this item!"));
129 return false;
130 }
131 }
132
133 final int value = storeItem.getShopValue();
134
135 if (!(currencyType.currency.currencyAmount(player) >= (value * item.getAmount()))) {
136 player.send(new SendMessage("You do not have enough " + currencyType.toString() + " to buy this item."));
137 return false;
138 }
139
140 if (player.inventory.remaining() >= item.getAmount() && !item.isStackable()
141 || player.inventory.remaining() >= 1 && item.isStackable()
142 || player.inventory.contains(item.getId()) && item.isStackable()) {
143
144 if (value > 0 && !currencyType.currency.takeCurrency(player, item.getAmount() * value)) {
145 return false;
146 }
147
148 if (type().equals(StoreType.PERSONAL) && container.retrieve(slot).isPresent() && (container.retrieve(slot).get().getAmount() - item.getAmount() > 0)) {
149 container.retrieve(slot).get().decrementAmountBy(item.getAmount());
150 } else if (itemCache.containsKey(item.getId()) && container.retrieve(slot).isPresent()) {
151 if (decrementStock()) {
152 container.retrieve(slot).get().decrementAmountBy(item.getAmount());
153 }
154 } else if (!itemCache.containsKey(item.getId())) {
155 if (decrementStock()) {
156 container.remove(item);
157 }
158 if (type().equals(StoreType.PERSONAL)) {
159 container.shift();
160 }
161 }
162 player.inventory.add(new Item(item.getId(), item.getAmount()));
163 } else {
164 player.send(new SendMessage("You don't have enough space in your inventory."));
165 return false;
166 }
167 onPurchase(player, new Item(item.getId(), item.getAmount() * value));
168 refresh(player);
169 return true;
170 }
171
172 public void onPurchase(Player player, Item item) {
173
174 }
175
176 protected final void sell(Player player, Item item, int slot, boolean addX) {
177 if (item == null || !Item.valid(item)) {
178 return;
179 }
180
181 final Item inventoryItem = player.inventory.get(slot);
182
183 if (inventoryItem == null) {
184 player.send(new SendMessage("This item does not exist."));
185 return;
186 }
187
188 if (sellType() == SellType.NONE) {
189 player.send(new SendMessage("This store won't buy any items."));
190 return;
191 }
192
193 if (!item.isTradeable()) {
194 player.send(new SendMessage("This item can't be sold to shops."));
195 return;
196 }
197
198 final boolean contains = container.contains(item.getId());
199
200 if (!contains && sellType() == SellType.CONTAINS) {
201 player.send(new SendMessage("You can't sell " + item.getName() + " to this shop."));
202 return;
203 }
204 if (!container.hasCapacityFor(item)) {
205 player.send(new SendMessage("There is no room in this store for the item you are trying to sell!"));
206 return;
207 }
208
209 if (player.inventory.remaining() == 0 && !currencyType.currency.canRecieveCurrency(player) && inventoryItem.getAmount() > 1) {
210 player.send(new SendMessage("You do not have enough space in your inventory to sell this item!"));
211 return;
212 }
213
214 if (CurrencyType.isCurrency(item.getId())) {
215 player.send(new SendMessage("You can not sell currency to this shop!"));
216 return;
217 }
218
219 final int sellValue = item.getSellValue();
220
221 if (sellValue >= StoreConstant.MAXIMUM_SELL_VALUE) {
222 player.send(new SendMessage("This item can not be sold as it has a value greater than 500,000 coins!"));
223 return;
224 }
225
226 final int amount = player.inventory.computeAmountForId(item.getId());
227
228 if (item.getAmount() > amount && !item.isStackable()) {
229 item.setAmount(amount);
230 } else if (item.getAmount() > inventoryItem.getAmount() && item.isStackable()) {
231 item.setAmount(inventoryItem.getAmount());
232 }
233
234 player.inventory.remove(item, slot);
235
236 if (sellValue > 0) {
237 currencyType.currency.recieveCurrency(player, item.getAmount() * sellValue);
238 }
239
240 final StoreItem converted = new StoreItem(item.getId(), item.getAmount());
241
242 container.add(converted);
243
244 refresh(player);
245 }
246
247 public abstract void refresh(Player player);
248
249 protected final void sendSellValue(Player player, int slot) {
250 Item item = player.inventory.get(slot);
251
252 if (item == null) {
253 return;
254 }
255
256 if (!item.isTradeable()) {
257 player.send(new SendMessage("This item can't be sold to shops."));
258 return;
259 }
260
261 if (CurrencyType.isCurrency(item.getId())) {
262 player.send(new SendMessage("You can not sell currency to this shop!"));
263 return;
264 }
265
266 final int value = item.getSellValue();
267
268 if (value <= 0) {
269 player.send(new SendMessage(String.format("This store will buy %s for free!", item.getName())));
270 return;
271 }
272
273 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);
274 player.send(new SendMessage(message));
275 }
276
277 protected void sendPurchaseValue(Player player, int slot) {
278 Optional<Item> find = container.retrieve(slot);
279
280 if (!find.isPresent()) {
281 return;
282 }
283
284 Item item = find.get();
285
286 if (item instanceof StoreItem) {
287 StoreItem storeItem = (StoreItem) item;
288 final int value = storeItem.getShopValue();
289 String message = "This store will sell " + item.getName() + " for " + (value <= 0 ? "free!" : Utility.formatDigits(value) + " " + storeItem.getShopCurrency(this).toString() + ".");
290 player.message(message);
291 }
292
293 }
294
295 public abstract void open(Player player);
296
297 public abstract void close(Player player);
298
299 public abstract StoreType type();
300
301 public abstract SellType sellType();
302
303 public boolean decrementStock() {
304 return true;
305 }
306
307 @Override
308 public final int hashCode() {
309 final int prime = 31;
310 int result = 1;
311 result = prime * result + ((name == null) ? 0 : name.hashCode());
312 return result;
313 }
314
315 @Override
316 public final boolean equals(Object obj) {
317 if (this == obj)
318 return true;
319 if (obj == null)
320 return false;
321 if (!(obj instanceof Store))
322 return false;
323 Store other = (Store) obj;
324 if (name == null) {
325 if (other.name != null)
326 return false;
327 } else if (!name.equals(other.name))
328 return false;
329 return true;
330 }
331}
Class to execute all constants for Shops.
static final int MAXIMUM_SELL_VALUE
The maximum sell value.
static final int INTERFACE_ID
The identification for the shop itemcontainer.
abstract SellType sellType()
void sendPurchaseValue(Player player, int slot)
Definition Store.java:277
static void closeShop(Player player)
Definition Store.java:47
final String name
The name of this shop.
Definition Store.java:26
Store(String name, ItemContainer.StackPolicy policy, CurrencyType currencyType, int capacity)
Definition Store.java:40
abstract void itemContainerAction(Player player, int id, int slot, int action, boolean purchase)
abstract StoreType type()
final Set< Player > players
The set of players that are currently viewing this shop.
Definition Store.java:38
Map< Integer, Integer > itemCache
The map of cached shop item identifications and their amounts.
Definition Store.java:35
final void sell(Player player, Item item, int slot, boolean addX)
Definition Store.java:176
abstract void open(Player player)
static List< PersonalStore > getFeaturedShops()
Definition Store.java:81
void onPurchase(Player player, Item item)
Definition Store.java:172
final void sendSellValue(Player player, int slot)
Definition Store.java:249
static List< PersonalStore > getPersonalShops()
Definition Store.java:75
abstract void refresh(Player player)
static Map< String, Store > STORES
A mapping of each shop by it's name.
Definition Store.java:23
abstract void close(Player player)
final CurrencyType currencyType
The currency for this shop.
Definition Store.java:32
final boolean equals(Object obj)
Definition Store.java:316
ItemContainer container
The current item container which contains the current items from this shop.
Definition Store.java:29
static void exchange(Player player, int id, int slot, int action, boolean purchase)
Definition Store.java:61
boolean purchase(Player player, Item item, int slot)
Definition Store.java:89
A simple wrapper class which holds extra attributes for the item object.
CurrencyType getShopCurrency(Store store)
static void add(Player player, PersonalStore store)
final GenericAttributes attributes
Definition Mob.java:95
boolean isInterfaceOpen(int id)
Checks if a certain interface is enter.
This class represents a character controlled by a player.
Definition Player.java:125
The container class that represents an item that can be interacted with.
Definition Item.java:21
final void setAmount(int amount)
Sets the quantity of this item.
Definition Item.java:351
final int getId()
Gets the identification of this item.
Definition Item.java:324
static boolean valid(Item item)
Determines if item is valid.
Definition Item.java:259
final int getAmount()
Gets the quantity of this item.
Definition Item.java:342
An abstraction game representing a group of Items.
final int computeAmountForId(int id)
Computes the total quantity of the Items in this container with id.
boolean remove(Item item)
Attempts to withdraw item from this container.
final Item get(int index)
Gets the Item located on index.
boolean add(Item item)
Attempts to deposit item into this container.
final boolean hasCapacityFor(Item... item)
Determines if this container has the capacity for item.
boolean contains(int id)
Determines if this container contains id.
The OutgoingPacket that sends a message to a Players chatbox in the client.
Handles miscellaneous methods.
Definition Utility.java:27
static String formatDigits(final int amount)
Formats digits for integers.
Definition Utility.java:41
public< K, E > E get(K key)
Gets a generic attribute.
public< K > boolean has(K key)
Checks if a key is in the list of generic attribute.
Represents ways items can be sold in a shop.
Definition SellType.java:8
NONE
No items can be sold in the shop.
Definition SellType.java:13
CONTAINS
Can only sell items that are contained in the shop.
Definition SellType.java:18
The enumerated type whose elements represent constants that are used to differ between shops.
Definition StoreType.java:9
PERSONAL
The personal shop which is commonly owned by players.
The enumerated type whom holds all the currencies usable for a server.
static boolean isIronman(Player player)
Checks if the player is an ironman.
An enumerated type defining policies for stackable Items.