Skip to content

Commit 4fc1976

Browse files
Implement deep copies for Chunk Sections (#754)
1 parent 025418d commit 4fc1976

File tree

9 files changed

+66
-6
lines changed

9 files changed

+66
-6
lines changed

src/main/java/com/github/steveice10/mc/protocol/data/game/chunk/BitStorage.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
package com.github.steveice10.mc.protocol.data.game.chunk;
22

3-
import lombok.EqualsAndHashCode;
4-
import lombok.Getter;
5-
import lombok.NonNull;
3+
import lombok.*;
64
import org.jetbrains.annotations.Nullable;
75

86
import java.util.Arrays;
97

8+
@AllArgsConstructor(access = AccessLevel.PRIVATE)
109
@EqualsAndHashCode
1110
public class BitStorage {
1211
private static final int[] MAGIC_VALUES = {
@@ -77,6 +76,11 @@ public BitStorage(int bitsPerEntry, int size, long @Nullable[] data) {
7776
this.divideShift = MAGIC_VALUES[magicIndex + 2];
7877
}
7978

79+
public BitStorage(BitStorage original) {
80+
this(Arrays.copyOf(original.data, original.data.length), original.bitsPerEntry, original.size,
81+
original.maxValue, original.valuesPerLong, original.divideMultiply, original.divideAdd, original.divideShift);
82+
}
83+
8084
public int get(int index) {
8185
if (index < 0 || index > this.size - 1) {
8286
throw new IndexOutOfBoundsException();

src/main/java/com/github/steveice10/mc/protocol/data/game/chunk/ChunkSection.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ public ChunkSection() {
1919
this(0, DataPalette.createForChunk(), DataPalette.createForBiome(4));
2020
}
2121

22+
public ChunkSection(ChunkSection original) {
23+
this(original.blockCount, new DataPalette(original.chunkData), new DataPalette(original.biomeData));
24+
}
25+
2226
public int getBlock(int x, int y, int z) {
2327
return this.chunkData.get(x, y, z);
2428
}
@@ -35,4 +39,4 @@ public void setBlock(int x, int y, int z, int state) {
3539
public boolean isBlockCountEmpty() {
3640
return this.blockCount == 0;
3741
}
38-
}
42+
}

src/main/java/com/github/steveice10/mc/protocol/data/game/chunk/DataPalette.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ public class DataPalette {
1616
private final PaletteType paletteType;
1717
private final int globalPaletteBits;
1818

19+
public DataPalette(DataPalette original) {
20+
this(original.palette.copy(), original.storage == null ? null : new BitStorage(original.storage), original.paletteType, original.globalPaletteBits);
21+
}
22+
1923
public static DataPalette createForChunk() {
2024
return createForChunk(GLOBAL_PALETTE_BITS_PER_ENTRY);
2125
}

src/main/java/com/github/steveice10/mc/protocol/data/game/chunk/palette/GlobalPalette.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,9 @@ public int stateToId(int state) {
2323
public int idToState(int id) {
2424
return id;
2525
}
26+
27+
@Override
28+
public GlobalPalette copy() {
29+
return this;
30+
}
2631
}

src/main/java/com/github/steveice10/mc/protocol/data/game/chunk/palette/ListPalette.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@
22

33
import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper;
44
import io.netty.buffer.ByteBuf;
5+
import lombok.AccessLevel;
6+
import lombok.AllArgsConstructor;
57
import lombok.EqualsAndHashCode;
68
import lombok.Getter;
79

810
import java.io.IOException;
11+
import java.util.Arrays;
912

1013
/**
1114
* A palette backed by a List.
1215
*/
1316
@Getter
1417
@EqualsAndHashCode
18+
@AllArgsConstructor(access = AccessLevel.PRIVATE)
1519
public class ListPalette implements Palette {
1620
private final int maxId;
1721

@@ -65,4 +69,9 @@ public int idToState(int id) {
6569
return 0;
6670
}
6771
}
72+
73+
@Override
74+
public ListPalette copy() {
75+
return new ListPalette(this.maxId, Arrays.copyOf(this.data, this.data.length), this.nextId);
76+
}
6877
}

src/main/java/com/github/steveice10/mc/protocol/data/game/chunk/palette/MapPalette.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@
44
import io.netty.buffer.ByteBuf;
55
import io.netty.util.collection.IntObjectHashMap;
66
import io.netty.util.collection.IntObjectMap;
7+
import lombok.AccessLevel;
8+
import lombok.AllArgsConstructor;
79
import lombok.EqualsAndHashCode;
810

911
import java.io.IOException;
12+
import java.util.Arrays;
1013

1114
/**
1215
* A palette backed by a map.
1316
*/
17+
@AllArgsConstructor(access = AccessLevel.PRIVATE)
1418
@EqualsAndHashCode
1519
public class MapPalette implements Palette {
1620
private final int maxId;
@@ -66,4 +70,11 @@ public int idToState(int id) {
6670
return 0;
6771
}
6872
}
73+
74+
@Override
75+
public MapPalette copy() {
76+
MapPalette mapPalette = new MapPalette(this.maxId, Arrays.copyOf(this.idToState, this.idToState.length), this.nextId);
77+
mapPalette.stateToId.putAll(this.stateToId);
78+
return mapPalette;
79+
}
6980
}

src/main/java/com/github/steveice10/mc/protocol/data/game/chunk/palette/Palette.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public interface Palette {
1818
* @param state Block state to convert.
1919
* @return The resulting storage ID.
2020
*/
21-
public int stateToId(int state);
21+
int stateToId(int state);
2222

2323
/**
2424
* Converts a storage ID to a block state. If the storage ID has no mapping,
@@ -27,5 +27,12 @@ public interface Palette {
2727
* @param id Storage ID to convert.
2828
* @return The resulting block state.
2929
*/
30-
public int idToState(int id);
30+
int idToState(int id);
31+
32+
/**
33+
* Creates a copy of this palette.
34+
* This performs a deep copy of the palette's internal data.
35+
* @return The palette's copy.
36+
*/
37+
Palette copy();
3138
}

src/main/java/com/github/steveice10/mc/protocol/data/game/chunk/palette/SingletonPalette.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,9 @@ public int idToState(int id) {
3333
}
3434
return 0;
3535
}
36+
37+
@Override
38+
public SingletonPalette copy() {
39+
return this;
40+
}
3641
}

src/test/java/com/github/steveice10/mc/protocol/data/ChunkTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,15 @@ public void testChunkSectionEncoding() throws IOException {
5252
Assert.assertEquals("Decoded packet does not match original: " + section + " vs " + decoded, section, decoded);
5353
}
5454
}
55+
56+
@Test
57+
public void testDeepCopy() {
58+
for (ChunkSection section : chunkSectionsToTest) {
59+
ChunkSection copy = new ChunkSection(section);
60+
Assert.assertEquals("Deep copy does not match original: " + section + " vs " + copy, section, copy);
61+
62+
copy.setBlock(1, 1, 1, 10);
63+
Assert.assertNotEquals("Deep copy is not deep: " + section + " vs " + copy, section, copy);
64+
}
65+
}
5566
}

0 commit comments

Comments
 (0)