diff --git a/src/main/java/emu/lunarcore/database/DatabaseManager.java b/src/main/java/emu/lunarcore/database/DatabaseManager.java index 5a3ec63..834a63a 100644 --- a/src/main/java/emu/lunarcore/database/DatabaseManager.java +++ b/src/main/java/emu/lunarcore/database/DatabaseManager.java @@ -2,6 +2,7 @@ package emu.lunarcore.database; import java.util.stream.Stream; +import org.bson.codecs.configuration.CodecRegistries; import org.reflections.Reflections; import com.mongodb.MongoCommandException; @@ -15,6 +16,7 @@ import de.bwaldvogel.mongo.MongoBackend; import de.bwaldvogel.mongo.MongoServer; import de.bwaldvogel.mongo.backend.h2.H2Backend; import de.bwaldvogel.mongo.backend.memory.MemoryBackend; + import dev.morphia.Datastore; import dev.morphia.DeleteOptions; import dev.morphia.Morphia; @@ -22,10 +24,12 @@ import dev.morphia.annotations.Entity; import dev.morphia.mapping.Mapper; import dev.morphia.mapping.MapperOptions; import dev.morphia.query.filters.Filters; + import emu.lunarcore.Config.DatabaseInfo; import emu.lunarcore.Config.InternalMongoInfo; import emu.lunarcore.LunarCore; import emu.lunarcore.LunarCore.ServerType; +import emu.lunarcore.database.codecs.*; public final class DatabaseManager { private MongoServer server; @@ -48,11 +52,17 @@ public final class DatabaseManager { // Initialize MongoClient gameMongoClient = MongoClients.create(connectionString); + + // Add our custom fastutil codecs + var codecProvider = CodecRegistries.fromCodecs( + new IntSetCodec(), new Int2IntMapCodec() + ); // Set mapper options. MapperOptions mapperOptions = MapperOptions.builder() .storeEmpties(true) .storeNulls(false) + .codecProvider(codecProvider) .build(); // Create data store. diff --git a/src/main/java/emu/lunarcore/database/codecs/Int2IntMapCodec.java b/src/main/java/emu/lunarcore/database/codecs/Int2IntMapCodec.java new file mode 100644 index 0000000..923187e --- /dev/null +++ b/src/main/java/emu/lunarcore/database/codecs/Int2IntMapCodec.java @@ -0,0 +1,43 @@ +package emu.lunarcore.database.codecs; + +import org.bson.BsonReader; +import org.bson.BsonType; +import org.bson.BsonWriter; +import org.bson.codecs.Codec; +import org.bson.codecs.DecoderContext; +import org.bson.codecs.EncoderContext; + +import it.unimi.dsi.fastutil.ints.Int2IntMap; +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; + +/** + * Custom mongodb codec for encoding/decoding fastutil int2int maps. + */ +public class Int2IntMapCodec implements Codec { + + @Override + public Class getEncoderClass() { + return Int2IntMap.class; + } + + @Override + public void encode(BsonWriter writer, Int2IntMap collection, EncoderContext encoderContext) { + writer.writeStartDocument(); + for (var entry : collection.int2IntEntrySet()) { + writer.writeName(Integer.toString(entry.getIntKey())); + writer.writeInt32(entry.getIntValue()); + } + writer.writeEndDocument(); + } + + @Override + public Int2IntMap decode(BsonReader reader, DecoderContext decoderContext) { + Int2IntMap collection = new Int2IntOpenHashMap(); + reader.readStartDocument(); + while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) { + collection.put(Integer.parseInt(reader.readName()), reader.readInt32()); + } + reader.readEndDocument(); + return collection; + } +} \ No newline at end of file diff --git a/src/main/java/emu/lunarcore/database/codecs/IntSetCodec.java b/src/main/java/emu/lunarcore/database/codecs/IntSetCodec.java new file mode 100644 index 0000000..7cfcbc2 --- /dev/null +++ b/src/main/java/emu/lunarcore/database/codecs/IntSetCodec.java @@ -0,0 +1,42 @@ +package emu.lunarcore.database.codecs; + +import org.bson.BsonReader; +import org.bson.BsonType; +import org.bson.BsonWriter; +import org.bson.codecs.Codec; +import org.bson.codecs.DecoderContext; +import org.bson.codecs.EncoderContext; + +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; + +/** + * Custom mongodb codec for encoding/decoding fastutil int sets. + */ +public class IntSetCodec implements Codec { + + @Override + public Class getEncoderClass() { + return IntSet.class; + } + + @Override + public void encode(BsonWriter writer, IntSet collection, EncoderContext encoderContext) { + writer.writeStartArray(); + for (int value : collection) { + writer.writeInt32(value); + } + writer.writeEndArray(); + } + + @Override + public IntSet decode(BsonReader reader, DecoderContext decoderContext) { + IntSet collection = new IntOpenHashSet(); + reader.readStartArray(); + while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) { + collection.add(reader.readInt32()); + } + reader.readEndArray(); + return collection; + } +} \ No newline at end of file diff --git a/src/main/java/emu/lunarcore/game/avatar/AvatarData.java b/src/main/java/emu/lunarcore/game/avatar/AvatarData.java index b68b1be..bc69265 100644 --- a/src/main/java/emu/lunarcore/game/avatar/AvatarData.java +++ b/src/main/java/emu/lunarcore/game/avatar/AvatarData.java @@ -1,10 +1,9 @@ package emu.lunarcore.game.avatar; -import java.util.HashMap; -import java.util.Map; - import dev.morphia.annotations.Entity; import emu.lunarcore.data.excel.AvatarExcel; +import it.unimi.dsi.fastutil.ints.Int2IntMap; +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import lombok.Getter; import lombok.Setter; @@ -16,7 +15,7 @@ public class AvatarData { @Getter @Setter private int rank; // Eidolons @Getter - private Map skills; // Skill tree + private Int2IntMap skills; // Skill tree @Deprecated public AvatarData() { @@ -24,7 +23,7 @@ public class AvatarData { } public AvatarData(AvatarExcel excel) { - this.skills = new HashMap<>(); + this.skills = new Int2IntOpenHashMap(); for (var skillTree : excel.getDefaultSkillTrees()) { this.skills.put(skillTree.getPointID(), skillTree.getLevel()); } diff --git a/src/main/java/emu/lunarcore/game/avatar/GameAvatar.java b/src/main/java/emu/lunarcore/game/avatar/GameAvatar.java index a9ca90e..39497c9 100644 --- a/src/main/java/emu/lunarcore/game/avatar/GameAvatar.java +++ b/src/main/java/emu/lunarcore/game/avatar/GameAvatar.java @@ -1,6 +1,5 @@ package emu.lunarcore.game.avatar; -import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -49,12 +48,12 @@ public class GameAvatar implements GameEntity { private transient AvatarExcel excel; private int avatarId; // Id of avatar + private AvatarData data; @Setter private int level; @Setter private int exp; @Setter private int promotion; - private AvatarData data; - private Set takenRewards; + private IntSet takenRewards; private long timestamp; @Getter(AccessLevel.NONE) private int currentHp; @@ -110,7 +109,7 @@ public class GameAvatar implements GameEntity { public Set getTakenRewards() { if (this.takenRewards == null) { - this.takenRewards = new HashSet<>(); + this.takenRewards = new IntOpenHashSet(); } return this.takenRewards; } diff --git a/src/main/java/emu/lunarcore/game/player/Player.java b/src/main/java/emu/lunarcore/game/player/Player.java index d6e8c71..7695cc5 100644 --- a/src/main/java/emu/lunarcore/game/player/Player.java +++ b/src/main/java/emu/lunarcore/game/player/Player.java @@ -1,6 +1,5 @@ package emu.lunarcore.game.player; -import java.util.HashSet; import java.util.Set; import dev.morphia.annotations.Entity; @@ -50,7 +49,8 @@ import emu.lunarcore.server.packet.send.PacketPlayerSyncScNotify; import emu.lunarcore.server.packet.send.PacketSceneEntityMoveScNotify; import emu.lunarcore.server.packet.send.PacketSyncRogueVirtualItemInfoScNotify; import emu.lunarcore.util.Position; - +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; import lombok.Getter; import lombok.Setter; @@ -83,7 +83,7 @@ public class Player { private int floorId; private int entryId; - private Set unlockedHeadIcons; + private IntSet unlockedHeadIcons; // Player managers private transient GameSession session; @@ -132,7 +132,7 @@ public class Player { this.level = 1; this.stamina = GameConstants.MAX_STAMINA; - this.unlockedHeadIcons = new HashSet<>(); + this.unlockedHeadIcons = new IntOpenHashSet(); this.lineupManager = new LineupManager(this); this.gachaInfo = new PlayerGachaInfo(); @@ -205,7 +205,7 @@ public class Player { public Set getUnlockedHeadIcons() { if (this.unlockedHeadIcons == null) { - this.unlockedHeadIcons = new HashSet<>(); + this.unlockedHeadIcons = new IntOpenHashSet(); } return this.unlockedHeadIcons; }