Add custom morphia codecs for fastutil collections

This commit is contained in:
Melledy
2023-11-03 20:29:23 -07:00
parent 4e95c717dd
commit d4cf19790e
6 changed files with 107 additions and 14 deletions

View File

@@ -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.

View File

@@ -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<Int2IntMap> {
@Override
public Class<Int2IntMap> 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;
}
}

View File

@@ -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<IntSet> {
@Override
public Class<IntSet> 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;
}
}

View File

@@ -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<Integer, Integer> 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());
}

View File

@@ -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<Integer> takenRewards;
private IntSet takenRewards;
private long timestamp;
@Getter(AccessLevel.NONE) private int currentHp;
@@ -110,7 +109,7 @@ public class GameAvatar implements GameEntity {
public Set<Integer> getTakenRewards() {
if (this.takenRewards == null) {
this.takenRewards = new HashSet<>();
this.takenRewards = new IntOpenHashSet();
}
return this.takenRewards;
}

View File

@@ -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<Integer> 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<Integer> getUnlockedHeadIcons() {
if (this.unlockedHeadIcons == null) {
this.unlockedHeadIcons = new HashSet<>();
this.unlockedHeadIcons = new IntOpenHashSet();
}
return this.unlockedHeadIcons;
}