RuneHive-Tarnish
Neural OSRS Enhancement Framework
Loading...
Searching...
No Matches
Store.java
1package com.osroyale.content.store;
2
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;
11
12import java.util.*;
13
51
52* The class which holds support for further abstraction for shops.
53 *
54 * @author <a href="http://www.rune-server.org/members/stand+up/">Stand Up</a>
55 * @since 4-1-2017.
56 */
57public abstract class Store {
58
60 public static Map<String, Store> STORES = new HashMap<>();
61
63 public final String name;
64
66 public ItemContainer container;
67
69 protected final CurrencyType currencyType;
70
72 public Map<Integer, Integer> itemCache;
73
75 public final Set<Player> players = new HashSet<>();
76
77 public Store(String name, ItemContainer.StackPolicy policy, CurrencyType currencyType, int capacity) {
78 this.name = name;
79 this.currencyType = currencyType;
80 this.container = new ItemContainer(capacity, policy, new StoreItem[capacity]);
81 this.itemCache = new HashMap<>(container.capacity());
82 }
83
84 public static void closeShop(Player player) {
85 if (!player.interfaceManager.isInterfaceOpen(StoreConstant.INTERFACE_ID) || !player.attributes.has("SHOP")) {
86 return;
87 }
88
89 Store store = STORES.get(player.attributes.get("SHOP"));
90
91 if (store == null) {
92 return;
93 }
94
95 store.close(player);
96 }
97
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")) {
100 return;
101 }
102
103 Store store = STORES.get(player.attributes.get("SHOP"));
104
105 if (store == null) {
106 return;
107 }
108
109 store.itemContainerAction(player, id, slot, action, purchase);
110 }
111
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;
116 }
117
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;
122 }
123
124 public abstract void itemContainerAction(Player player, int id, int slot, int action, boolean purchase);
125
126 public boolean purchase(Player player, Item item, int slot) {
127 if (item == null || !Item.valid(item)) {
128 return false;
129 }
130
131 Optional<Item> find = container.retrieve(slot);
132
133 if (!find.isPresent()) {
134 return false;
135 }
136
137 Item found = find.get();
138
139 if (!(found instanceof StoreItem)) {
140 return false;
141 }
142
143 if (!found.matchesId(item.getId())) {
144 player.send(new SendMessage("Something went wrong."));
145 return false;
146 }
147
148 StoreItem storeItem = (StoreItem) find.get();
149
150 if (storeItem.getAmount() < 1) {
151 player.send(new SendMessage("There is none of this item left in stock!"));
152 return false;
153 }
154 if(PlayerRight.isIronman(player)) {
155 player.send(new SendMessage("Ironman-players cannot buy items sold by players."));
156 return false;
157 }
158
159 if (item.getAmount() > storeItem.getAmount())
160 item.setAmount(storeItem.getAmount());
161 if (!player.inventory.hasCapacityFor(item)) {
162 item.setAmount(player.inventory.remaining());
163
164 if (item.getAmount() == 0) {
165 player.send(new SendMessage("You do not have enough space in your inventory to buy this item!"));
166 return false;
167 }
168 }
169
170 final int value = storeItem.getShopValue();
171
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."));
174 return false;
175 }
176
177 if (player.inventory.remaining() >= item.getAmount() && !item.isStackable()
178 || player.inventory.remaining() >= 1 && item.isStackable()
179 || player.inventory.contains(item.getId()) && item.isStackable()) {
180
181 if (value > 0 && !currencyType.currency.takeCurrency(player, item.getAmount() * value)) {
182 return false;
183 }
184
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());
190 }
191 } else if (!itemCache.containsKey(item.getId())) {
192 if (decrementStock()) {
193 container.remove(item);
194 }
195 if (type().equals(StoreType.PERSONAL)) {
196 container.shift();
197 }
198 }
199 player.inventory.add(new Item(item.getId(), item.getAmount()));
200 } else {
201 player.send(new SendMessage("You don't have enough space in your inventory."));
202 return false;
203 }
204 onPurchase(player, new Item(item.getId(), item.getAmount() * value));
205 refresh(player);
206 return true;
207 }
208
209 public void onPurchase(Player player, Item item) {
210
211 }
212
213 protected final void sell(Player player, Item item, int slot, boolean addX) {
214 if (item == null || !Item.valid(item)) {
215 return;
216 }
217
218 final Item inventoryItem = player.inventory.get(slot);
219
220 if (inventoryItem == null) {
221 player.send(new SendMessage("This item does not exist."));
222 return;
223 }
224
225 if (sellType() == SellType.NONE) {
226 player.send(new SendMessage("This store won't buy any items."));
227 return;
228 }
229
230 if (!item.isTradeable()) {
231 player.send(new SendMessage("This item can't be sold to shops."));
232 return;
233 }
234
235 final boolean contains = container.contains(item.getId());
236
237 if (!contains && sellType() == SellType.CONTAINS) {
238 player.send(new SendMessage("You can't sell " + item.getName() + " to this shop."));
239 return;
240 }
241 if (!container.hasCapacityFor(item)) {
242 player.send(new SendMessage("There is no room in this store for the item you are trying to sell!"));
243 return;
244 }
245
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!"));
248 return;
249 }
250
251 if (CurrencyType.isCurrency(item.getId())) {
252 player.send(new SendMessage("You can not sell currency to this shop!"));
253 return;
254 }
255
256 final int sellValue = item.getSellValue();
257
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!"));
260 return;
261 }
262
263 final int amount = player.inventory.computeAmountForId(item.getId());
264
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());
269 }
270
271 player.inventory.remove(item, slot);
272
273 if (sellValue > 0) {
274 currencyType.currency.recieveCurrency(player, item.getAmount() * sellValue);
275 }
276
277 final StoreItem converted = new StoreItem(item.getId(), item.getAmount());
278
279 container.add(converted);
280
281 refresh(player);
282 }
283
284 public abstract void refresh(Player player);
285
286 protected final void sendSellValue(Player player, int slot) {
287 Item item = player.inventory.get(slot);
288
289 if (item == null) {
290 return;
291 }
292
293 if (!item.isTradeable()) {
294 player.send(new SendMessage("This item can't be sold to shops."));
295 return;
296 }
297
298 if (CurrencyType.isCurrency(item.getId())) {
299 player.send(new SendMessage("You can not sell currency to this shop!"));
300 return;
301 }
302
303 final int value = item.getSellValue();
304
305 if (value <= 0) {
306 player.send(new SendMessage(String.format("This store will buy %s for free!", item.getName())));
307 return;
308 }
309
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));
312 }
313
314 protected void sendPurchaseValue(Player player, int slot) {
315 Optional<Item> find = container.retrieve(slot);
316
317 if (!find.isPresent()) {
318 return;
319 }
320
321 Item item = find.get();
322
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);
328 }
329
330 }
331
332 public abstract void open(Player player);
333
334 public abstract void close(Player player);
335
336 public abstract StoreType type();
337
338 public abstract SellType sellType();
339
340 public boolean decrementStock() {
341 return true;
342 }
343
344 @Override
345 public final int hashCode() {
346 final int prime = 31;
347 int result = 1;
348 result = prime * result + ((name == null) ? 0 : name.hashCode());
349 return result;
350 }
351
352 @Override
353 public final boolean equals(Object obj) {
354 if (this == obj)
355 return true;
356 if (obj == null)
357 return false;
358 if (!(obj instanceof Store))
359 return false;
360 Store other = (Store) obj;
361 if (name == null) {
362 if (other.name != null)
363 return false;
364 } else if (!name.equals(other.name))
365 return false;
366 return true;
367 }
368}
boolean takeCurrency(Player player, int amount)
void recieveCurrency(Player player, int amount)