package openblocks.integration;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.google.common.primitives.UnsignedBytes;
import java.util.Map;
import net.minecraft.block.material.MapColor;
import openblocks.common.HeightMapData;
import openblocks.common.HeightMapData.LayerData;
import openblocks.common.tileentity.TileEntityProjector;
import openperipheral.api.adapter.Asynchronous;
import openperipheral.api.adapter.IPeripheralAdapter;
import openperipheral.api.adapter.method.Arg;
import openperipheral.api.adapter.method.ArgType;
import openperipheral.api.adapter.method.IMultiReturn;
import openperipheral.api.adapter.method.ReturnType;
import openperipheral.api.adapter.method.ScriptCallable;
import openperipheral.api.architecture.FeatureGroup;
import openperipheral.api.helpers.MultiReturn;
import org.apache.commons.lang3.ArrayUtils;
@FeatureGroup("openblocks-projector")
public class AdapterProjector implements IPeripheralAdapter {
@Override
public String getSourceId() {
return "openblocks_projector";
}
private static int toInt(Object object) {
return ((Number)object).intValue();
}
@Override
public Class<?> getTargetClass() {
return TileEntityProjector.class;
}
@ScriptCallable(returnTypes = ReturnType.NUMBER, description = "Get current map id")
public Integer getMapId(TileEntityProjector projector) {
int mapId = projector.mapId();
return (mapId >= 0)? mapId : null;
}
@ScriptCallable(returnTypes = ReturnType.TABLE, description = "Get current map info")
public Map<String, Object> getMapInfo(final TileEntityProjector projector) {
HeightMapData data = projector.getMap();
Preconditions.checkState(data.isValid(), "Map not loaded");
Map<String, Object> result = Maps.newHashMap();
result.put("center_x", data.centerX);
result.put("center_z", data.centerZ);
result.put("scale", data.scale);
result.put("dimension", data.dimension);
Map<Integer, Integer> layers = Maps.newHashMap();
for (int i = 0; i < data.layers.length; i++) {
LayerData layerData = data.layers[i];
layers.put(i, UnsignedBytes.toInt(layerData.alpha));
}
result.put("layers", layers);
return result;
}
@ScriptCallable(description = "Set current map info")
public void setMapInfo(TileEntityProjector projector, @Arg(name = "properties", description = "Map of properties", type = ArgType.TABLE) Map<String, Object> args) {
HeightMapData data = projector.getMap();
Preconditions.checkState(data != null && data.isValid(), "Map not loaded");
{
Object value = args.get("center_x");
if (value != null) data.centerX = toInt(value);
}
{
Object value = args.get("center_z");
if (value != null) data.centerZ = toInt(value);
}
{
Object value = args.get("dimension");
if (value != null) data.dimension = toInt(value);
}
{
Object value = args.get("layers");
if (value != null) {
@SuppressWarnings("unchecked")
Map<Integer, Integer> layers = (Map<Integer, Integer>)value;
for (Map.Entry<Integer, Integer> e : layers.entrySet()) {
int index = toInt(e.getKey());
Preconditions.checkElementIndex(index, data.layers.length, "layer index");
LayerData layerData = data.layers[index];
layerData.alpha = (byte)toInt(e.getValue());
}
}
}
projector.markMapDirty();
}
@ScriptCallable(returnTypes = ReturnType.NUMBER, description = "Get displayed map rotation")
public int getRotation(TileEntityProjector projector) {
return projector.rotation();
}
@ScriptCallable(description = "Rotate displayed map rotation")
public void rotate(TileEntityProjector projector,
@Arg(name = "delta", description = "Rotation delta (positive - CW, negative - CCW)") int delta) {
projector.rotate(delta);
}
@Asynchronous
@ScriptCallable(returnTypes = { ReturnType.NUMBER, ReturnType.NUMBER }, description = "Get height and color of point on map")
public IMultiReturn getPoint(TileEntityProjector projector,
@Arg(name = "row", description = "Map row (0..63)") int row,
@Arg(name = "column", description = "Map column (0..63)") int column,
@Arg(name = "layer", description = "Map layer") int layer) {
Preconditions.checkElementIndex(row, 64, "row");
Preconditions.checkElementIndex(column, 64, "column");
HeightMapData data = projector.getMap();
Preconditions.checkState(data != null && data.isValid(), "Map not loaded");
Preconditions.checkElementIndex(layer, data.layers.length, "layer");
int index = 64 * row + column;
LayerData layerData = data.layers[layer];
return MultiReturn.wrap(UnsignedBytes.toInt(layerData.heightMap[index]), layerData.colorMap[index]);
}
@Asynchronous
@ScriptCallable(description = "Get height and color of point on map")
public void setPoint(TileEntityProjector projector,
@Arg(name = "row", description = "Map row (0..63)") int row,
@Arg(name = "column", description = "Map column (0..63)") int column,
@Arg(name = "layer", description = "Map layer") int layer,
@Arg(name = "height", description = "Point height") int height,
@Arg(name = "color", description = "Point color ") int color) {
Preconditions.checkElementIndex(row, 64, "row");
Preconditions.checkElementIndex(column, 64, "column");
Preconditions.checkElementIndex(height, 256, "height");
Preconditions.checkElementIndex(color, MapColor.mapColorArray.length, "color");
HeightMapData data = projector.getMap();
Preconditions.checkState(data != null && data.isValid(), "Map not loaded");
Preconditions.checkElementIndex(layer, data.layers.length, "layer");
int index = 64 * row + column;
LayerData layerData = data.layers[layer];
layerData.heightMap[index] = (byte)height;
layerData.colorMap[index] = (byte)color;
projector.markMapDirty();
}
@ScriptCallable(description = "Clear map")
public void clearMap(TileEntityProjector projector) {
HeightMapData data = projector.getMap();
Preconditions.checkState(data.isValid(), "Map not loaded");
data.layers = new LayerData[0];
projector.markMapDirty();
}
@ScriptCallable(description = "Clear single layer")
public void clearLayer(TileEntityProjector projector,
@Arg(name = "layer", description = "Map layer") int layer) {
HeightMapData data = projector.getMap();
Preconditions.checkState(data.isValid(), "Map not loaded");
Preconditions.checkElementIndex(layer, data.layers.length, "layer");
LayerData newLayer = new LayerData();
newLayer.alpha = (byte)255;
data.layers[layer] = newLayer;
projector.markMapDirty();
}
@ScriptCallable(description = "Append layer")
public void appendLayer(TileEntityProjector projector) {
HeightMapData data = projector.getMap();
Preconditions.checkState(data.isValid(), "Map not loaded");
LayerData newLayer = new LayerData();
newLayer.alpha = (byte)255;
data.layers = ArrayUtils.add(data.layers, newLayer);
projector.markMapDirty();
}
}