/*******************************************************************************
* Copyright (C) 2013 JMaNGOS <http://jmangos.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package org.jmangos.commons.entities;
import java.io.Serializable;
import java.nio.ByteOrder;
import java.util.BitSet;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.MappedSuperclass;
import javax.persistence.PostLoad;
import javax.persistence.PostPersist;
import javax.persistence.Transient;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jmangos.commons.dataholder.Streamable;
import org.jmangos.commons.enums.TypeID;
import org.jmangos.commons.enums.TypeMask;
import org.jmangos.commons.enums.UpdateFlags;
import org.jmangos.commons.enums.UpdateType;
import org.jmangos.commons.model.UpdateBlock;
import org.jmangos.commons.update.ObjectFields;
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@MappedSuperclass
public abstract class FieldsObject implements Streamable, Serializable {
/**
*
*/
private static final long serialVersionUID = 4905353224557432822L;
@Transient
protected BitSet bitSet = new BitSet();
@Transient
public static final float DEFAULT_OBJECT_SCALE = 1f;
@Id
@GenericGenerator(name = "seq_id",
strategy = "org.jmangos.commons.model.WowExtendIdGenerator",
parameters = { @Parameter(name = "table_name", value = "wow_sequences") })
@GeneratedValue(generator = "seq_id")
private Long guid;
@Transient
private int type;
@Column(name = "entry",
nullable = false,
insertable = true,
updatable = true,
length = 10,
precision = 0)
private int entry;
@Column(name = "scale",
nullable = false,
insertable = true,
updatable = true,
length = 10,
precision = 0)
private float scale = DEFAULT_OBJECT_SCALE;
@Transient
private byte[] packGuid;
public FieldsObject() {
this.bitSet = new BitSet(getBitSize());
}
@PostLoad
public void initBits() {
packGuid();
setType(TypeMask.OBJECT.getValue());
this.bitSet.set(ObjectFields.OBJECT_FIELD_GUID.getValue());
this.bitSet.set(ObjectFields.OBJECT_FIELD_GUID.getValue() + 1);
this.bitSet.set(ObjectFields.OBJECT_FIELD_SCALE_X.getValue());
}
/**
* @return the movement
*/
public BasicPositionerHolder getMovement() {
return new BasicPositionerHolder();
}
/**
* Override to set proper bit size
*
* @return
*/
protected int getBitSize() {
return ObjectFields.OBJECT_END;
}
@PostPersist
private final void packGuid() {
if (this.guid == null) {
return;
}
long tguid = this.guid;
final byte[] packGUID = new byte[8 + 1];
packGUID[0] = 0;
int size = 1;
for (byte i = 0; i < 8; ++i) {
if ((tguid & 0xFF) > 0) {
packGUID[0] |= (1 << i);
packGUID[size] = (byte) (tguid & 0xFF);
++size;
}
tguid >>= 8;
}
this.packGuid = new byte[size];
for (int i = 0; i < size; i++) {
this.packGuid[i] = packGUID[i];
}
}
/*
* (non-Javadoc)
*
* @see
* org.jmangos.test.id.Streamable#BuildCreateUpdateBlockForPlayer(org.jmangos
* .test.id.Player)
*/
@Override
public void buildCreateBlock(final UpdateBlock updateBlock, final CharacterData characterData) {
final ChannelBuffer buffer = updateBlock.getBuffer();
final UpdateType type = getCreateUpdateType();
buffer.writeByte(type.getValue());
buffer.writeBytes(this.packGuid);
buffer.writeByte(getTypeId().getValue());
final UpdateFlags[] additionFlags = new UpdateFlags[2];
if (this == characterData) {
additionFlags[0] = (UpdateFlags.SELFTARGET);
}
getMovement().buildUpdateBlock(updateBlock.getBuffer(), additionFlags);
buffer.writeBytes(writeValuesUpdate());
updateBlock.icrementCountBlocks();
}
public TypeID getTypeId() {
return TypeID.OBJECT;
}
protected UpdateType getCreateUpdateType() {
return UpdateType.CREATE_OBJECT;
}
/*
* (non-Javadoc)
*
* @see org.jmangos.test.id.Streamable#_write(java.nio.ByteBuffer)
*/
@Override
public ChannelBuffer writeValuesUpdate() {
final byte[] bytesc = this.bitSet.toByteArray();
final ChannelBuffer ocBuffer =
ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, this.bitSet.size() * 32);
final int arraySize =
((bytesc.length % 4) > 0) ? ((bytesc.length / 4) + 1) * 4 : bytesc.length;
ocBuffer.writeByte(arraySize / 4);
ocBuffer.writeBytes(bytesc);
if ((bytesc.length % 4) > 0) {
ocBuffer.writeZero(4 - (bytesc.length % 4));
}
if (this.bitSet.get(ObjectFields.OBJECT_FIELD_GUID.getValue())) {
ocBuffer.writeLong(getGuid());
};
if (this.bitSet.get(ObjectFields.OBJECT_FIELD_TYPE.getValue())) {
ocBuffer.writeInt(getType());
}
if (this.bitSet.get(ObjectFields.OBJECT_FIELD_ENTRY.getValue())) {
ocBuffer.writeInt(getEntry());
}
if (this.bitSet.get(ObjectFields.OBJECT_FIELD_SCALE_X.getValue())) {
ocBuffer.writeFloat(getScale());
}
return ocBuffer;
}
/**
* @return the guid
*/
public final Long getGuid() {
return this.guid;
}
/**
* @param guid
* the guid to set
*/
public final void setGuid(final Long guid) {
this.bitSet.set(ObjectFields.OBJECT_FIELD_GUID.getValue());
this.bitSet.set(ObjectFields.OBJECT_FIELD_GUID.getValue() + 1);
this.guid = guid;
packGuid();
}
/**
* @return the type
*/
public final int getType() {
return this.type;
}
/**
* @param type
* the type to set
*/
public final void setType(final int type) {
this.bitSet.set(ObjectFields.OBJECT_FIELD_TYPE.getValue());
this.type = type;
}
/**
* @return the entry
*/
public final int getEntry() {
return this.entry;
}
/**
* @param entry
* the entry to set
*/
public final void setEntry(final int entry) {
this.bitSet.set(ObjectFields.OBJECT_FIELD_ENTRY.getValue());
this.entry = entry;
}
/**
* @return the scale
*/
public float getScale() {
return this.scale;
}
/**
* @param scale
* the scale to set
*/
public void setScale(final float scale) {
this.bitSet.set(ObjectFields.OBJECT_FIELD_SCALE_X.getValue());
this.scale = scale;
}
/**
* @return the packetGuid
*/
public final byte[] getPacketGuid() {
return this.packGuid;
}
}