Basic loaders implemented
This commit is contained in:
@@ -3,5 +3,10 @@
|
||||
"id": 1,
|
||||
"name": "Consumables",
|
||||
"description": "Limited usage consumable items."
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Services",
|
||||
"description": "Non-item services and boosts."
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -4,7 +4,33 @@
|
||||
"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"
|
||||
"image": "https://www.wurmpedia.com/images/5/5e/Sleep_powder.png",
|
||||
"currency": {
|
||||
"type": "WurmBankCurrency",
|
||||
"ironAmount": 50000
|
||||
},
|
||||
"handler": {
|
||||
"type": "ShopWurmItemPurchaseEffect",
|
||||
"itemTemplateId": 740,
|
||||
"ql": 99.0,
|
||||
"rarity": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"categoryId": 1,
|
||||
"name": "Res Stone",
|
||||
"description": "Gives you one resurrection charge.",
|
||||
"image": "https://www.wurmpedia.com/images/a/aa/Resurrection_stone_icon.png",
|
||||
"currency": {
|
||||
"type": "WurmBankCurrency",
|
||||
"ironAmount": 100000
|
||||
},
|
||||
"handler": {
|
||||
"type": "ShopWurmItemPurchaseEffect",
|
||||
"itemTemplateId": 302,
|
||||
"ql": 99.0,
|
||||
"rarity": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -1,18 +1,25 @@
|
||||
package mod.treestar.shopmod.categoryprovider;
|
||||
|
||||
import com.wurmonline.server.support.JSONArray;
|
||||
import com.wurmonline.server.support.JSONObject;
|
||||
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.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class JsonShopCategoryProvider implements ShopCategoryProvider {
|
||||
private static final Logger logger = Logger.getLogger(JsonShopCategoryProvider.class.getName());
|
||||
|
||||
private final String categoryJsonPath;
|
||||
private long lastModified = -1L;
|
||||
private List<ShopCategory> cachedCategories = Collections.emptyList();
|
||||
|
||||
public JsonShopCategoryProvider(String categoryJsonPath) {
|
||||
this.categoryJsonPath = categoryJsonPath;
|
||||
@@ -20,14 +27,46 @@ public class JsonShopCategoryProvider implements ShopCategoryProvider {
|
||||
|
||||
@Override
|
||||
public List<ShopCategory> getCategories() {
|
||||
return Collections.emptyList();
|
||||
try {
|
||||
maybeReload();
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.WARNING, "Failed loading categories from " + categoryJsonPath, e);
|
||||
}
|
||||
return cachedCategories;
|
||||
}
|
||||
|
||||
private void loadCategories() throws IOException {
|
||||
private void maybeReload() throws IOException {
|
||||
File file = new File(categoryJsonPath);
|
||||
if (!file.exists()) {
|
||||
logger.log(Level.WARNING, "Category file not found at " + categoryJsonPath);
|
||||
cachedCategories = Collections.emptyList();
|
||||
return;
|
||||
}
|
||||
if (file.lastModified() == lastModified) {
|
||||
return; // up to date
|
||||
}
|
||||
try (FileInputStream f = new FileInputStream(file)) {
|
||||
JSONTokener tokenizer = new JSONTokener(f);
|
||||
JSONArray typeArray = new JSONArray(tokenizer);
|
||||
cachedCategories = parseCategories(typeArray);
|
||||
lastModified = file.lastModified();
|
||||
}
|
||||
}
|
||||
|
||||
private List<ShopCategory> parseCategories(JSONArray typeArray) {
|
||||
List<ShopCategory> categories = new ArrayList<>();
|
||||
for (int i = 0; i < typeArray.length(); i++) {
|
||||
JSONObject obj = typeArray.getJSONObject(i);
|
||||
if (!obj.has("id") || !obj.has("name")) {
|
||||
logger.log(Level.WARNING, "Skipping category missing required fields at index " + i);
|
||||
continue;
|
||||
}
|
||||
ShopCategory category = new ShopCategory();
|
||||
category.setId(obj.getInt("id"));
|
||||
category.setName(obj.getString("name"));
|
||||
category.setDescription(obj.optString("description", ""));
|
||||
categories.add(category);
|
||||
}
|
||||
return categories;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,4 +72,15 @@ public class ShopItem {
|
||||
public void setCurrency(ShopCurrency currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Human-readable price for UI/BML display.
|
||||
*/
|
||||
public String getPriceDisplay() {
|
||||
return currency != null ? currency.getDisplay() : "Unavailable";
|
||||
}
|
||||
|
||||
public boolean hasCurrency() {
|
||||
return currency != null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,35 @@
|
||||
package mod.treestar.shopmod.itemprovider;
|
||||
|
||||
import com.wurmonline.server.support.JSONArray;
|
||||
import com.wurmonline.server.support.JSONObject;
|
||||
import com.wurmonline.server.support.JSONTokener;
|
||||
import mod.treestar.shopmod.currencies.ShopCurrency;
|
||||
import mod.treestar.shopmod.currencies.WurmBankCurrency;
|
||||
import mod.treestar.shopmod.datamodels.ShopItem;
|
||||
import mod.treestar.shopmod.purchasehandlers.ShopItemPurchaseEffect;
|
||||
import mod.treestar.shopmod.purchasehandlers.ShopWurmItemPurchaseEffect;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Loads shop items from a JSON file. Parsing will be completed in a later step.
|
||||
* Loads shop items from a JSON file. Expects an array of objects with:
|
||||
* id (int), name (string), description (string, optional), image (string, optional),
|
||||
* categoryId (int), currency (object with type and amount), handler (object describing purchase effect).
|
||||
*/
|
||||
public class JsonShopItemProvider implements ShopItemProvider {
|
||||
private static final Logger logger = Logger.getLogger(JsonShopItemProvider.class.getName());
|
||||
|
||||
private final String itemJsonPath;
|
||||
private long lastModified = -1L;
|
||||
private List<ShopItem> cachedItems = Collections.emptyList();
|
||||
|
||||
public JsonShopItemProvider(String itemJsonPath) {
|
||||
this.itemJsonPath = itemJsonPath;
|
||||
@@ -22,14 +37,97 @@ public class JsonShopItemProvider implements ShopItemProvider {
|
||||
|
||||
@Override
|
||||
public List<ShopItem> getItems() {
|
||||
return Collections.emptyList();
|
||||
try {
|
||||
maybeReload();
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.WARNING, "Failed loading items from " + itemJsonPath, e);
|
||||
}
|
||||
return cachedItems;
|
||||
}
|
||||
|
||||
private void loadItems() throws IOException {
|
||||
private void maybeReload() throws IOException {
|
||||
File file = new File(itemJsonPath);
|
||||
if (!file.exists()) {
|
||||
logger.log(Level.WARNING, "Item file not found at " + itemJsonPath);
|
||||
cachedItems = Collections.emptyList();
|
||||
return;
|
||||
}
|
||||
if (file.lastModified() == lastModified) {
|
||||
return; // up to date
|
||||
}
|
||||
try (FileInputStream f = new FileInputStream(file)) {
|
||||
JSONTokener tokenizer = new JSONTokener(f);
|
||||
JSONArray typeArray = new JSONArray(tokenizer);
|
||||
cachedItems = parseItems(typeArray);
|
||||
lastModified = file.lastModified();
|
||||
}
|
||||
}
|
||||
|
||||
private List<ShopItem> parseItems(JSONArray typeArray) {
|
||||
List<ShopItem> items = new ArrayList<>();
|
||||
for (int i = 0; i < typeArray.length(); i++) {
|
||||
JSONObject obj = typeArray.getJSONObject(i);
|
||||
if (!obj.has("id") || !obj.has("name") || !obj.has("categoryId")) {
|
||||
logger.log(Level.WARNING, "Skipping item missing required fields at index " + i);
|
||||
continue;
|
||||
}
|
||||
ShopItem item = new ShopItem();
|
||||
item.setId(obj.getInt("id"));
|
||||
item.setName(obj.getString("name"));
|
||||
item.setDescription(obj.optString("description", ""));
|
||||
item.setImage(obj.optString("image", ""));
|
||||
item.setCategoryId(obj.getInt("categoryId"));
|
||||
ShopCurrency currency = parseCurrency(obj.optJSONObject("currency"), i);
|
||||
item.setCurrency(currency);
|
||||
ShopItemPurchaseEffect handler = parsePurchaseHandler(obj.optJSONObject("handler"), i);
|
||||
item.setPurchaseHandler(handler);
|
||||
if (currency == null || handler == null) {
|
||||
logger.log(Level.WARNING, "Skipping item at index " + i + " due to missing currency or handler");
|
||||
continue;
|
||||
}
|
||||
items.add(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
private ShopCurrency parseCurrency(JSONObject currencyObj, int index) {
|
||||
if (currencyObj == null) {
|
||||
logger.log(Level.WARNING, "Item at index " + index + " missing currency; item will be unusable");
|
||||
return null;
|
||||
}
|
||||
String type = currencyObj.optString("type", "");
|
||||
switch (type) {
|
||||
case "WurmBankCurrency":
|
||||
long ironAmount = currencyObj.optLong("ironAmount", currencyObj.optLong("priceIron", 0L));
|
||||
return new WurmBankCurrency(ironAmount);
|
||||
default:
|
||||
logger.log(Level.WARNING, "Unknown currency type '" + type + "' for item at index " + index);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private ShopItemPurchaseEffect parsePurchaseHandler(JSONObject handlerObj, int index) {
|
||||
if (handlerObj == null) {
|
||||
logger.log(Level.WARNING, "Item at index " + index + " missing handler; item will be unusable");
|
||||
return null;
|
||||
}
|
||||
String type = handlerObj.optString("type", "");
|
||||
switch (type) {
|
||||
case "ShopWurmItemPurchaseEffect":
|
||||
int templateId = handlerObj.optInt("itemTemplateId", -1);
|
||||
if (templateId <= 0) {
|
||||
logger.log(Level.WARNING, "Handler for item at index " + index + " missing valid itemTemplateId");
|
||||
return null;
|
||||
}
|
||||
ShopWurmItemPurchaseEffect effect = new ShopWurmItemPurchaseEffect();
|
||||
effect.setItemTemplateId(templateId);
|
||||
effect.setQl((float) handlerObj.optDouble("ql", 50));
|
||||
effect.setRandomQl(handlerObj.optBoolean("randomQl", false));
|
||||
effect.setRarity((byte) handlerObj.optInt("rarity", 0));
|
||||
return effect;
|
||||
default:
|
||||
logger.log(Level.WARNING, "Unknown handler type '" + type + "' for item at index " + index);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ 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 ShopItemPurchaseEffect
|
||||
@@ -17,6 +15,22 @@ public class ShopWurmItemPurchaseEffect implements ShopItemPurchaseEffect {
|
||||
private boolean randomQl;
|
||||
private byte rarity;
|
||||
|
||||
public void setItemTemplateId(int itemTemplateId) {
|
||||
this.itemTemplateId = itemTemplateId;
|
||||
}
|
||||
|
||||
public void setQl(float ql) {
|
||||
this.ql = ql;
|
||||
}
|
||||
|
||||
public void setRandomQl(boolean randomQl) {
|
||||
this.randomQl = randomQl;
|
||||
}
|
||||
|
||||
public void setRarity(byte rarity) {
|
||||
this.rarity = rarity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPurchase(Player player) {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user