Skip to content

Commit

Permalink
feat: switch to Fastutil synchronized maps
Browse files Browse the repository at this point in the history
Closes #211
  • Loading branch information
klikli-dev committed Jun 17, 2024
1 parent 861befc commit f9d9134
Show file tree
Hide file tree
Showing 15 changed files with 217 additions and 111 deletions.
22 changes: 11 additions & 11 deletions common/src/main/java/com/klikli_dev/modonomicon/book/Book.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import com.klikli_dev.modonomicon.client.gui.book.BookAddress;
import com.klikli_dev.modonomicon.client.gui.book.markdown.BookTextRenderer;
import com.klikli_dev.modonomicon.util.BookGsonHelper;
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.core.HolderLookup;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
Expand All @@ -24,8 +26,6 @@
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class Book {
protected ResourceLocation id;
Expand All @@ -46,9 +46,9 @@ public class Book {

protected ResourceLocation craftingTexture;
protected ResourceLocation turnPageSound;
protected ConcurrentMap<ResourceLocation, BookCategory> categories;
protected ConcurrentMap<ResourceLocation, BookEntry> entries;
protected ConcurrentMap<ResourceLocation, BookCommand> commands;
protected Map<ResourceLocation, BookCategory> categories;
protected Map<ResourceLocation, BookEntry> entries;
protected Map<ResourceLocation, BookCommand> commands;


protected int defaultTitleColor;
Expand Down Expand Up @@ -97,7 +97,7 @@ public class Book {


public Book(ResourceLocation id, String name, BookTextHolder description, String tooltip, ResourceLocation model, BookDisplayMode displayMode, boolean generateBookItem,
ResourceLocation customBookItem, String creativeTab, ResourceLocation font, ResourceLocation bookOverviewTexture, ResourceLocation frameTexture,
@Nullable ResourceLocation customBookItem, String creativeTab, ResourceLocation font, ResourceLocation bookOverviewTexture, ResourceLocation frameTexture,
BookFrameOverlay topFrameOverlay, BookFrameOverlay bottomFrameOverlay, BookFrameOverlay leftFrameOverlay, BookFrameOverlay rightFrameOverlay,
ResourceLocation bookContentTexture, ResourceLocation craftingTexture, ResourceLocation turnPageSound,
int defaultTitleColor, float categoryButtonIconScale, boolean autoAddReadConditions, int bookTextOffsetX, int bookTextOffsetY, int bookTextOffsetWidth,
Expand Down Expand Up @@ -125,9 +125,9 @@ public Book(ResourceLocation id, String name, BookTextHolder description, String
this.defaultTitleColor = defaultTitleColor;
this.categoryButtonIconScale = categoryButtonIconScale;
this.autoAddReadConditions = autoAddReadConditions;
this.categories = new ConcurrentHashMap<>();
this.entries = new ConcurrentHashMap<>();
this.commands = new ConcurrentHashMap<>();
this.categories = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>());
this.entries = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>());
this.commands = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>());
this.bookTextOffsetX = bookTextOffsetX;
this.bookTextOffsetY = bookTextOffsetY;
this.bookTextOffsetWidth = bookTextOffsetWidth;
Expand Down Expand Up @@ -394,7 +394,7 @@ public void addCommand(BookCommand command) {
this.commands.putIfAbsent(command.id, command);
}

public ConcurrentMap<ResourceLocation, BookCommand> getCommands() {
public Map<ResourceLocation, BookCommand> getCommands() {
return this.commands;
}

Expand Down Expand Up @@ -464,7 +464,7 @@ public ResourceLocation getModel() {
}

public BookDisplayMode getDisplayMode() {
if(this.isLeaflet()) {
if (this.isLeaflet()) {
return BookDisplayMode.INDEX;
}
return this.displayMode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import com.klikli_dev.modonomicon.book.error.BookErrorManager;
import com.klikli_dev.modonomicon.client.gui.book.markdown.BookTextRenderer;
import com.klikli_dev.modonomicon.util.BookGsonHelper;
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.core.HolderLookup;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
Expand All @@ -24,8 +26,6 @@
import java.text.MessageFormat;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class BookCategory {

Expand All @@ -49,7 +49,7 @@ public class BookCategory {
protected float backgroundTextureZoomMultiplier;
protected List<BookCategoryBackgroundParallaxLayer> backgroundParallaxLayers;
protected ResourceLocation entryTextures;
protected ConcurrentMap<ResourceLocation, BookEntry> entries;
protected Map<ResourceLocation, BookEntry> entries;
protected BookCondition condition;
protected boolean showCategoryButton;
/**
Expand Down Expand Up @@ -78,7 +78,7 @@ public BookCategory(ResourceLocation id, String name, BookTextHolder description
this.backgroundTextureZoomMultiplier = backgroundTextureZoomMultiplier;
this.backgroundParallaxLayers = backgroundParallaxLayers;
this.entryTextures = entryTextures;
this.entries = new ConcurrentHashMap<>();
this.entries = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>());
this.entryToOpen = entryToOpen;
this.openEntryToOpenOnlyOnce = openEntryOnlyOnce;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@
import com.klikli_dev.modonomicon.Modonomicon;
import com.klikli_dev.modonomicon.book.entries.BookContentEntry;
import com.klikli_dev.modonomicon.book.page.BookPage;
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.resources.ResourceLocation;
import org.slf4j.helpers.MessageFormatter;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.Map;

public class BookErrorManager {
private static final BookErrorManager instance = new BookErrorManager();

private final ConcurrentMap<ResourceLocation, BookErrorHolder> booksErrors = new ConcurrentHashMap<>();
private final Map<ResourceLocation, BookErrorHolder> booksErrors = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>());
private final BookErrorContextHelper contextHelper = new BookErrorContextHelper();
private ResourceLocation currentBookId;
private String currentContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,35 @@
import com.klikli_dev.modonomicon.util.Codecs;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.world.level.saveddata.SavedData;
import org.jetbrains.annotations.NotNull;

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class BookStatesSaveData extends SavedData {
public static final Codec<BookStatesSaveData> CODEC = RecordCodecBuilder.create((instance) -> instance.group(
Codecs.concurrentMap(Codecs.UUID, BookUnlockStates.CODEC).fieldOf("unlockStates").forGetter((state) -> state.unlockStates),
Codecs.concurrentMap(Codecs.UUID, BookVisualStates.CODEC).fieldOf("visualStates").forGetter((state) -> state.visualStates)
Codec.unboundedMap(Codecs.UUID, BookUnlockStates.CODEC).fieldOf("unlockStates").forGetter((state) -> state.unlockStates),
Codec.unboundedMap(Codecs.UUID, BookVisualStates.CODEC).fieldOf("visualStates").forGetter((state) -> state.visualStates)
).apply(instance, BookStatesSaveData::new));

public static final String ID = "modonomicon_book_states";

public ConcurrentMap<UUID, BookUnlockStates> unlockStates;
public ConcurrentMap<UUID, BookVisualStates> visualStates;
public Map<UUID, BookUnlockStates> unlockStates;
public Map<UUID, BookVisualStates> visualStates;

public BookStatesSaveData() {
this(new ConcurrentHashMap<>(), new ConcurrentHashMap<>());
this(Object2ObjectMaps.emptyMap(), Object2ObjectMaps.emptyMap());
}

public BookStatesSaveData(ConcurrentMap<UUID, BookUnlockStates> unlockStates, ConcurrentMap<UUID, BookVisualStates> visualStates) {
this.unlockStates = unlockStates;
this.visualStates = visualStates;
public BookStatesSaveData(Map<UUID, BookUnlockStates> unlockStates, Map<UUID, BookVisualStates> visualStates) {
this.unlockStates = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>(unlockStates));
this.visualStates = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>(visualStates));

this.setDirty();
}
Expand All @@ -59,7 +61,7 @@ public BookVisualStates getVisualStates(UUID playerUUID) {
}

@Override
public CompoundTag save(CompoundTag compoundTag, HolderLookup.Provider pHolderProvider) {
public @NotNull CompoundTag save(CompoundTag compoundTag, HolderLookup.@NotNull Provider pHolderProvider) {
compoundTag.put("bookStates", CODEC.encodeStart(NbtOps.INSTANCE, this).result().orElseThrow());
return compoundTag;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import net.minecraft.network.FriendlyByteBuf;
Expand All @@ -32,16 +34,15 @@
import net.minecraft.server.level.ServerPlayer;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

public class BookUnlockStates {
public static final Codec<BookUnlockStates> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codecs.concurrentMap(ResourceLocation.CODEC, Codecs.set(ResourceLocation.CODEC)).fieldOf("readEntries").forGetter((s) -> s.readEntries),
Codecs.concurrentMap(ResourceLocation.CODEC, Codecs.mutableMap(ResourceLocation.CODEC, Codecs.set(Codec.INT))).fieldOf("unlockedPages").forGetter((s) -> s.unlockedPages),
Codecs.concurrentMap(ResourceLocation.CODEC, Codecs.set(ResourceLocation.CODEC)).fieldOf("unlockedEntries").forGetter((s) -> s.unlockedEntries),
Codecs.concurrentMap(ResourceLocation.CODEC, Codecs.set(ResourceLocation.CODEC)).fieldOf("unlockedCategories").forGetter((s) -> s.unlockedCategories),
Codecs.concurrentMap(ResourceLocation.CODEC, Codecs.mutableMap(ResourceLocation.CODEC, Codec.INT)).fieldOf("usedCommands").forGetter((s) -> s.usedCommands)
Codec.unboundedMap(ResourceLocation.CODEC, Codecs.set(ResourceLocation.CODEC)).fieldOf("readEntries").forGetter((s) -> s.readEntries),
Codec.unboundedMap(ResourceLocation.CODEC, Codec.unboundedMap(ResourceLocation.CODEC, Codecs.set(Codec.INT))).fieldOf("unlockedPages").forGetter((s) -> s.unlockedPages),
Codec.unboundedMap(ResourceLocation.CODEC, Codecs.set(ResourceLocation.CODEC)).fieldOf("unlockedEntries").forGetter((s) -> s.unlockedEntries),
Codec.unboundedMap(ResourceLocation.CODEC, Codecs.set(ResourceLocation.CODEC)).fieldOf("unlockedCategories").forGetter((s) -> s.unlockedCategories),
Codec.unboundedMap(ResourceLocation.CODEC, Codec.unboundedMap(ResourceLocation.CODEC, Codec.INT)).fieldOf("usedCommands").forGetter((s) -> s.usedCommands)
).apply(instance, BookUnlockStates::new));

public static final StreamCodec<RegistryFriendlyByteBuf, BookUnlockStates> STREAM_CODEC = ByteBufCodecs.fromCodecWithRegistries(CODEC);
Expand All @@ -50,42 +51,53 @@ public class BookUnlockStates {
/**
* Map Book ID to read entry IDs
*/
public ConcurrentMap<ResourceLocation, Set<ResourceLocation>> readEntries;
public Map<ResourceLocation, Set<ResourceLocation>> readEntries;

/**
* Map Book ID to entry IDs to lists of unlocked pages
*/
public ConcurrentMap<ResourceLocation, Map<ResourceLocation, Set<Integer>>> unlockedPages;
public Map<ResourceLocation, Map<ResourceLocation, Set<Integer>>> unlockedPages;

/**
* Map Book ID to unlocked entry IDs
*/
public ConcurrentMap<ResourceLocation, Set<ResourceLocation>> unlockedEntries;
public Map<ResourceLocation, Set<ResourceLocation>> unlockedEntries;

/**
* Map Book ID to unlocked categories IDs
*/
public ConcurrentMap<ResourceLocation, Set<ResourceLocation>> unlockedCategories;
public Map<ResourceLocation, Set<ResourceLocation>> unlockedCategories;

/**
* Map Book ID to commands used. This is never wiped to avoid reusing reward commands.
*/
public ConcurrentMap<ResourceLocation, Map<ResourceLocation, Integer>> usedCommands;
public Map<ResourceLocation, Map<ResourceLocation, Integer>> usedCommands;

public BookUnlockStates() {
this(new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), new ConcurrentHashMap<>());
this(Object2ObjectMaps.emptyMap(), Object2ObjectMaps.emptyMap(), Object2ObjectMaps.emptyMap(), Object2ObjectMaps.emptyMap(), Object2ObjectMaps.emptyMap());
}

public BookUnlockStates(ConcurrentMap<ResourceLocation, Set<ResourceLocation>> readEntries,
ConcurrentMap<ResourceLocation, Map<ResourceLocation, Set<Integer>>> unlockedPages,
ConcurrentMap<ResourceLocation, Set<ResourceLocation>> unlockedEntries,
ConcurrentMap<ResourceLocation, Set<ResourceLocation>> unlockedCategories,
ConcurrentMap<ResourceLocation, Map<ResourceLocation, Integer>> usedCommands) {
this.readEntries = readEntries;
this.unlockedPages = unlockedPages;
this.unlockedEntries = unlockedEntries;
this.unlockedCategories = unlockedCategories;
this.usedCommands = usedCommands;
public BookUnlockStates(Map<ResourceLocation, Set<ResourceLocation>> readEntries,
Map<ResourceLocation, Map<ResourceLocation, Set<Integer>>> unlockedPages,
Map<ResourceLocation, Set<ResourceLocation>> unlockedEntries,
Map<ResourceLocation, Set<ResourceLocation>> unlockedCategories,
Map<ResourceLocation, Map<ResourceLocation, Integer>> usedCommands) {
this.readEntries = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>(readEntries));

this.unlockedPages = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>());
unlockedPages.forEach((bookId, entryPagesMap) -> {
var innerMap = this.unlockedPages.computeIfAbsent(bookId, k -> Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>()));
entryPagesMap.forEach((entryId, pages) -> innerMap.put(entryId, new ObjectOpenHashSet<>(pages)));
});

this.unlockedEntries = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>(unlockedEntries));
this.unlockedCategories = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>(unlockedCategories));

this.usedCommands = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>());
usedCommands.forEach((bookId, commandUsesMap) -> {
var innerMap = this.usedCommands.computeIfAbsent(bookId, k -> Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>()));
innerMap.putAll(commandUsesMap);
});
}

