mirror of
https://github.com/Melledy/Nebula.git
synced 2026-09-20 01:29:54 +02:00
Initial Commit
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
package emu.nebula.game.inventory;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import dev.morphia.annotations.Id;
|
||||
import dev.morphia.annotations.Indexed;
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.database.GameDatabaseObject;
|
||||
import emu.nebula.game.player.Player;
|
||||
import emu.nebula.proto.Public.Item;
|
||||
import emu.nebula.util.Utils;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Entity(value = "items", useDiscriminator = false)
|
||||
public class GameItem implements GameDatabaseObject {
|
||||
@Id
|
||||
private ObjectId uid;
|
||||
@Indexed
|
||||
private int playerUid;
|
||||
|
||||
private int itemId;
|
||||
private int count;
|
||||
|
||||
@Deprecated
|
||||
public GameItem() {
|
||||
|
||||
}
|
||||
|
||||
public GameItem(Player player, int id, int count) {
|
||||
this.playerUid = player.getUid();
|
||||
this.itemId = id;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public int add(int amount) {
|
||||
int oldCount = this.count;
|
||||
this.count = Utils.safeAdd(this.count, amount, Integer.MAX_VALUE, 0);
|
||||
return this.count - oldCount;
|
||||
}
|
||||
|
||||
// Database
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
if (this.getCount() <= 0) {
|
||||
if (this.getUid() != null) {
|
||||
Nebula.getGameDatabase().delete(this);
|
||||
}
|
||||
} else {
|
||||
Nebula.getGameDatabase().save(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Proto
|
||||
|
||||
public Item toProto() {
|
||||
var proto = Item.newInstance()
|
||||
.setTid(this.getItemId())
|
||||
.setQty(this.getCount());
|
||||
|
||||
return proto;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package emu.nebula.game.inventory;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import dev.morphia.annotations.Id;
|
||||
import dev.morphia.annotations.Indexed;
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.database.GameDatabaseObject;
|
||||
import emu.nebula.game.player.Player;
|
||||
import emu.nebula.proto.Public.Res;
|
||||
import emu.nebula.util.Utils;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Entity(value = "resources", useDiscriminator = false)
|
||||
public class GameResource implements GameDatabaseObject {
|
||||
@Id
|
||||
private ObjectId uid;
|
||||
@Indexed
|
||||
private int playerUid;
|
||||
|
||||
public int resourceId;
|
||||
public int count;
|
||||
|
||||
@Deprecated // Morphia only
|
||||
public GameResource() {
|
||||
|
||||
}
|
||||
|
||||
public GameResource(Player player, int id, int count) {
|
||||
this.playerUid = player.getUid();
|
||||
this.resourceId = id;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public int add(int amount) {
|
||||
int oldCount = this.count;
|
||||
this.count = Utils.safeAdd(this.count, amount, Integer.MAX_VALUE, 0);
|
||||
return this.count - oldCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
if (this.getCount() <= 0) {
|
||||
if (this.getUid() != null) {
|
||||
Nebula.getGameDatabase().delete(this);
|
||||
}
|
||||
} else {
|
||||
Nebula.getGameDatabase().save(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Proto
|
||||
|
||||
public Res toProto() {
|
||||
var proto = Res.newInstance()
|
||||
.setTid(this.getResourceId())
|
||||
.setQty(this.getCount());
|
||||
|
||||
return proto;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
package emu.nebula.game.inventory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.data.GameData;
|
||||
import emu.nebula.game.player.PlayerManager;
|
||||
import emu.nebula.proto.Public.Item;
|
||||
import emu.nebula.proto.Public.Res;
|
||||
import emu.nebula.game.player.Player;
|
||||
import emu.nebula.game.player.PlayerChangeInfo;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class Inventory extends PlayerManager {
|
||||
private final Int2ObjectMap<GameResource> resources;
|
||||
private final Int2ObjectMap<GameItem> items;
|
||||
|
||||
public Inventory(Player player) {
|
||||
super(player);
|
||||
|
||||
this.resources = new Int2ObjectOpenHashMap<>();
|
||||
this.items = new Int2ObjectOpenHashMap<>();
|
||||
}
|
||||
|
||||
// Resources
|
||||
|
||||
public synchronized int getResourceCount(int id) {
|
||||
var res = this.resources.get(id);
|
||||
return res != null ? res.getCount() : 0;
|
||||
}
|
||||
|
||||
// Items
|
||||
|
||||
public synchronized int getItemCount(int id) {
|
||||
var item = this.getItems().get(id);
|
||||
return item != null ? item.getCount() : 0;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public synchronized PlayerChangeInfo addItem(int id, int count, PlayerChangeInfo changes) {
|
||||
// Changes
|
||||
if (changes == null) {
|
||||
changes = new PlayerChangeInfo();
|
||||
}
|
||||
|
||||
// Sanity
|
||||
if (count == 0) {
|
||||
return changes;
|
||||
}
|
||||
|
||||
// Get game data
|
||||
var data = GameData.getItemDataTable().get(id);
|
||||
if (data == null) {
|
||||
return changes;
|
||||
}
|
||||
|
||||
// Set amount
|
||||
int amount = count;
|
||||
|
||||
// Add item
|
||||
switch (data.getItemType()) {
|
||||
case Res -> {
|
||||
var res = this.resources.get(id);
|
||||
int diff = 0;
|
||||
|
||||
if (amount > 0) {
|
||||
// Add resource
|
||||
if (res == null) {
|
||||
res = new GameResource(this.getPlayer(), id, amount);
|
||||
this.resources.put(res.getResourceId(), res);
|
||||
|
||||
diff = amount;
|
||||
} else {
|
||||
diff = res.add(amount);
|
||||
}
|
||||
|
||||
res.save();
|
||||
} else {
|
||||
// Remove resource
|
||||
if (res == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
diff = res.add(amount);
|
||||
res.save();
|
||||
|
||||
if (res.getCount() < 0) {
|
||||
this.resources.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
if (diff != 0) {
|
||||
var change = Res.newInstance()
|
||||
.setTid(id)
|
||||
.setQty(diff);
|
||||
|
||||
changes.add(change);
|
||||
}
|
||||
}
|
||||
case Item -> {
|
||||
var item = this.items.get(id);
|
||||
int diff = 0;
|
||||
|
||||
if (amount > 0) {
|
||||
// Add resource
|
||||
if (item == null) {
|
||||
item = new GameItem(this.getPlayer(), id, amount);
|
||||
this.items.put(item.getItemId(), item);
|
||||
|
||||
diff = amount;
|
||||
} else {
|
||||
diff = item.add(amount);
|
||||
}
|
||||
|
||||
item.save();
|
||||
} else {
|
||||
// Remove resource
|
||||
if (item == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
diff = item.add(amount);
|
||||
item.save();
|
||||
|
||||
if (item.getCount() < 0) {
|
||||
this.resources.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
if (diff != 0) {
|
||||
var change = Item.newInstance()
|
||||
.setTid(id)
|
||||
.setQty(diff);
|
||||
|
||||
changes.add(change);
|
||||
}
|
||||
}
|
||||
case Disc -> {
|
||||
if (amount <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
var disc = getPlayer().getCharacters().addDisc(id);
|
||||
|
||||
if (disc != null) {
|
||||
changes.add(disc.toProto());
|
||||
}
|
||||
}
|
||||
case Char -> {
|
||||
if (amount <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
var character = getPlayer().getCharacters().addCharacter(id);
|
||||
|
||||
if (character != null) {
|
||||
changes.add(character.toProto());
|
||||
}
|
||||
}
|
||||
case WorldRankExp -> {
|
||||
this.getPlayer().addExp(amount, changes);
|
||||
}
|
||||
default -> {
|
||||
// Not implemented
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return changes;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public synchronized PlayerChangeInfo addItems(List<ItemParam> params, PlayerChangeInfo changes) {
|
||||
// Changes
|
||||
if (changes == null) {
|
||||
changes = new PlayerChangeInfo();
|
||||
}
|
||||
|
||||
for (ItemParam param : params) {
|
||||
this.addItem(param.getId(), param.getCount(), changes);
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
public synchronized PlayerChangeInfo addItems(ItemParamMap params) {
|
||||
return this.addItems(params, null);
|
||||
}
|
||||
|
||||
public synchronized PlayerChangeInfo addItems(ItemParamMap params, PlayerChangeInfo changes) {
|
||||
// Changes
|
||||
if (changes == null) {
|
||||
changes = new PlayerChangeInfo();
|
||||
}
|
||||
|
||||
for (var param : params.getEntrySet()) {
|
||||
this.addItem(param.getIntKey(), param.getIntValue(), changes);
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
public synchronized PlayerChangeInfo removeItem(int id, int count, PlayerChangeInfo changes) {
|
||||
if (count > 0) {
|
||||
count = -count;
|
||||
}
|
||||
|
||||
return this.addItem(id, count, changes);
|
||||
}
|
||||
|
||||
public synchronized PlayerChangeInfo removeItems(ItemParamMap params) {
|
||||
return this.removeItems(params, null);
|
||||
}
|
||||
|
||||
public synchronized PlayerChangeInfo removeItems(ItemParamMap params, PlayerChangeInfo changes) {
|
||||
// Changes
|
||||
if (changes == null) {
|
||||
changes = new PlayerChangeInfo();
|
||||
}
|
||||
|
||||
for (var param : params.getEntrySet()) {
|
||||
this.removeItem(param.getIntKey(), param.getIntValue(), changes);
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player has enough quanity of this item
|
||||
*/
|
||||
public synchronized boolean verifyItem(int id, int count) {
|
||||
// Sanity check
|
||||
if (count == 0) {
|
||||
return true;
|
||||
} else if (count < 0) {
|
||||
// Return false if we are trying to verify negative numbers
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get game data
|
||||
var data = GameData.getItemDataTable().get(id);
|
||||
if (data == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean result = switch (data.getItemType()) {
|
||||
case Res -> {
|
||||
yield this.getResourceCount(id) >= count;
|
||||
}
|
||||
case Item -> {
|
||||
yield this.getItemCount(id) >= count;
|
||||
}
|
||||
case Disc -> {
|
||||
yield getPlayer().getCharacters().hasDisc(id);
|
||||
}
|
||||
case Char -> {
|
||||
yield getPlayer().getCharacters().hasCharacter(id);
|
||||
}
|
||||
default -> {
|
||||
// Not implemented
|
||||
yield false;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
public synchronized boolean verifyItems(ItemParamMap params) {
|
||||
boolean hasItems = true;
|
||||
|
||||
for (var param : params.getEntrySet()) {
|
||||
hasItems = this.verifyItem(param.getIntKey(), param.getIntValue());
|
||||
|
||||
if (!hasItems) {
|
||||
return hasItems;
|
||||
}
|
||||
}
|
||||
|
||||
return hasItems;
|
||||
}
|
||||
|
||||
// Database
|
||||
|
||||
public void loadFromDatabase() {
|
||||
var db = Nebula.getGameDatabase();
|
||||
|
||||
db.getObjects(GameItem.class, "playerUid", getPlayerUid()).forEach(item -> {
|
||||
// Get data
|
||||
var data = GameData.getItemDataTable().get(item.getItemId());
|
||||
if (data == null) return;
|
||||
|
||||
// Add
|
||||
this.items.put(item.getItemId(), item);
|
||||
});
|
||||
|
||||
db.getObjects(GameResource.class, "playerUid", getPlayerUid()).forEach(res -> {
|
||||
// Get data
|
||||
var data = GameData.getItemDataTable().get(res.getResourceId());
|
||||
if (data == null) return;
|
||||
|
||||
// Add
|
||||
this.resources.put(res.getResourceId(), res);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package emu.nebula.game.inventory;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import emu.nebula.proto.Public.ItemTpl;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Entity(useDiscriminator = false)
|
||||
public class ItemParam {
|
||||
public int id;
|
||||
public int count;
|
||||
|
||||
@Deprecated // Morphia only
|
||||
public ItemParam() {
|
||||
|
||||
}
|
||||
|
||||
public ItemParam(int id, int count) {
|
||||
this.id = id;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public ItemTpl toProto() {
|
||||
var proto = ItemTpl.newInstance()
|
||||
.setTid(this.getId())
|
||||
.setQty(this.getCount());
|
||||
|
||||
return proto;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package emu.nebula.game.inventory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import emu.nebula.proto.Public.ItemInfo;
|
||||
import emu.nebula.proto.Public.ItemTpl;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import us.hebi.quickbuf.RepeatedMessage;
|
||||
|
||||
public class ItemParamMap extends Int2IntOpenHashMap {
|
||||
private static final long serialVersionUID = -4186524272780523459L;
|
||||
|
||||
public FastEntrySet entries() {
|
||||
return this.int2IntEntrySet();
|
||||
}
|
||||
|
||||
@Override @Deprecated
|
||||
public int addTo(int itemId, int count) {
|
||||
return this.add(itemId, count);
|
||||
}
|
||||
|
||||
public int add(int itemId, int count) {
|
||||
if (count == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return super.addTo(itemId, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all item params from the other map to this one
|
||||
* @param map The other item param map
|
||||
*/
|
||||
public void add(ItemParamMap map) {
|
||||
for (var entry : map.entries()) {
|
||||
this.add(entry.getIntKey(), entry.getIntValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new ItemParamMap with item amounts multiplied
|
||||
* @param mult Value to multiply all item amounts in this map by
|
||||
* @return
|
||||
*/
|
||||
public ItemParamMap mulitply(int multiplier) {
|
||||
var params = new ItemParamMap();
|
||||
|
||||
for (var entry : this.int2IntEntrySet()) {
|
||||
params.put(entry.getIntKey(), entry.getIntValue() * multiplier);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public FastEntrySet getEntrySet() {
|
||||
return this.int2IntEntrySet();
|
||||
}
|
||||
|
||||
public List<ItemParam> toList() {
|
||||
List<ItemParam> list = new ArrayList<>();
|
||||
|
||||
for (var entry : this.int2IntEntrySet()) {
|
||||
list.add(new ItemParam(entry.getIntKey(), entry.getIntValue()));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public Stream<ItemTpl> itemTemplateStream() {
|
||||
return getEntrySet()
|
||||
.stream()
|
||||
.map(e -> ItemTpl.newInstance().setTid(e.getIntKey()).setQty(e.getIntValue()));
|
||||
}
|
||||
|
||||
// Proto
|
||||
|
||||
public static ItemParamMap fromTemplates(RepeatedMessage<ItemTpl> items) {
|
||||
var map = new ItemParamMap();
|
||||
|
||||
for (var template : items) {
|
||||
map.add(template.getTid(), template.getQty());
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
public static ItemParamMap fromItemInfos(RepeatedMessage<ItemInfo> items) {
|
||||
var map = new ItemParamMap();
|
||||
|
||||
for (var template : items) {
|
||||
map.add(template.getTid(), template.getQty());
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package emu.nebula.game.inventory;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
|
||||
public enum ItemSubType {
|
||||
Res (1),
|
||||
Item (2),
|
||||
Char (3),
|
||||
Energy (4),
|
||||
WorldRankExp (5),
|
||||
CharShard (6),
|
||||
Disc (8),
|
||||
TalentStrengthen (9),
|
||||
DiscStrengthen (12),
|
||||
DiscPromote (13),
|
||||
TreasureBox (17),
|
||||
GearTreasureBox (18),
|
||||
SubNoteSkill (19),
|
||||
SkillStrengthen (24),
|
||||
CharacterLimitBreak (25),
|
||||
MonthlyCard (30),
|
||||
EnergyItem (31),
|
||||
ComCYO (32),
|
||||
OutfitCYO (33),
|
||||
RandomPackage (34),
|
||||
Equipment (35),
|
||||
FateCard (37),
|
||||
EquipmentExp (38),
|
||||
DiscLimitBreak (40),
|
||||
Potential (41),
|
||||
SpecificPotential (42),
|
||||
Honor (43),
|
||||
CharacterYO (44),
|
||||
PlayHead (45),
|
||||
CharacterSkin (46);
|
||||
|
||||
@Getter
|
||||
private final int value;
|
||||
private final static Int2ObjectMap<ItemSubType> map = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
static {
|
||||
for (ItemSubType type : ItemSubType.values()) {
|
||||
map.put(type.getValue(), type);
|
||||
}
|
||||
}
|
||||
|
||||
private ItemSubType(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static ItemSubType getByValue(int value) {
|
||||
return map.get(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package emu.nebula.game.inventory;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
|
||||
public enum ItemType {
|
||||
Res (1),
|
||||
Item (2),
|
||||
Char (3),
|
||||
Energy (4),
|
||||
WorldRankExp (5),
|
||||
RogueItem (6),
|
||||
Disc (7),
|
||||
Equipment (8),
|
||||
CharacterSkin (9),
|
||||
MonthlyCard (10),
|
||||
Title (11),
|
||||
Honor (12),
|
||||
HeadItem (13);
|
||||
|
||||
@Getter
|
||||
private final int value;
|
||||
private final static Int2ObjectMap<ItemType> map = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
static {
|
||||
for (ItemType type : ItemType.values()) {
|
||||
map.put(type.getValue(), type);
|
||||
}
|
||||
}
|
||||
|
||||
private ItemType(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static ItemType getByValue(int value) {
|
||||
return map.get(value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user