cn.liutils.api.player.ControlData.java Source code

Java tutorial

Introduction

Here is the source code for cn.liutils.api.player.ControlData.java

Source

/**
 * Copyright (c) Lambda Innovation, 2013-2015
 * ??Lambda Innovation
 * http://www.li-dev.cn/
 *
 * This project is open-source, and it is distributed under 
 * the terms of GNU General Public License. You can modify
 * and distribute freely as long as you follow the license.
 * ??GNU???
 * ????
 * http://www.gnu.org/licenses/gpl.html
 */
package cn.liutils.api.player;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import cn.liutils.api.player.state.StateBase;
import cn.liutils.api.player.state.StateBase.StateType;
import cn.liutils.api.player.state.StateLockControlJump;
import cn.liutils.api.player.state.StateLockControlMove;
import cn.liutils.api.player.state.StateLockControlSpin;
import cn.liutils.api.player.state.StateLockPosition;
import cn.liutils.api.player.state.StateLockRotation;
import cn.liutils.core.LIUtils;
import cn.liutils.core.player.MsgControlSyncAll;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraftforge.common.IExtendedEntityProperties;

/**
 * 
 * @author Violet
 *
 */
public class ControlData implements IExtendedEntityProperties {

    public static final String IDENTIFIER = "li_con";

    /**
     * Get the data
     */
    public static ControlData get(Entity entity) {
        return (ControlData) entity.getExtendedProperties(IDENTIFIER);
    }

    private final EntityPlayer player;

    private StateBase[] state = new StateBase[StateType.values().length];

    private boolean shouldSync;

    public ControlData(EntityPlayer host) {
        player = host;
    }

    public ControlData(EntityPlayer host, ByteBuf data) {
        this(host);
        fromBytes(data);
    }

    /**
     * Set state
     * @param ticks Ticks to cancel the state and negative for infinite
     */
    public void stateSet(StateType type, int ticks) {
        if (state[type.ordinal()] == null) {
            switch (type) {
            case LOCK_POSITION:
                state[type.ordinal()] = new StateLockPosition(player, ticks);
                break;
            case LOCK_ROTATION:
                state[type.ordinal()] = new StateLockRotation(player, ticks);
                break;
            case LOCK_CONTROL_MOVE:
                state[type.ordinal()] = new StateLockControlMove(player, ticks);
                break;
            case LOCK_CONTROL_JUMP:
                state[type.ordinal()] = new StateLockControlJump(player, ticks);
                break;
            case LOCK_CONTROL_SPIN:
                state[type.ordinal()] = new StateLockControlSpin(player, ticks);
                break;
            default:
                LIUtils.log.warn("Not supported yet: " + type);
            }
        } else
            state[type.ordinal()].setTick(ticks);
        shouldSync = true;
    }

    /**
     * Modify state
     * @param ticks Positive for increase while negative for decrease
     */
    public void stateModify(StateType type, int ticks) {
        if (state[type.ordinal()] != null)
            state[type.ordinal()].modifyTick(ticks);
        shouldSync = true;
    }

    /**
     * Cancel some state
     */
    public void stateCancel(StateType type) {
        if (state[type.ordinal()] != null)
            state[type.ordinal()].cancel();
        shouldSync = true;
    }

    /**
     * Called by ControlManager
     */
    public void tickSync() {
        if (shouldSync)
            syncAll();
    }

    /**
     * Never call it directly
     */
    public void tick() {
        for (int i = 0; i < state.length; ++i)
            if (state[i] != null && state[i].tick())
                state[i] = null;
    }

    private void stateCancelAll() {
        for (int i = 0; i < state.length; ++i)
            if (state[i] != null) {
                state[i].cancel();
                state[i] = null;
            }
    }

    private void clear() {
        stateCancelAll();
    }

    public void syncAll() {
        shouldSync = false;
        LIUtils.netHandler.sendTo(new MsgControlSyncAll(this), (EntityPlayerMP) player);
    }

    public void copyFrom(ControlData cd) {
        clear();
        state = cd.state.clone();
    }

    public void fromBytes(ByteBuf buf) {
        clear();
        while (buf.isReadable()) {
            byte tp = buf.readByte();
            switch (tp) {
            case 0:
                while (buf.isReadable()) {
                    byte pre = buf.readByte();
                    if (pre == -1)
                        break;
                    if (pre == StateType.LOCK_POSITION.ordinal()) {
                        state[pre] = new StateLockPosition(player, buf);
                    }
                    if (pre == StateType.LOCK_ROTATION.ordinal()) {
                        state[pre] = new StateLockRotation(player, buf);
                    }
                    if (pre == StateType.LOCK_CONTROL_MOVE.ordinal()) {
                        state[pre] = new StateLockControlMove(player, buf);
                    }
                    if (pre == StateType.LOCK_CONTROL_JUMP.ordinal()) {
                        state[pre] = new StateLockControlJump(player, buf);
                    }
                    if (pre == StateType.LOCK_CONTROL_SPIN.ordinal()) {
                        state[pre] = new StateLockControlSpin(player, buf);
                    }
                }
                break;
            case -1:
                return;
            default:
                LIUtils.log.warn("Unknown type: " + tp);
            }
        }
    }

    public void toBytes(ByteBuf buf) {
        buf.writeByte(0);
        for (StateBase lb : state)
            if (lb != null) {
                buf.writeByte(lb.type.ordinal());
                lb.toBytes(buf);
            }
        buf.writeByte(-1);

        buf.writeByte(-1);
    }

    @Override
    public void saveNBTData(NBTTagCompound tag) {
        ByteBuf buf = Unpooled.buffer();
        toBytes(buf);
        tag.setByteArray(IDENTIFIER, buf.array());
    }

    @Override
    public void loadNBTData(NBTTagCompound tag) {
        byte[] bytes = tag.getByteArray(IDENTIFIER);
        if (bytes.length > 0)
            fromBytes(Unpooled.wrappedBuffer(bytes));
        else
            clear();
    }

    @Override
    public void init(Entity entity, World world) {
        if (!(entity instanceof EntityPlayer)) {
            LIUtils.log.warn("Registering ControlData for a(n)" + entity.getClass().getName());
            return;
        }
    }
}