public void update(ServerPlayer owner) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,38 @@
import com.klikli_dev.modonomicon.bookstate.visual.BookVisualState;
import com.klikli_dev.modonomicon.bookstate.visual.CategoryVisualState;
import com.klikli_dev.modonomicon.bookstate.visual.EntryVisualState;
import com.klikli_dev.modonomicon.util.Codecs;
import com.klikli_dev.modonomicon.client.gui.book.BookAddress;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.resources.ResourceLocation;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.List;
import java.util.Map;

public class BookVisualStates {
public static final Codec<BookVisualStates> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codecs.concurrentMap(ResourceLocation.CODEC, BookVisualState.CODEC).fieldOf("bookStates").forGetter((s) -> s.bookStates)
Codec.unboundedMap(ResourceLocation.CODEC, BookVisualState.CODEC).fieldOf("bookStates").forGetter((s) -> s.bookStates),
Codec.unboundedMap(ResourceLocation.CODEC, BookAddress.CODEC.listOf()).fieldOf("bookBookmarks").forGetter((s) -> s.bookBookmarks)
).apply(instance, BookVisualStates::new));

//TODO: make proper stream codec
public static final StreamCodec<ByteBuf, BookVisualStates> STREAM_CODEC = ByteBufCodecs.fromCodec(CODEC);

public Map<ResourceLocation, BookVisualState> bookStates;

public ConcurrentMap<ResourceLocation, BookVisualState> bookStates;
public Map<ResourceLocation, List<BookAddress>> bookBookmarks;

public BookVisualStates() {
this(new ConcurrentHashMap<>());
this(Object2ObjectMaps.emptyMap(), Object2ObjectMaps.emptyMap());
}

public BookVisualStates(ConcurrentMap<ResourceLocation, BookVisualState> bookStates) {
this.bookStates = bookStates;
public BookVisualStates(Map<ResourceLocation, BookVisualState> bookStates, Map<ResourceLocation, List<BookAddress>> bookBookmarks) {
this.bookStates = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>(bookStates));
this.bookBookmarks = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>(bookBookmarks));
}

public BookVisualState getBookState(Book book) {
Expand Down
Loading

0 comments on commit f9d9134

Please sign in to comment.