--- a/net/minecraft/world/level/chunk/HashMapPalette.java
+++ b/net/minecraft/world/level/chunk/HashMapPalette.java
@@ -8,19 +_,26 @@
 import net.minecraft.network.VarInt;
 import net.minecraft.util.CrudeIncrementalIntIdentityHashBiMap;
 
-public class HashMapPalette<T> implements Palette<T> {
+public class HashMapPalette<T> implements Palette<T>, ca.spottedleaf.moonrise.patches.fast_palette.FastPalette<T> { // Paper - optimise palette reads
     private final IdMap<T> registry;
     private final CrudeIncrementalIntIdentityHashBiMap<T> values;
     private final PaletteResize<T> resizeHandler;
     private final int bits;
 
+    // Paper start - optimise palette reads
+    @Override
+    public final T[] moonrise$getRawPalette(final ca.spottedleaf.moonrise.patches.fast_palette.FastPaletteData<T> container) {
+        return ((ca.spottedleaf.moonrise.patches.fast_palette.FastPalette<T>)this.values).moonrise$getRawPalette(container);
+    }
+    // Paper end - optimise palette reads
+
     public HashMapPalette(IdMap<T> registry, int bits, PaletteResize<T> resizeHandler, List<T> values) {
         this(registry, bits, resizeHandler);
         values.forEach(this.values::add);
     }
 
     public HashMapPalette(IdMap<T> registry, int bits, PaletteResize<T> resizeHandler) {
-        this(registry, bits, resizeHandler, CrudeIncrementalIntIdentityHashBiMap.create(1 << bits));
+        this(registry, bits, resizeHandler, CrudeIncrementalIntIdentityHashBiMap.create((1 << bits) + 1)); // Paper - Perf: Avoid unnecessary resize operation in CrudeIncrementalIntIdentityHashBiMap
     }
 
     private HashMapPalette(IdMap<T> registry, int bits, PaletteResize<T> resizeHandler, CrudeIncrementalIntIdentityHashBiMap<T> values) {
@@ -38,10 +_,16 @@
     public int idFor(T state) {
         int id = this.values.getId(state);
         if (id == -1) {
-            id = this.values.add(state);
-            if (id >= 1 << this.bits) {
+            // Paper start - Perf: Avoid unnecessary resize operation in CrudeIncrementalIntIdentityHashBiMap and optimize
+            // We use size() instead of the result from add(K)
+            // This avoids adding another object unnecessarily
+            // Without this change, + 2 would be required in the constructor
+            if (this.values.size() >= 1 << this.bits) {
                 id = this.resizeHandler.onResize(this.bits + 1, state);
+            } else {
+                id = this.values.add(state);
             }
+            // Paper end - Perf: Avoid unnecessary resize operation in CrudeIncrementalIntIdentityHashBiMap and optimize
         }
 
         return id;
