mirror of
https://github.com/array-in-a-matrix/brainwine.git
synced 2025-04-02 11:11:58 -04:00
Looting & loot tables
This commit is contained in:
parent
0a0ec311fb
commit
a9968c69ee
9 changed files with 1742 additions and 1 deletions
|
@ -42,6 +42,7 @@ public class GameConfiguration {
|
|||
long startTime = System.currentTimeMillis();
|
||||
logger.info("Loading game configuration ...");
|
||||
mapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE, true);
|
||||
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
|
||||
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true);
|
||||
LoaderOptions options = new LoaderOptions();
|
||||
options.setMaxAliasesForCollections(Short.MAX_VALUE);
|
||||
|
|
|
@ -8,6 +8,7 @@ import org.apache.logging.log4j.Logger;
|
|||
|
||||
import brainwine.gameserver.command.CommandManager;
|
||||
import brainwine.gameserver.entity.player.PlayerManager;
|
||||
import brainwine.gameserver.loot.LootManager;
|
||||
import brainwine.gameserver.msgpack.MessagePackHelper;
|
||||
import brainwine.gameserver.server.NetworkRegistry;
|
||||
import brainwine.gameserver.server.Server;
|
||||
|
@ -21,6 +22,7 @@ public class GameServer {
|
|||
private static GameServer instance;
|
||||
private final Thread handlerThread;
|
||||
private final Queue<Runnable> tasks = new ConcurrentLinkedQueue<>();
|
||||
private final LootManager lootManager;
|
||||
private final ZoneManager zoneManager;
|
||||
private final PlayerManager playerManager;
|
||||
private final Server server;
|
||||
|
@ -34,8 +36,9 @@ public class GameServer {
|
|||
logger.info("Starting GameServer ...");
|
||||
CommandManager.init();
|
||||
GameConfiguration.init();
|
||||
StaticZoneGenerator.init();
|
||||
MessagePackHelper.init();
|
||||
lootManager = new LootManager();
|
||||
StaticZoneGenerator.init();
|
||||
zoneManager = new ZoneManager();
|
||||
playerManager = new PlayerManager();
|
||||
NetworkRegistry.init();
|
||||
|
@ -99,6 +102,10 @@ public class GameServer {
|
|||
return shutdownRequested;
|
||||
}
|
||||
|
||||
public LootManager getLootManager() {
|
||||
return lootManager;
|
||||
}
|
||||
|
||||
public ZoneManager getZoneManager() {
|
||||
return zoneManager;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,11 @@ package brainwine.gameserver.entity.player;
|
|||
|
||||
import java.beans.ConstructorProperties;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
@ -24,6 +26,8 @@ import brainwine.gameserver.entity.EntityType;
|
|||
import brainwine.gameserver.entity.FacingDirection;
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.item.ItemRegistry;
|
||||
import brainwine.gameserver.item.LootGraphic;
|
||||
import brainwine.gameserver.loot.Loot;
|
||||
import brainwine.gameserver.server.Message;
|
||||
import brainwine.gameserver.server.messages.BlockMetaMessage;
|
||||
import brainwine.gameserver.server.messages.ConfigurationMessage;
|
||||
|
@ -525,6 +529,44 @@ public class Player extends Entity implements CommandExecutor {
|
|||
return MathUtils.clamp(skills.getOrDefault(skill, 1), 1, MAX_NATURAL_SKILL_LEVEL);
|
||||
}
|
||||
|
||||
public void awardLoot(Loot loot) {
|
||||
awardLoot(loot, LootGraphic.LOOT);
|
||||
}
|
||||
|
||||
public void awardLoot(Loot loot, LootGraphic graphic) {
|
||||
List<Map<String, Object>> notifications = new ArrayList<>();
|
||||
|
||||
loot.getItems().forEach((item, quantity) -> {
|
||||
inventory.addItem(item, quantity);
|
||||
Map<String, Object> notification = new HashMap<>();
|
||||
notification.put("item", item.getId());
|
||||
notification.put("text", String.format("%s x %s", item.getTitle(), quantity));
|
||||
notifications.add(notification);
|
||||
});
|
||||
|
||||
Map<String, Object> dialog = new HashMap<>();
|
||||
Map<String, Object> section = new HashMap<>();
|
||||
section.put("list", notifications);
|
||||
dialog.put("sections", Arrays.asList(section));
|
||||
int crowns = loot.getCrowns();
|
||||
|
||||
if(crowns > 0) {
|
||||
addCrowns(crowns);
|
||||
section.put("text", isV3() ? String.format("<color=#ffd95f>%s shiny crowns!</color>", crowns) : String.format("%s shiny crowns!", crowns));
|
||||
}
|
||||
|
||||
if(isV3()) {
|
||||
dialog.put("title", "You found:");
|
||||
dialog.put("type", graphic);
|
||||
sendMessage(new DialogMessage(0, dialog));
|
||||
} else {
|
||||
section.put("title", "You found:");
|
||||
section.put("text-color", "ffd95f");
|
||||
notify(dialog, NotificationType.REWARD);
|
||||
sendMessage(new EffectMessage(x, y, "chime", 1));
|
||||
}
|
||||
}
|
||||
|
||||
public Inventory getInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,9 @@ public class Item {
|
|||
@JsonProperty("title")
|
||||
private String title;
|
||||
|
||||
@JsonProperty("loot_graphic")
|
||||
private LootGraphic lootGraphic = LootGraphic.NONE;
|
||||
|
||||
@JsonProperty("action")
|
||||
private Action action = Action.NONE;
|
||||
|
||||
|
@ -78,6 +81,9 @@ public class Item {
|
|||
@JsonProperty("crafting quantity")
|
||||
private int craftingQuantity = 1;
|
||||
|
||||
@JsonProperty("loot")
|
||||
private String[] lootCategories = {};
|
||||
|
||||
@JsonProperty("ingredients")
|
||||
private List<CraftingIngredient> ingredients = new ArrayList<>();
|
||||
|
||||
|
@ -128,6 +134,10 @@ public class Item {
|
|||
return id == 0;
|
||||
}
|
||||
|
||||
public LootGraphic getLootGraphic() {
|
||||
return lootGraphic;
|
||||
}
|
||||
|
||||
public Action getAction() {
|
||||
return action;
|
||||
}
|
||||
|
@ -200,6 +210,10 @@ public class Item {
|
|||
return decayInventoryItem == null ? this : decayInventoryItem.get();
|
||||
}
|
||||
|
||||
public String[] getLootCategories() {
|
||||
return lootCategories;
|
||||
}
|
||||
|
||||
public int getCraftingQuantity() {
|
||||
return craftingQuantity;
|
||||
}
|
||||
|
|
|
@ -6,9 +6,11 @@ import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
|
|||
public enum ItemUseType {
|
||||
|
||||
AFTERBURNER,
|
||||
CONTAINER,
|
||||
CREATE_DIALOG,
|
||||
DIALOG,
|
||||
CHANGE,
|
||||
FIELDABLE,
|
||||
FLY,
|
||||
TELEPORT,
|
||||
ZONE_TELEPORT,
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package brainwine.gameserver.item;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
|
||||
|
||||
import brainwine.gameserver.msgpack.EnumValue;
|
||||
import brainwine.gameserver.msgpack.RegisterEnum;
|
||||
|
||||
@RegisterEnum
|
||||
public enum LootGraphic {
|
||||
|
||||
LOOT,
|
||||
LOOT_RED,
|
||||
LOOT_MECH,
|
||||
|
||||
@JsonEnumDefaultValue
|
||||
NONE;
|
||||
|
||||
@EnumValue
|
||||
public String getId() {
|
||||
return toString().toLowerCase();
|
||||
}
|
||||
}
|
46
gameserver/src/main/java/brainwine/gameserver/loot/Loot.java
Normal file
46
gameserver/src/main/java/brainwine/gameserver/loot/Loot.java
Normal file
|
@ -0,0 +1,46 @@
|
|||
package brainwine.gameserver.loot;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.zone.Biome;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Loot {
|
||||
|
||||
@JsonProperty("items")
|
||||
private Map<Item, Integer> items = new HashMap<>();
|
||||
|
||||
@JsonProperty("crowns")
|
||||
private int crowns;
|
||||
|
||||
@JsonProperty("frequency")
|
||||
private int frequency = 1;
|
||||
|
||||
@JsonProperty("biome")
|
||||
private Biome biome;
|
||||
|
||||
@JsonCreator
|
||||
private Loot() {}
|
||||
|
||||
public Map<Item, Integer> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public int getCrowns() {
|
||||
return crowns;
|
||||
}
|
||||
|
||||
public int getFrequency() {
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public Biome getBiome() {
|
||||
return biome;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package brainwine.gameserver.loot;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import brainwine.gameserver.util.WeightedList;
|
||||
import brainwine.gameserver.zone.Biome;
|
||||
|
||||
public class LootManager {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger();
|
||||
private final Map<String, List<Loot>> lootTables = new HashMap<>();
|
||||
|
||||
public LootManager() {
|
||||
loadLootTables();
|
||||
}
|
||||
|
||||
private void loadLootTables() {
|
||||
logger.info("Loading loot tables ...");
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
File file = new File("loottables.json");
|
||||
|
||||
try {
|
||||
if(!file.exists()) {
|
||||
Files.copy(LootManager.class.getResourceAsStream("/loottables.json"), file.toPath());
|
||||
}
|
||||
|
||||
Map<String, List<Loot>> loot = mapper.readValue(file, new TypeReference<Map<String, List<Loot>>>(){});
|
||||
lootTables.putAll(loot);
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to load loot tables", e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Loot> getLootTable(String category) {
|
||||
return lootTables.getOrDefault(category, Collections.emptyList());
|
||||
}
|
||||
|
||||
public List<Loot> getEligibleLoot(int level, Biome biome, String... categories) {
|
||||
List<Loot> eligibleLoot = new ArrayList<>();
|
||||
|
||||
for(String category : categories) {
|
||||
eligibleLoot.addAll(getLootTable(category));
|
||||
}
|
||||
|
||||
eligibleLoot.removeIf(loot -> loot.getBiome() != null && loot.getBiome() != biome);
|
||||
|
||||
if(Math.random() > level * 0.015) {
|
||||
int[] frequencies = {18, 15, 12, 9, 7, 5, 4, 3, 2};
|
||||
int minFrequency = level > frequencies.length ? 1 : frequencies[level - 1];
|
||||
eligibleLoot.removeIf(loot -> loot.getFrequency() < minFrequency);
|
||||
}
|
||||
|
||||
return eligibleLoot;
|
||||
}
|
||||
|
||||
public Loot getRandomLoot(int level, Biome biome, String... categories) {
|
||||
WeightedList<Loot> weightedLoot = new WeightedList<>();
|
||||
List<Loot> eligibleLoot = getEligibleLoot(level, biome, categories);
|
||||
|
||||
for(Loot loot : eligibleLoot) {
|
||||
weightedLoot.addEntry(loot, loot.getFrequency());
|
||||
}
|
||||
|
||||
return weightedLoot.next();
|
||||
}
|
||||
}
|
1528
gameserver/src/main/resources/loottables.json
Normal file
1528
gameserver/src/main/resources/loottables.json
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue