Properly encode and decode x and z coordinates

This commit is contained in:
Dan Mulloy 2015-06-16 19:48:30 -04:00
parent 06eac8f67b
commit 4e7bff40c0
2 changed files with 65 additions and 36 deletions

View File

@ -47,6 +47,12 @@ public class MultiBlockChangeInfo {
this.chunk = chunk; this.chunk = chunk;
} }
public MultiBlockChangeInfo(Location location, WrappedBlockData data) {
this.data = data;
this.chunk = new ChunkCoordIntPair(location.getBlockX() >> 4, location.getBlockZ() >> 4);
this.setLocation(location);
}
/** /**
* Returns this block change's absolute Location in a given World. * Returns this block change's absolute Location in a given World.
* *
@ -54,7 +60,7 @@ public class MultiBlockChangeInfo {
* @return This block change's absolute Location * @return This block change's absolute Location
*/ */
public Location getLocation(World world) { public Location getLocation(World world) {
return new Location(world, getX(), getY(), getZ()); return new Location(world, getAbsoluteX(), getY(), getAbsoluteZ());
} }
/** /**
@ -63,30 +69,48 @@ public class MultiBlockChangeInfo {
* @param location This block change's new location * @param location This block change's new location
*/ */
public void setLocation(Location location) { public void setLocation(Location location) {
int x = location.getBlockX() - getChunkX() << 4; setLocation(location.getBlockX(), location.getBlockY(), location.getBlockZ());
int y = location.getBlockY(); }
int z = location.getBlockZ() - getChunkZ() << 4;
/**
* Sets this block change's absolute coordinates.
*
* @param x X coordinate
* @param y Y coordinate
* @param z Z coordinate
*/
public void setLocation(int x, int y, int z) {
x = x & 15;
z = z & 15;
this.location = (short) (x << 12 | z << 8 | y); this.location = (short) (x << 12 | z << 8 | y);
} }
/** /**
* Gets this block change's absolute x coordinate * Gets this block change's relative x coordinate.
* *
* @return X coordinate * @return Relative X coordinate
*/ */
public int getX() { public int getX() {
return getChunkX() + (location >> 12 & 15); return location >> 12 & 15;
} }
/** /**
* Sets this block change's absolute x coordinate * Gets this block change's absolute x coordinate.
*
* @return Absolute X coordinate
*/
public int getAbsoluteX() {
return (chunk.getChunkX() << 4) + getX();
}
/**
* Sets this block change's absolute x coordinate.
* *
* @param x New x coordinate * @param x New x coordinate
*/ */
public void setX(int x) { public void setX(int x) {
x -= getChunkX() << 4; setLocation(x, getY(), getZ());
this.location = (short) (x << 12 | getZ() << 8 | getY());
} }
/** /**
@ -104,34 +128,34 @@ public class MultiBlockChangeInfo {
* @param y New y coordinate * @param y New y coordinate
*/ */
public void setY(int y) { public void setY(int y) {
this.location = (short) (getX() << 12 | getZ() << 8 | y); setLocation(getX(), y, getZ());
}
/**
* Gets this block change's relative z coordinate.
*
* @return Relative Z coordinate
*/
public int getZ() {
return location >> 8 & 15;
} }
/** /**
* Gets this block change's absolute z coordinate. * Gets this block change's absolute z coordinate.
* *
* @return Z coordinate * @return Absolute Z coordinate
*/ */
public int getZ() { public int getAbsoluteZ() {
return getChunkZ() + (location >> 8 & 15); return (chunk.getChunkZ() << 4) + getZ();
} }
/** /**
* Sets this block change's absolute z coordinate. * Sets this block change's relative z coordinate.
* *
* @param z New z coordinate * @param z New z coordinate
*/ */
public void setZ(int z) { public void setZ(int z) {
z -= getChunkZ() << 4; setLocation(getX(), getY(), z);
this.location = (short) (getX() << 12 | getZ() << 8 | getY());
}
private int getChunkX() {
return chunk.getChunkX() << 4;
}
private int getChunkZ() {
return chunk.getChunkZ() << 4;
} }
/** /**

View File

@ -18,11 +18,13 @@ package com.comphenix.protocol.wrappers;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import com.comphenix.protocol.BukkitInitialization; import com.comphenix.protocol.BukkitInitialization;
import com.comphenix.protocol.reflect.EquivalentConverter;
import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.utility.MinecraftReflection;
/** /**
@ -38,22 +40,25 @@ public class MultiBlockChangeTest {
@Test @Test
public void test() { public void test() {
int x = 10; int x = 42;
int y = 128; int y = 64;
int z = 7; int z = 70;
short location = (short) (x << 12 | z << 8 | y); Location loc = new Location(null, x, y, z);
ChunkCoordIntPair chunk = new ChunkCoordIntPair(x >> 4, z >> 4);
ChunkCoordIntPair chunk = new ChunkCoordIntPair(1, 2);
WrappedBlockData blockData = WrappedBlockData.createData(Material.STONE); WrappedBlockData blockData = WrappedBlockData.createData(Material.STONE);
MultiBlockChangeInfo info = new MultiBlockChangeInfo(location, blockData, chunk); MultiBlockChangeInfo info = new MultiBlockChangeInfo(loc, blockData);
// Make sure the location is correct
assertEquals(loc, info.getLocation(null));
MultiBlockChangeInfo[] array = { info, info }; MultiBlockChangeInfo[] array = { info, info };
Object generic = MultiBlockChangeInfo.getArrayConverter(chunk).getGeneric(MinecraftReflection.getMultiBlockChangeInfoArrayClass(), EquivalentConverter<MultiBlockChangeInfo[]> converter = MultiBlockChangeInfo.getArrayConverter(chunk);
array); Object generic = converter.getGeneric(MinecraftReflection.getMultiBlockChangeInfoArrayClass(), array);
MultiBlockChangeInfo[] back = MultiBlockChangeInfo.getArrayConverter(chunk).getSpecific(generic); MultiBlockChangeInfo[] back = converter.getSpecific(generic);
// Make sure our conversions are correct
assertEquals(info.getX(), back[0].getX()); assertEquals(info.getX(), back[0].getX());
assertEquals(info.getY(), back[0].getY()); assertEquals(info.getY(), back[0].getY());
assertEquals(info.getZ(), back[0].getZ()); assertEquals(info.getZ(), back[0].getZ());