// Near Infinity - An Infinity Engine Browser and Editor
// Copyright (C) 2001 - 2005 Jon Olav Hauglid
// See LICENSE.txt for license information
package org.infinity.resource.are;
import java.nio.ByteBuffer;
import javax.swing.JComponent;
import org.infinity.datatype.Bitmap;
import org.infinity.datatype.DecNumber;
import org.infinity.datatype.Flag;
import org.infinity.datatype.HexNumber;
import org.infinity.datatype.ResourceRef;
import org.infinity.datatype.StringRef;
import org.infinity.datatype.TextString;
import org.infinity.datatype.Unknown;
import org.infinity.gui.StructViewer;
import org.infinity.resource.AbstractStruct;
import org.infinity.resource.AddRemovable;
import org.infinity.resource.HasAddRemovable;
import org.infinity.resource.HasViewerTabs;
import org.infinity.resource.Profile;
import org.infinity.resource.StructEntry;
import org.infinity.resource.vertex.Vertex;
import org.infinity.util.io.StreamUtils;
public final class Container extends AbstractStruct implements AddRemovable, HasVertices, HasViewerTabs,
HasAddRemovable
{
// ARE/Container-specific field labels
public static final String ARE_CONTAINER = "Container";
public static final String ARE_CONTAINER_NAME = "Name";
public static final String ARE_CONTAINER_LOCATION_X = "Location: X";
public static final String ARE_CONTAINER_LOCATION_Y = "Location: Y";
public static final String ARE_CONTAINER_TYPE = "Type";
public static final String ARE_CONTAINER_LOCK_DIFFICULTY = "Lock difficulty";
public static final String ARE_CONTAINER_FLAGS = "Flags";
public static final String ARE_CONTAINER_TRAP_DETECTION_DIFFICULTY = "Trap detection difficulty";
public static final String ARE_CONTAINER_TRAP_REMOVAL_DIFFICULTY = "Trap removal difficulty";
public static final String ARE_CONTAINER_TRAPPED = "Is trapped?";
public static final String ARE_CONTAINER_TRAP_DETECTED = "Is trap detected?";
public static final String ARE_CONTAINER_LAUNCH_POINT_X = "Launch point: X";
public static final String ARE_CONTAINER_LAUNCH_POINT_Y = "Launch point: Y";
public static final String ARE_CONTAINER_BOUNDING_BOX_LEFT = "Bounding box: Left";
public static final String ARE_CONTAINER_BOUNDING_BOX_TOP = "Bounding box: Top";
public static final String ARE_CONTAINER_BOUNDING_BOX_RIGHT = "Bounding box: Right";
public static final String ARE_CONTAINER_BOUNDING_BOX_BOTTOM = "Bounding box: Bottom";
public static final String ARE_CONTAINER_FIRST_ITEM_INDEX = "First item index";
public static final String ARE_CONTAINER_NUM_ITEMS = "# items";
public static final String ARE_CONTAINER_SCRIPT_TRAP = "Trap script";
public static final String ARE_CONTAINER_FIRST_VERTEX_INDEX = "First vertex index";
public static final String ARE_CONTAINER_NUM_VERTICES = "# vertices";
public static final String ARE_CONTAINER_ACTIVATION_RANGE = "Activation range";
public static final String ARE_CONTAINER_OWNER_NAME = "Owner name";
public static final String ARE_CONTAINER_KEY = "Key";
public static final String ARE_CONTAINER_LOCKPICK_STRING = "Lockpick string";
public static final String[] s_type = { "", "Bag", "Chest", "Drawer", "Pile", "Table", "Shelf",
"Altar", "Non-visible", "Spellbook", "Body", "Barrel", "Crate"};
public static final String[] s_noyes = {"No", "Yes"};
public static final String[] s_flag = { "No flags set", "Locked", "", "Magical lock", "Trap resets",
"", "Disabled" };
public static final String[] s_flag_ee = { "No flags set", "Locked", "", "Magical lock", "Trap resets",
"", "Disabled", "Don't clear" };
public Container() throws Exception
{
super(null, ARE_CONTAINER, StreamUtils.getByteBuffer(192), 0);
}
public Container(AbstractStruct superStruct, ByteBuffer buffer, int offset, int nr) throws Exception
{
super(superStruct, ARE_CONTAINER + " " + nr, buffer, offset);
}
// --------------------- Begin Interface HasAddRemovable ---------------------
@Override
public AddRemovable[] getAddRemovables() throws Exception
{
return new AddRemovable[]{new Vertex(), new Item()};
}
@Override
public AddRemovable confirmAddEntry(AddRemovable entry) throws Exception
{
return entry;
}
@Override
public boolean confirmRemoveEntry(AddRemovable entry) throws Exception
{
return true;
}
// --------------------- End Interface HasAddRemovable ---------------------
//--------------------- Begin Interface AddRemovable ---------------------
@Override
public boolean canRemove()
{
return true;
}
//--------------------- End Interface AddRemovable ---------------------
// --------------------- Begin Interface HasViewerTabs ---------------------
@Override
public int getViewerTabCount()
{
return 1;
}
@Override
public String getViewerTabName(int index)
{
return StructViewer.TAB_VIEW;
}
@Override
public JComponent getViewerTab(int index)
{
return new ViewerContainer(this);
}
@Override
public boolean viewerTabAddedBefore(int index)
{
return true;
}
// --------------------- End Interface HasViewerTabs ---------------------
// --------------------- Begin Interface HasVertices ---------------------
@Override
public void readVertices(ByteBuffer buffer, int offset) throws Exception
{
int firstVertex = ((DecNumber)getAttribute(ARE_CONTAINER_FIRST_VERTEX_INDEX)).getValue();
int numVertices = ((DecNumber)getAttribute(ARE_CONTAINER_NUM_VERTICES)).getValue();
offset += firstVertex << 2;
for (int i = 0; i < numVertices; i++) {
addField(new Vertex(this, buffer, offset + 4 * i, i));
}
}
@Override
public int updateVertices(int offset, int number)
{
((DecNumber)getAttribute(ARE_CONTAINER_FIRST_VERTEX_INDEX)).setValue(number);
int count = 0;
for (int i = 0; i < getFieldCount(); i++) {
StructEntry entry = getField(i);
if (entry instanceof Vertex) {
entry.setOffset(offset);
((Vertex)entry).realignStructOffsets();
offset += 4;
count++;
}
}
((DecNumber)getAttribute(ARE_CONTAINER_NUM_VERTICES)).setValue(count);
return count;
}
// --------------------- End Interface HasVertices ---------------------
@Override
protected void setAddRemovableOffset(AddRemovable datatype)
{
if (datatype instanceof Vertex) {
int index = ((DecNumber)getAttribute(ARE_CONTAINER_FIRST_VERTEX_INDEX)).getValue();
index += ((DecNumber)getAttribute(ARE_CONTAINER_NUM_VERTICES)).getValue();
int offset = ((HexNumber)getSuperStruct().getAttribute(AreResource.ARE_OFFSET_VERTICES)).getValue();
datatype.setOffset(offset + 4 * index);
((AbstractStruct)datatype).realignStructOffsets();
}
else if (datatype instanceof Item) {
int index = ((DecNumber)getAttribute(ARE_CONTAINER_FIRST_ITEM_INDEX)).getValue();
index += ((DecNumber)getAttribute(ARE_CONTAINER_NUM_ITEMS)).getValue();
int offset = ((HexNumber)getSuperStruct().getAttribute(AreResource.ARE_OFFSET_ITEMS)).getValue();
datatype.setOffset(offset + 20 * index);
((AbstractStruct)datatype).realignStructOffsets();
}
}
public void readItems(ByteBuffer buffer, int offset) throws Exception
{
int firstIndex = ((DecNumber)getAttribute(ARE_CONTAINER_FIRST_ITEM_INDEX)).getValue();
int numItems = ((DecNumber)getAttribute(ARE_CONTAINER_NUM_ITEMS)).getValue();
offset += firstIndex * 20;
for (int i = 0; i < numItems; i++) {
addField(new Item(this, buffer, offset + 20 * i, i));
}
// return offset + numItems * 20;
}
public int updateItems(int offset, int number)
{
((DecNumber)getAttribute(ARE_CONTAINER_FIRST_ITEM_INDEX)).setValue(number);
int count = 0;
for (int i = 0; i < getFieldCount(); i++) {
StructEntry entry = getField(i);
if (entry instanceof Item) {
entry.setOffset(offset);
((Item)entry).realignStructOffsets();
offset += 20;
count++;
}
}
((DecNumber)getAttribute(ARE_CONTAINER_NUM_ITEMS)).setValue(count);
return count;
}
@Override
public int read(ByteBuffer buffer, int offset) throws Exception
{
addField(new TextString(buffer, offset, 32, ARE_CONTAINER_NAME));
addField(new DecNumber(buffer, offset + 32, 2, ARE_CONTAINER_LOCATION_X));
addField(new DecNumber(buffer, offset + 34, 2, ARE_CONTAINER_LOCATION_Y));
addField(new Bitmap(buffer, offset + 36, 2, ARE_CONTAINER_TYPE, s_type));
addField(new DecNumber(buffer, offset + 38, 2, ARE_CONTAINER_LOCK_DIFFICULTY));
if (Profile.isEnhancedEdition()) {
addField(new Flag(buffer, offset + 40, 4, ARE_CONTAINER_FLAGS, s_flag_ee));
} else {
addField(new Flag(buffer, offset + 40, 4, ARE_CONTAINER_FLAGS, s_flag));
}
addField(new DecNumber(buffer, offset + 44, 2, ARE_CONTAINER_TRAP_DETECTION_DIFFICULTY));
addField(new DecNumber(buffer, offset + 46, 2, ARE_CONTAINER_TRAP_REMOVAL_DIFFICULTY));
addField(new Bitmap(buffer, offset + 48, 2, ARE_CONTAINER_TRAPPED, s_noyes));
addField(new Bitmap(buffer, offset + 50, 2, ARE_CONTAINER_TRAP_DETECTED, s_noyes));
addField(new DecNumber(buffer, offset + 52, 2, ARE_CONTAINER_LAUNCH_POINT_X));
addField(new DecNumber(buffer, offset + 54, 2, ARE_CONTAINER_LAUNCH_POINT_Y));
addField(new DecNumber(buffer, offset + 56, 2, ARE_CONTAINER_BOUNDING_BOX_LEFT));
addField(new DecNumber(buffer, offset + 58, 2, ARE_CONTAINER_BOUNDING_BOX_TOP));
addField(new DecNumber(buffer, offset + 60, 2, ARE_CONTAINER_BOUNDING_BOX_RIGHT));
addField(new DecNumber(buffer, offset + 62, 2, ARE_CONTAINER_BOUNDING_BOX_BOTTOM));
addField(new DecNumber(buffer, offset + 64, 4, ARE_CONTAINER_FIRST_ITEM_INDEX));
addField(new DecNumber(buffer, offset + 68, 4, ARE_CONTAINER_NUM_ITEMS));
addField(new ResourceRef(buffer, offset + 72, ARE_CONTAINER_SCRIPT_TRAP, "BCS"));
addField(new DecNumber(buffer, offset + 80, 4, ARE_CONTAINER_FIRST_VERTEX_INDEX));
addField(new DecNumber(buffer, offset + 84, 2, ARE_CONTAINER_NUM_VERTICES));
addField(new DecNumber(buffer, offset + 86, 2, ARE_CONTAINER_ACTIVATION_RANGE));
addField(new TextString(buffer, offset + 88, 32, ARE_CONTAINER_OWNER_NAME));
addField(new ResourceRef(buffer, offset + 120, ARE_CONTAINER_KEY, "ITM"));
addField(new Unknown(buffer, offset + 128, 4));
addField(new StringRef(buffer, offset + 132, ARE_CONTAINER_LOCKPICK_STRING));
addField(new Unknown(buffer, offset + 136, 56));
return offset + 192;
}
}