mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 09:47:38 +00:00
Fix data cycling the right way. Merged TomyLobo's test changes in.
This commit is contained in:
parent
868fef813f
commit
102e5f142e
@ -583,19 +583,24 @@ public final class BlockData {
|
|||||||
* @return the new data value for the block
|
* @return the new data value for the block
|
||||||
*/
|
*/
|
||||||
public static int cycle(int type, int data, int increment) {
|
public static int cycle(int type, int data, int increment) {
|
||||||
|
if (increment != -1 && increment != 1) {
|
||||||
|
throw new IllegalArgumentException("Increment must be 1 or -1.");
|
||||||
|
}
|
||||||
|
|
||||||
int store;
|
int store;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BlockID.LOG:
|
case BlockID.LOG:
|
||||||
case BlockID.LONG_GRASS:
|
case BlockID.LONG_GRASS:
|
||||||
case BlockID.STONE_BRICK:
|
case BlockID.STONE_BRICK:
|
||||||
case BlockID.SILVERFISH_BLOCK:
|
case BlockID.SILVERFISH_BLOCK:
|
||||||
return (data + increment) % 3;
|
if (data > 2) return -1;
|
||||||
|
return mod((data + increment), 3);
|
||||||
|
|
||||||
case BlockID.TORCH:
|
case BlockID.TORCH:
|
||||||
case BlockID.REDSTONE_TORCH_ON:
|
case BlockID.REDSTONE_TORCH_ON:
|
||||||
case BlockID.REDSTONE_TORCH_OFF:
|
case BlockID.REDSTONE_TORCH_OFF:
|
||||||
if (data < 1 || data > 4) return -1;
|
if (data < 1 || data > 4) return -1;
|
||||||
return (data - 1 + increment) % 4 + 1;
|
return mod((data - 1 + increment), 4) + 1;
|
||||||
|
|
||||||
case BlockID.WOODEN_STAIRS:
|
case BlockID.WOODEN_STAIRS:
|
||||||
case BlockID.COBBLESTONE_STAIRS:
|
case BlockID.COBBLESTONE_STAIRS:
|
||||||
@ -603,31 +608,37 @@ public final class BlockData {
|
|||||||
case BlockID.STONE_BRICK_STAIRS:
|
case BlockID.STONE_BRICK_STAIRS:
|
||||||
case BlockID.PUMPKIN:
|
case BlockID.PUMPKIN:
|
||||||
case BlockID.JACKOLANTERN:
|
case BlockID.JACKOLANTERN:
|
||||||
return (data + increment) % 4;
|
if (data > 3) return -1;
|
||||||
|
return mod((data + increment), 4);
|
||||||
|
|
||||||
case BlockID.STEP:
|
case BlockID.STEP:
|
||||||
case BlockID.DOUBLE_STEP:
|
case BlockID.DOUBLE_STEP:
|
||||||
case BlockID.CAKE_BLOCK:
|
case BlockID.CAKE_BLOCK:
|
||||||
return (data + increment) % 6;
|
if (data > 5) return -1;
|
||||||
|
return mod((data + increment), 6);
|
||||||
|
|
||||||
case BlockID.CROPS:
|
case BlockID.CROPS:
|
||||||
case BlockID.PUMPKIN_STEM:
|
case BlockID.PUMPKIN_STEM:
|
||||||
case BlockID.MELON_STEM:
|
case BlockID.MELON_STEM:
|
||||||
return (data + increment) % 7;
|
if (data > 6) return -1;
|
||||||
|
return mod((data + increment), 7);
|
||||||
|
|
||||||
case BlockID.SOIL:
|
case BlockID.SOIL:
|
||||||
case BlockID.SNOW:
|
if (data > 8) return -1;
|
||||||
return (data + increment) % 9;
|
return mod((data + increment), 9);
|
||||||
|
|
||||||
case BlockID.RED_MUSHROOM_CAP:
|
case BlockID.RED_MUSHROOM_CAP:
|
||||||
case BlockID.BROWN_MUSHROOM_CAP:
|
case BlockID.BROWN_MUSHROOM_CAP:
|
||||||
return (data + increment) % 11;
|
if (data > 10) return -1;
|
||||||
|
return mod((data + increment), 11);
|
||||||
|
|
||||||
case BlockID.CACTUS:
|
case BlockID.CACTUS:
|
||||||
case BlockID.REED:
|
case BlockID.REED:
|
||||||
case BlockID.SIGN_POST:
|
case BlockID.SIGN_POST:
|
||||||
case BlockID.VINE:
|
case BlockID.VINE:
|
||||||
return (data + increment) % 16;
|
case BlockID.SNOW:
|
||||||
|
if (data > 15) return -1;
|
||||||
|
return mod((data + increment), 16);
|
||||||
|
|
||||||
case BlockID.FURNACE:
|
case BlockID.FURNACE:
|
||||||
case BlockID.BURNING_FURNACE:
|
case BlockID.BURNING_FURNACE:
|
||||||
@ -635,31 +646,32 @@ public final class BlockData {
|
|||||||
case BlockID.WALL_SIGN:
|
case BlockID.WALL_SIGN:
|
||||||
case BlockID.LADDER:
|
case BlockID.LADDER:
|
||||||
case BlockID.CHEST:
|
case BlockID.CHEST:
|
||||||
return (data - 2 + increment) % 4 + 2;
|
if (data < 2 || data > 5) return -1;
|
||||||
|
return mod((data - 2 + increment), 4) + 2;
|
||||||
|
|
||||||
case BlockID.REDSTONE_REPEATER_OFF:
|
case BlockID.REDSTONE_REPEATER_OFF:
|
||||||
case BlockID.REDSTONE_REPEATER_ON:
|
case BlockID.REDSTONE_REPEATER_ON:
|
||||||
case BlockID.TRAP_DOOR:
|
case BlockID.TRAP_DOOR:
|
||||||
case BlockID.FENCE_GATE:
|
case BlockID.FENCE_GATE:
|
||||||
case BlockID.LEAVES:
|
case BlockID.LEAVES:
|
||||||
|
if (data > 7) return -1;
|
||||||
store = data & ~0x3;
|
store = data & ~0x3;
|
||||||
return ((data & 0x3) + increment) % 4 | store;
|
return mod(((data & 0x3) + increment), 4) | store;
|
||||||
|
|
||||||
case BlockID.MINECART_TRACKS:
|
case BlockID.MINECART_TRACKS:
|
||||||
if (data < 6 || data > 9) return -1;
|
if (data < 6 || data > 9) return -1;
|
||||||
return (data - 6 + increment) % 4 + 6;
|
return mod((data - 6 + increment), 4) + 6;
|
||||||
|
|
||||||
case BlockID.SAPLING:
|
case BlockID.SAPLING:
|
||||||
|
if ((data & 0x3) == 3 || data > 15) return -1;
|
||||||
store = data & ~0x3;
|
store = data & ~0x3;
|
||||||
return ((data & 0x3) + increment) % 3 | store;
|
return mod(((data & 0x3) + increment), 3) | store;
|
||||||
|
|
||||||
case BlockID.CLOTH:
|
case BlockID.CLOTH:
|
||||||
if (increment > 0) {
|
if (increment == 1) {
|
||||||
data = nextClothColor(data);
|
data = nextClothColor(data);
|
||||||
} else if (increment < 0) {
|
} else if (increment == -1) {
|
||||||
data = prevClothColor(data);
|
data = prevClothColor(data);
|
||||||
} else {
|
|
||||||
return -1; // shouldn't have a 0 increment anyway
|
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
@ -668,6 +680,14 @@ public final class BlockData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Better modulo, not just remainder.
|
||||||
|
*/
|
||||||
|
private static int mod(int x, int y) {
|
||||||
|
int res = x % y;
|
||||||
|
return res < 0 ? res + y : res;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the data value for the next color of cloth in the rainbow. This
|
* Returns the data value for the next color of cloth in the rainbow. This
|
||||||
* should not be used if you want to just increment the data value.
|
* should not be used if you want to just increment the data value.
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.data;
|
package com.sk89q.worldedit.data;
|
||||||
|
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import com.sk89q.worldedit.CuboidClipboard.FlipDirection;
|
import com.sk89q.worldedit.CuboidClipboard.FlipDirection;
|
||||||
@ -26,6 +28,9 @@ import com.sk89q.worldedit.blocks.BlockID;
|
|||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TomyLobo
|
||||||
|
*/
|
||||||
public class BlockDataTest {
|
public class BlockDataTest {
|
||||||
@Test
|
@Test
|
||||||
public void testRotateFlip() {
|
public void testRotateFlip() {
|
||||||
@ -33,23 +38,36 @@ public class BlockDataTest {
|
|||||||
for (int data = 0; data < 16; ++data) {
|
for (int data = 0; data < 16; ++data) {
|
||||||
final String message = type+"/"+data;
|
final String message = type+"/"+data;
|
||||||
|
|
||||||
|
//Test r90(r-90(x))==x
|
||||||
assertEquals(message, data, BlockData.rotate90(type, BlockData.rotate90Reverse(type, data)));
|
assertEquals(message, data, BlockData.rotate90(type, BlockData.rotate90Reverse(type, data)));
|
||||||
|
//Test r-90(r90(x))==x
|
||||||
assertEquals(message, data, BlockData.rotate90Reverse(type, BlockData.rotate90(type, data)));
|
assertEquals(message, data, BlockData.rotate90Reverse(type, BlockData.rotate90(type, data)));
|
||||||
|
|
||||||
int flipped = BlockData.flip(type, BlockData.flip(type, data, FlipDirection.WEST_EAST), FlipDirection.NORTH_SOUTH);
|
final int flipped = BlockData.flip(type, BlockData.flip(type, data, FlipDirection.WEST_EAST), FlipDirection.NORTH_SOUTH);
|
||||||
|
|
||||||
|
//Test r90(r90(x))==flipNS(flipWE(x))
|
||||||
assertEquals(message, flipped, BlockData.rotate90(type, BlockData.rotate90(type, data)));
|
assertEquals(message, flipped, BlockData.rotate90(type, BlockData.rotate90(type, data)));
|
||||||
|
//Test r-90(r-90(x))==flipNS(flipWE(x))
|
||||||
assertEquals(message, flipped, BlockData.rotate90Reverse(type, BlockData.rotate90Reverse(type, data)));
|
assertEquals(message, flipped, BlockData.rotate90Reverse(type, BlockData.rotate90Reverse(type, data)));
|
||||||
|
|
||||||
|
//Test flipNS(flipNS(x))==x
|
||||||
assertEquals(message, data, BlockData.flip(type, BlockData.flip(type, data, FlipDirection.NORTH_SOUTH), FlipDirection.NORTH_SOUTH));
|
assertEquals(message, data, BlockData.flip(type, BlockData.flip(type, data, FlipDirection.NORTH_SOUTH), FlipDirection.NORTH_SOUTH));
|
||||||
|
//Test flipWE(flipWE(x))==x
|
||||||
assertEquals(message, data, BlockData.flip(type, BlockData.flip(type, data, FlipDirection.WEST_EAST), FlipDirection.WEST_EAST));
|
assertEquals(message, data, BlockData.flip(type, BlockData.flip(type, data, FlipDirection.WEST_EAST), FlipDirection.WEST_EAST));
|
||||||
|
//Test flipUD(flipUD(x))==x
|
||||||
assertEquals(message, data, BlockData.flip(type, BlockData.flip(type, data, FlipDirection.UP_DOWN), FlipDirection.UP_DOWN));
|
assertEquals(message, data, BlockData.flip(type, BlockData.flip(type, data, FlipDirection.UP_DOWN), FlipDirection.UP_DOWN));
|
||||||
|
|
||||||
|
//Test r90(r90(r90(r90(x))))==x
|
||||||
|
assertEquals(message, data, BlockData.rotate90(type, BlockData.rotate90(type, BlockData.rotate90(type, BlockData.rotate90(type, data)))));
|
||||||
|
//Test r-90(r-90(r-90(r-90(x))))==x
|
||||||
|
assertEquals(message, data, BlockData.rotate90Reverse(type, BlockData.rotate90Reverse(type, BlockData.rotate90Reverse(type, BlockData.rotate90Reverse(type, data)))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCycle() {
|
public void testCycle() {
|
||||||
|
// Test monotony
|
||||||
for (int type = 0; type < 256; ++type) {
|
for (int type = 0; type < 256; ++type) {
|
||||||
if (type == BlockID.CLOTH)
|
if (type == BlockID.CLOTH)
|
||||||
continue;
|
continue;
|
||||||
@ -57,14 +75,65 @@ public class BlockDataTest {
|
|||||||
for (int data = 0; data < 16; ++data) {
|
for (int data = 0; data < 16; ++data) {
|
||||||
final String message = type+"/"+data;
|
final String message = type+"/"+data;
|
||||||
|
|
||||||
int cycled = BlockData.cycle(type, data, 1);
|
final int cycled = BlockData.cycle(type, data, 1);
|
||||||
|
|
||||||
if (cycled <= data) {
|
if (cycled <= data) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(message, data+1, cycled);
|
assertEquals(message, data+1, cycled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test cyclicity
|
||||||
|
final TreeSet<Integer> datasTemplate = new TreeSet<Integer>();
|
||||||
|
for (int data = 0; data < 16; ++data) {
|
||||||
|
datasTemplate.add(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forwards...
|
||||||
|
for (int type = 0; type < 256; ++type) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final TreeSet<Integer> datas = (TreeSet<Integer>) datasTemplate.clone();
|
||||||
|
while (!datas.isEmpty()) {
|
||||||
|
final int start = datas.pollFirst();
|
||||||
|
String message = type+"/"+start;
|
||||||
|
int current = start;
|
||||||
|
boolean first = true;
|
||||||
|
while (true) {
|
||||||
|
current = BlockData.cycle(type, current, 1);
|
||||||
|
if (first && current == -1) break;
|
||||||
|
first = false;
|
||||||
|
message += "->"+current;
|
||||||
|
assertTrue(message, current >= 0);
|
||||||
|
assertTrue(message, current < 16);
|
||||||
|
if (current == start) break;
|
||||||
|
assertTrue(message, datas.remove(current));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...and backwards
|
||||||
|
for (int type = 0; type < 256; ++type) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final TreeSet<Integer> datas = (TreeSet<Integer>) datasTemplate.clone();
|
||||||
|
while (!datas.isEmpty()) {
|
||||||
|
final int start = datas.pollFirst();
|
||||||
|
String message = type+"/"+start;
|
||||||
|
int current = start;
|
||||||
|
boolean first = true;
|
||||||
|
while (true) {
|
||||||
|
current = BlockData.cycle(type, current, -1);
|
||||||
|
if (first && current == -1) break;
|
||||||
|
first = false;
|
||||||
|
message += "->"+current;
|
||||||
|
assertTrue(message, current >= 0);
|
||||||
|
assertTrue(message, current < 16);
|
||||||
|
if (current == start) break;
|
||||||
|
assertTrue(message, datas.remove(current));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user