diff --git a/build.gradle.kts b/build.gradle.kts index a78130f..0b7be1d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,16 +10,8 @@ repositories { maven { url = uri("https://gotti.no-ip.org/maven/repository") } - maven { - url = uri("https://jitpack.io") - } } dependencies { implementation("org.gotti.wurmunlimited:server-modlauncher:0.46") - implementation("com.github.Sindusk:sindusklibrary:v2.3") -} - -tasks.test { - useJUnitPlatform() } \ No newline at end of file diff --git a/mods/shop_categories.json b/mods/shop_categories.json new file mode 100644 index 0000000..a631e7f --- /dev/null +++ b/mods/shop_categories.json @@ -0,0 +1,7 @@ +[ + { + "id": 1, + "name": "Consumables", + "description": "Limited usage consumable items." + } +] \ No newline at end of file diff --git a/mods/shop_items.json b/mods/shop_items.json index 0b314a5..ca3ea35 100644 --- a/mods/shop_items.json +++ b/mods/shop_items.json @@ -1,18 +1,10 @@ -{ - "categories": [ - { - "id": 1, - "name": "Items", - "description": "Available in-game items for purchase.", - "items": [ - { - "id": 1, - "name": "Sleep Powder", - "description": "Grants 1 hour of sleep bonus.", - "ironPrice": 50000, - "image": "https://www.wurmpedia.com/images/5/5e/Sleep_powder.png" - } - ] - } - ] -} \ No newline at end of file +[ + { + "id": 1, + "categoryId": 1, + "name": "Sleep Powder", + "description": "Grants 1 hour of sleep bonus.", + "ironPrice": 50000, + "image": "https://www.wurmpedia.com/images/5/5e/Sleep_powder.png" + } +] \ No newline at end of file diff --git a/src/main/java/com/wurmonline/server/questions/ShopQuestion.java b/src/main/java/com/wurmonline/server/questions/ShopQuestion.java new file mode 100644 index 0000000..fa7aa57 --- /dev/null +++ b/src/main/java/com/wurmonline/server/questions/ShopQuestion.java @@ -0,0 +1,36 @@ +package com.wurmonline.server.questions; + +import com.wurmonline.server.NoSuchPlayerException; +import com.wurmonline.server.Players; +import mod.treestar.shopmod.ShopService; + +import java.util.Properties; + +public class ShopQuestion extends Question { + private static final int SHOP_QUESTION_ID = 90001; + + private ShopService shopService; + + public ShopQuestion(long responderId, String shopName, ShopService shopService) throws NoSuchPlayerException { + super(Players.getInstance().getPlayer(responderId), shopName, null, SHOP_QUESTION_ID, responderId); + this.shopService = shopService; + } + + @Override + public void answer(Properties properties) { + super.answer(properties); + } + + @Override + public void sendQuestion() { + super.sendQuestion(); + } + + public ShopService getShopService() { + return shopService; + } + + public void setShopService(ShopService shopService) { + this.shopService = shopService; + } +} diff --git a/src/main/java/mod/treestar/shopmod/ShopMod.java b/src/main/java/mod/treestar/shopmod/ShopMod.java new file mode 100644 index 0000000..65a7040 --- /dev/null +++ b/src/main/java/mod/treestar/shopmod/ShopMod.java @@ -0,0 +1,63 @@ +package mod.treestar.shopmod; + +import mod.treestar.shopmod.categoryprovider.JsonShopCategoryProvider; +import mod.treestar.shopmod.itemprovider.JsonShopItemProvider; +import org.gotti.wurmunlimited.modloader.interfaces.Configurable; +import org.gotti.wurmunlimited.modloader.interfaces.Initable; +import org.gotti.wurmunlimited.modloader.interfaces.WurmServerMod; + +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class ShopMod implements WurmServerMod, Initable, Configurable { + private static final Logger logger = Logger.getLogger(ShopMod.class.getName()); + + private String shopName = "Server Shop"; + private boolean enableTokenAccess = true; + private boolean enableMailboxAccess = false; + private String categoryJsonPath = "mods/shop/categories.json"; + private String itemJsonPath = "mods/shop/items.json"; + private Level logLevel = Level.INFO; + + @Override + public void configure(Properties properties) { + shopName = properties.getProperty("shopName", shopName); + enableTokenAccess = getBoolean(properties, "enableTokenAccess", enableTokenAccess); + enableMailboxAccess = getBoolean(properties, "enableMailboxAccess", enableMailboxAccess); + categoryJsonPath = properties.getProperty("categoryJsonPath", categoryJsonPath); + itemJsonPath = properties.getProperty("itemJsonPath", itemJsonPath); + logLevel = getLogLevel(properties.getProperty("logLevel", logLevel.getName())); + logger.setLevel(logLevel); + } + + @Override + public void init() { + ShopService shopService = ShopService.getInstance(); + + shopService.registerCategoryProvider(new JsonShopCategoryProvider(categoryJsonPath)); + shopService.registerItemProvider(new JsonShopItemProvider(itemJsonPath)); + + logger.log(Level.INFO, String.format("Initialized shop '%s' (token access: %s, mailbox access: %s)", shopName, enableTokenAccess, enableMailboxAccess)); + } + + /** + * Factory for other mods to build a new shop instance separate from the default singleton. + */ + public ShopService createShopService() { + return ShopService.create(); + } + + private boolean getBoolean(Properties properties, String key, boolean defaultValue) { + return Boolean.parseBoolean(properties.getProperty(key, Boolean.toString(defaultValue))); + } + + private Level getLogLevel(String value) { + try { + return Level.parse(value); + } catch (IllegalArgumentException e) { + logger.log(Level.WARNING, String.format("Invalid log level '%s', defaulting to %s", value, logLevel.getName()), e); + return logLevel; + } + } +} diff --git a/src/main/java/mod/treestar/shopmod/ShopService.java b/src/main/java/mod/treestar/shopmod/ShopService.java new file mode 100644 index 0000000..bad8a1b --- /dev/null +++ b/src/main/java/mod/treestar/shopmod/ShopService.java @@ -0,0 +1,37 @@ +package mod.treestar.shopmod; + +import mod.treestar.shopmod.categoryprovider.ShopCategoryProvider; +import mod.treestar.shopmod.itemprovider.ShopItemProvider; + +import java.util.ArrayList; +import java.util.List; + +public class ShopService { + private List categoryProviders = new ArrayList<>(); + private List itemProviders = new ArrayList<>(); + + private static ShopService instance; + + public void registerCategoryProvider(ShopCategoryProvider provider) { + categoryProviders.add(provider); + } + + public void registerItemProvider(ShopItemProvider provider) { + itemProviders.add(provider); + } + + + public static ShopService getInstance() { + if(instance == null) { + instance = new ShopService(); + } + return instance; + } + + /** + * Creates a new, unconfigured shop service for consumers that want a separate shop instance. + */ + public static ShopService create() { + return new ShopService(); + } +} diff --git a/src/main/java/mod/treestar/shopmod/SilverShop.java b/src/main/java/mod/treestar/shopmod/SilverShop.java deleted file mode 100644 index 0324c2d..0000000 --- a/src/main/java/mod/treestar/shopmod/SilverShop.java +++ /dev/null @@ -1,15 +0,0 @@ -package mod.treestar.shopmod; - -import mod.treestar.shopmod.itemprovider.SilverShopItemProvider; -import org.gotti.wurmunlimited.modloader.interfaces.WurmServerMod; - -import java.util.ArrayList; -import java.util.List; - -public class SilverShop implements WurmServerMod { - - @Override - public void init() { - - } -} diff --git a/src/main/java/mod/treestar/shopmod/SilverShopService.java b/src/main/java/mod/treestar/shopmod/SilverShopService.java deleted file mode 100644 index c2819c8..0000000 --- a/src/main/java/mod/treestar/shopmod/SilverShopService.java +++ /dev/null @@ -1,74 +0,0 @@ -package mod.treestar.shopmod; - -import com.wurmonline.server.players.Player; -import mod.treestar.shopmod.categoryprovider.SilverShopCategoryProvider; -import mod.treestar.shopmod.datamodels.SilverShopCategory; -import mod.treestar.shopmod.datamodels.SilverShopItem; -import mod.treestar.shopmod.datamodels.SilverShopPurchaseOrder; -import mod.treestar.shopmod.itemprovider.SilverShopItemProvider; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; - -public class SilverShopService { - private HashMap categories; - private HashMap items; - private List categoryProviders; - private List itemProviders; - - private static SilverShopService instance; - - public void init() { - for (SilverShopCategoryProvider categoryProvider : categoryProviders) { - - List providerCategories = categoryProvider.getCategories(); - for (SilverShopCategory category : providerCategories) { - if (categories.containsKey(category.getId())) { - // Ignore it. The newer category simply won't update any details. - continue; - } - - categories.put(category.getId(), category); - } - } - for (SilverShopItemProvider itemProvider : itemProviders) { - List providerItems = itemProvider.getItems(); - - } - } - - public boolean canPurchase(SilverShopPurchaseOrder purchaseOrder, Player shopper) { - long totalCost = purchaseOrder.getTotalCost(); - - if(shopper.getMoney() < totalCost) { - return false; - } - - return true; - } - - public boolean attemptPurchase(SilverShopPurchaseOrder purchaseOrder, Player shopper) { - if(!canPurchase(purchaseOrder, shopper)) { - return false; - } - - long totalCost = purchaseOrder.getTotalCost(); - try { - if (shopper.chargeMoney(totalCost)) { - return true; - } - } catch (IOException e) { - return false; - } - - return false; - } - - public static SilverShopService getInstance() { - if(instance == null) { - instance = new SilverShopService(); - } - return instance; - } -} diff --git a/src/main/java/mod/treestar/shopmod/categoryprovider/JsonShopCategoryProvider.java b/src/main/java/mod/treestar/shopmod/categoryprovider/JsonShopCategoryProvider.java new file mode 100644 index 0000000..6b18bd4 --- /dev/null +++ b/src/main/java/mod/treestar/shopmod/categoryprovider/JsonShopCategoryProvider.java @@ -0,0 +1,33 @@ +package mod.treestar.shopmod.categoryprovider; + +import com.wurmonline.server.support.JSONArray; +import com.wurmonline.server.support.JSONTokener; +import mod.treestar.shopmod.datamodels.ShopCategory; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +public class JsonShopCategoryProvider implements ShopCategoryProvider { + private final String categoryJsonPath; + + public JsonShopCategoryProvider(String categoryJsonPath) { + this.categoryJsonPath = categoryJsonPath; + } + + @Override + public List getCategories() { + return Collections.emptyList(); + } + + private void loadCategories() throws IOException { + File file = new File(categoryJsonPath); + try (FileInputStream f = new FileInputStream(file)) { + JSONTokener tokenizer = new JSONTokener(f); + JSONArray typeArray = new JSONArray(tokenizer); + } + } +} diff --git a/src/main/java/mod/treestar/shopmod/categoryprovider/ShopCategoryProvider.java b/src/main/java/mod/treestar/shopmod/categoryprovider/ShopCategoryProvider.java new file mode 100644 index 0000000..410dcdd --- /dev/null +++ b/src/main/java/mod/treestar/shopmod/categoryprovider/ShopCategoryProvider.java @@ -0,0 +1,9 @@ +package mod.treestar.shopmod.categoryprovider; + +import mod.treestar.shopmod.datamodels.ShopCategory; + +import java.util.List; + +public interface ShopCategoryProvider { + List getCategories(); +} diff --git a/src/main/java/mod/treestar/shopmod/categoryprovider/SilverShopCategoryProvider.java b/src/main/java/mod/treestar/shopmod/categoryprovider/SilverShopCategoryProvider.java deleted file mode 100644 index 27f69b7..0000000 --- a/src/main/java/mod/treestar/shopmod/categoryprovider/SilverShopCategoryProvider.java +++ /dev/null @@ -1,10 +0,0 @@ -package mod.treestar.shopmod.categoryprovider; - -import mod.treestar.shopmod.datamodels.SilverShopCategory; - -import java.util.List; - -public interface SilverShopCategoryProvider { - void init(); - List getCategories(); -} diff --git a/src/main/java/mod/treestar/shopmod/currencies/ShopCurrency.java b/src/main/java/mod/treestar/shopmod/currencies/ShopCurrency.java new file mode 100644 index 0000000..c8aab46 --- /dev/null +++ b/src/main/java/mod/treestar/shopmod/currencies/ShopCurrency.java @@ -0,0 +1,9 @@ +package mod.treestar.shopmod.currencies; + +import com.wurmonline.server.players.Player; + +public interface ShopCurrency { + String getDisplay(); + boolean canPlayerAfford(Player player); + boolean chargePlayer(Player player); +} diff --git a/src/main/java/mod/treestar/shopmod/currencies/WurmBankCurrency.java b/src/main/java/mod/treestar/shopmod/currencies/WurmBankCurrency.java new file mode 100644 index 0000000..55f511d --- /dev/null +++ b/src/main/java/mod/treestar/shopmod/currencies/WurmBankCurrency.java @@ -0,0 +1,49 @@ +package mod.treestar.shopmod.currencies; + +import com.wurmonline.server.economy.Change; +import com.wurmonline.server.economy.Economy; +import com.wurmonline.server.players.Player; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Currency backed by a player's Wurm bank balance. + */ +public class WurmBankCurrency implements ShopCurrency { + private static final Logger logger = Logger.getLogger(WurmBankCurrency.class.getName()); + private long ironAmount; + + public WurmBankCurrency() { + } + + public WurmBankCurrency(long ironAmount) { + this.ironAmount = ironAmount; + } + + public void setIronAmount(long ironAmount) { + this.ironAmount = ironAmount; + } + + @Override + public String getDisplay() { + Change bankAmount = Economy.getEconomy().getChangeFor(ironAmount); + return bankAmount.getChangeShortString(); + } + + @Override + public boolean canPlayerAfford(Player player) { + return player.getMoney() >= ironAmount; + } + + @Override + public boolean chargePlayer(Player player) { + try { + return player.chargeMoney(ironAmount); + } catch (IOException e) { + logger.log(Level.WARNING, "An error occurred when charging money for player with wurmId " + player.getWurmId(), e); + return false; + } + } +} diff --git a/src/main/java/mod/treestar/shopmod/datamodels/SilverShopCategory.java b/src/main/java/mod/treestar/shopmod/datamodels/ShopCategory.java similarity index 80% rename from src/main/java/mod/treestar/shopmod/datamodels/SilverShopCategory.java rename to src/main/java/mod/treestar/shopmod/datamodels/ShopCategory.java index 6e545ca..aa8f311 100644 --- a/src/main/java/mod/treestar/shopmod/datamodels/SilverShopCategory.java +++ b/src/main/java/mod/treestar/shopmod/datamodels/ShopCategory.java @@ -5,12 +5,12 @@ import java.util.List; /** * A category containing some number of items for the silver shop. */ -public class SilverShopCategory { +public class ShopCategory { private int id; private String name; private String description; - private List items; + private List items; public int getId() { return id; @@ -36,11 +36,11 @@ public class SilverShopCategory { this.description = description; } - public List getItems() { + public List getItems() { return items; } - public void setItems(List items) { + public void setItems(List items) { this.items = items; } } diff --git a/src/main/java/mod/treestar/shopmod/datamodels/SilverShopItem.java b/src/main/java/mod/treestar/shopmod/datamodels/ShopItem.java similarity index 68% rename from src/main/java/mod/treestar/shopmod/datamodels/SilverShopItem.java rename to src/main/java/mod/treestar/shopmod/datamodels/ShopItem.java index c9411d1..db4ae9c 100644 --- a/src/main/java/mod/treestar/shopmod/datamodels/SilverShopItem.java +++ b/src/main/java/mod/treestar/shopmod/datamodels/ShopItem.java @@ -1,19 +1,21 @@ package mod.treestar.shopmod.datamodels; -import mod.treestar.shopmod.purchasehandlers.SilverShopItemPurchaseEffect; +import mod.treestar.shopmod.purchasehandlers.ShopItemPurchaseEffect; +import mod.treestar.shopmod.currencies.ShopCurrency; /** * Represents a single item for purchase in the silver shop. This may be an in-game item, service, etc. */ -public class SilverShopItem { +public class ShopItem { private int id; private String name; private String description; private String image; - private long ironPrice; private int categoryId; - private SilverShopItemPurchaseEffect purchaseHandler; + private ShopCurrency currency; + + private ShopItemPurchaseEffect purchaseHandler; public int getId() { return id; @@ -47,19 +49,11 @@ public class SilverShopItem { this.image = image; } - public long getIronPrice() { - return ironPrice; - } - - public void setIronPrice(long ironPrice) { - this.ironPrice = ironPrice; - } - - public SilverShopItemPurchaseEffect getPurchaseHandler() { + public ShopItemPurchaseEffect getPurchaseHandler() { return purchaseHandler; } - public void setPurchaseHandler(SilverShopItemPurchaseEffect purchaseHandler) { + public void setPurchaseHandler(ShopItemPurchaseEffect purchaseHandler) { this.purchaseHandler = purchaseHandler; } @@ -70,4 +64,12 @@ public class SilverShopItem { public void setCategoryId(int categoryId) { this.categoryId = categoryId; } + + public ShopCurrency getCurrency() { + return currency; + } + + public void setCurrency(ShopCurrency currency) { + this.currency = currency; + } } diff --git a/src/main/java/mod/treestar/shopmod/datamodels/ShopPurchaseOrder.java b/src/main/java/mod/treestar/shopmod/datamodels/ShopPurchaseOrder.java new file mode 100644 index 0000000..78695bc --- /dev/null +++ b/src/main/java/mod/treestar/shopmod/datamodels/ShopPurchaseOrder.java @@ -0,0 +1,23 @@ +package mod.treestar.shopmod.datamodels; + +import java.util.List; + +/** + * A single purchase in the shop. + */ +public class ShopPurchaseOrder { + private List shoppingCart; + + public List getShoppingCart() { + return shoppingCart; + } + + public void setShoppingCart(List shoppingCart) { + this.shoppingCart = shoppingCart; + } + + public long getTotalCost() { + // Cost calculation will depend on per-item currency; to be implemented alongside currency-aware purchase flow. + return 0L; + } +} diff --git a/src/main/java/mod/treestar/shopmod/datamodels/SilverShopPurchaseOrder.java b/src/main/java/mod/treestar/shopmod/datamodels/SilverShopPurchaseOrder.java deleted file mode 100644 index c5eae7a..0000000 --- a/src/main/java/mod/treestar/shopmod/datamodels/SilverShopPurchaseOrder.java +++ /dev/null @@ -1,22 +0,0 @@ -package mod.treestar.shopmod.datamodels; - -import java.util.List; - -/** - * A single purchase in the shop. - */ -public class SilverShopPurchaseOrder { - private List shoppingCart; - - public List getShoppingCart() { - return shoppingCart; - } - - public void setShoppingCart(List shoppingCart) { - this.shoppingCart = shoppingCart; - } - - public long getTotalCost() { - return getShoppingCart().stream().mapToLong(SilverShopItem::getIronPrice).sum(); - } -} diff --git a/src/main/java/mod/treestar/shopmod/itemprovider/JsonShopItemProvider.java b/src/main/java/mod/treestar/shopmod/itemprovider/JsonShopItemProvider.java new file mode 100644 index 0000000..49382f0 --- /dev/null +++ b/src/main/java/mod/treestar/shopmod/itemprovider/JsonShopItemProvider.java @@ -0,0 +1,35 @@ +package mod.treestar.shopmod.itemprovider; + +import com.wurmonline.server.support.JSONArray; +import com.wurmonline.server.support.JSONTokener; +import mod.treestar.shopmod.datamodels.ShopItem; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * Loads shop items from a JSON file. Parsing will be completed in a later step. + */ +public class JsonShopItemProvider implements ShopItemProvider { + private final String itemJsonPath; + + public JsonShopItemProvider(String itemJsonPath) { + this.itemJsonPath = itemJsonPath; + } + + @Override + public List getItems() { + return Collections.emptyList(); + } + + private void loadItems() throws IOException { + File file = new File(itemJsonPath); + try (FileInputStream f = new FileInputStream(file)) { + JSONTokener tokenizer = new JSONTokener(f); + JSONArray typeArray = new JSONArray(tokenizer); + } + } +} diff --git a/src/main/java/mod/treestar/shopmod/itemprovider/ShopItemProvider.java b/src/main/java/mod/treestar/shopmod/itemprovider/ShopItemProvider.java new file mode 100644 index 0000000..6dc2ecd --- /dev/null +++ b/src/main/java/mod/treestar/shopmod/itemprovider/ShopItemProvider.java @@ -0,0 +1,12 @@ +package mod.treestar.shopmod.itemprovider; + +import mod.treestar.shopmod.datamodels.ShopItem; + +import java.util.List; + +/** + * An interface representing a provider of silver shop items. + */ +public interface ShopItemProvider { + List getItems(); +} diff --git a/src/main/java/mod/treestar/shopmod/itemprovider/SilverShopItemProvider.java b/src/main/java/mod/treestar/shopmod/itemprovider/SilverShopItemProvider.java deleted file mode 100644 index aedac7b..0000000 --- a/src/main/java/mod/treestar/shopmod/itemprovider/SilverShopItemProvider.java +++ /dev/null @@ -1,14 +0,0 @@ -package mod.treestar.shopmod.itemprovider; - -import mod.treestar.shopmod.datamodels.SilverShopCategory; -import mod.treestar.shopmod.datamodels.SilverShopItem; - -import java.util.List; - -/** - * An interface representing a provider of silver shop items. - */ -public interface SilverShopItemProvider { - void init(); - List getItems(); -} diff --git a/src/main/java/mod/treestar/shopmod/purchasehandlers/SilverShopItemPurchaseEffect.java b/src/main/java/mod/treestar/shopmod/purchasehandlers/ShopItemPurchaseEffect.java similarity index 87% rename from src/main/java/mod/treestar/shopmod/purchasehandlers/SilverShopItemPurchaseEffect.java rename to src/main/java/mod/treestar/shopmod/purchasehandlers/ShopItemPurchaseEffect.java index 2fa3d3f..c8e21be 100644 --- a/src/main/java/mod/treestar/shopmod/purchasehandlers/SilverShopItemPurchaseEffect.java +++ b/src/main/java/mod/treestar/shopmod/purchasehandlers/ShopItemPurchaseEffect.java @@ -2,7 +2,7 @@ package mod.treestar.shopmod.purchasehandlers; import com.wurmonline.server.players.Player; -public interface SilverShopItemPurchaseEffect { +public interface ShopItemPurchaseEffect { /** * What happens after a player successfully purchases the item. This assumes the transaction was completed successfully. * @param player the player that performed the purchase diff --git a/src/main/java/mod/treestar/shopmod/purchasehandlers/SilverShopWurmItemPurchaseEffect.java b/src/main/java/mod/treestar/shopmod/purchasehandlers/ShopWurmItemPurchaseEffect.java similarity index 76% rename from src/main/java/mod/treestar/shopmod/purchasehandlers/SilverShopWurmItemPurchaseEffect.java rename to src/main/java/mod/treestar/shopmod/purchasehandlers/ShopWurmItemPurchaseEffect.java index 732010c..ab78843 100644 --- a/src/main/java/mod/treestar/shopmod/purchasehandlers/SilverShopWurmItemPurchaseEffect.java +++ b/src/main/java/mod/treestar/shopmod/purchasehandlers/ShopWurmItemPurchaseEffect.java @@ -1,14 +1,17 @@ package mod.treestar.shopmod.purchasehandlers; import com.wurmonline.server.FailedException; +import com.wurmonline.server.Server; import com.wurmonline.server.items.*; import com.wurmonline.server.players.Player; +import java.util.Random; + /** * Simple item purchase effect that gives a player a specific item on a successful purchase. - * @see SilverShopItemPurchaseEffect + * @see ShopItemPurchaseEffect */ -public class SilverShopWurmItemPurchaseEffect implements SilverShopItemPurchaseEffect { +public class ShopWurmItemPurchaseEffect implements ShopItemPurchaseEffect { private int itemTemplateId; private float ql; private boolean randomQl; @@ -17,7 +20,10 @@ public class SilverShopWurmItemPurchaseEffect implements SilverShopItemPurchaseE @Override public void onPurchase(Player player) { try { - Item item = ItemFactory.createItem(itemTemplateId, ql, (byte) 0, (byte) 0, null); + if(randomQl) { + ql = Server.rand.nextInt(99) + 1; + } + Item item = ItemFactory.createItem(itemTemplateId, ql, (byte) 0, (byte) rarity, null); player.getInventory().insertItem(item); ItemTemplate template = ItemTemplateFactory.getInstance().getTemplate(itemTemplateId); player.sendSystemMessage(String.format("You receive a %s.", template.getName()));