cn.academy.core.ctrl.SkillStateMessage.java Source code

Java tutorial

Introduction

Here is the source code for cn.academy.core.ctrl.SkillStateMessage.java

Source

/**
 * Copyright (c) Lambda Innovation, 2013-2015
 * ??Lambda Innovation
 * http://www.lambdacraft.cn/
 *
 * AcademyCraft 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.
 * AcademyCraft??GNU???
 * ????
 * http://www.gnu.org/licenses/gpl.html
 */
package cn.academy.core.ctrl;

import java.lang.reflect.Constructor;

import cn.academy.api.ctrl.SkillState;
import cn.academy.api.ctrl.SkillStateManager;
import cn.academy.core.AcademyCraft;
import cn.annoreg.core.RegistrationClass;
import cn.annoreg.mc.RegMessageHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import io.netty.buffer.ByteBuf;
import cpw.mods.fml.common.network.ByteBufUtils;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

/**
 * The message sent from server to client to synchronize the SkillStates of other players.
 * Those SkillStates are mainly used to render the skill effects.
 * @author acaly
 *
 */
@RegistrationClass
public class SkillStateMessage implements IMessage {
    public enum Action {
        START, UPDATE, FINISH, ABORT,

        //used by DimensionSkillStateMessage
        SYNC,
    }

    private Action action;

    private int stateID;

    /**
     * The player this skill belongs to.
     */
    private String playerName;

    /**
     * The name of the SkillState class. Used to initialize the instance on client.
     */
    private String className;

    /**
     * NBT data, if any, used by the SkillState.
     */
    private NBTTagCompound nbt;

    public SkillStateMessage() {
    }

    public SkillStateMessage(SkillState state, Action action) {
        this.action = action;
        this.stateID = state.stateID;
        this.playerName = state.player.getCommandSenderName();
        Class<? extends SkillState> clazz = state.getClass();
        this.className = clazz.getName();
        this.nbt = new NBTTagCompound();
        state.toNBT(this.nbt);
    }

    @Override
    public void fromBytes(ByteBuf buf) {
        action = Action.values()[buf.readInt()];
        stateID = buf.readInt();
        playerName = ByteBufUtils.readUTF8String(buf);
        className = ByteBufUtils.readUTF8String(buf);
        nbt = ByteBufUtils.readTag(buf);
    }

    @Override
    public void toBytes(ByteBuf buf) {
        buf.writeInt(action.ordinal());
        buf.writeInt(stateID);
        ByteBufUtils.writeUTF8String(buf, playerName);
        ByteBufUtils.writeUTF8String(buf, className);
        ByteBufUtils.writeTag(buf, nbt);
    }

    @RegMessageHandler(msg = SkillStateMessage.class, side = RegMessageHandler.Side.CLIENT)
    public static class Handler implements IMessageHandler<SkillStateMessage, IMessage> {

        @Override
        @SideOnly(Side.CLIENT)
        public IMessage onMessage(SkillStateMessage msg, MessageContext ctx) {
            Entity entity = Minecraft.getMinecraft().theWorld.getPlayerEntityByName(msg.playerName);

            SkillState ss = null;
            switch (msg.action) {

            case SYNC:
                ss = SkillStateManager.getStateById(msg.playerName, msg.stateID);
                if (ss != null)
                    break;
                //fall through

            case START:
                //If the player is not in the same dimension.
                if (entity == null)
                    return null;
                //If the player is thePlayer. These skills are directly handled by EventHandlerClient.
                if (entity == Minecraft.getMinecraft().thePlayer)
                    return null;

                try {
                    Class<?> clazz = Class.forName(msg.className);
                    for (Constructor ctor : clazz.getDeclaredConstructors()) {
                        if (ctor.getParameterTypes().length == 1) {
                            if (ctor.getParameterTypes()[0].isAssignableFrom(EntityPlayer.class)) {
                                ctor.setAccessible(true);
                                ss = (SkillState) ctor.newInstance(entity);
                                ss.onUpdate(msg.nbt);
                                break;
                            }
                        }
                    }
                } catch (Exception e) {
                    AcademyCraft.log.error(
                            "Cannot find constructor for SKillState. Check the implementation of your SkillState.");
                    throw new RuntimeException(e);
                }
                if (ss == null)
                    throw new RuntimeException(
                            "Cannot find constructor for SKillState. Check the implementation of your SkillState.");

                //Start the skill.
                ss.stateID = msg.stateID;
                ss.startSkill();
                break;

            case UPDATE:
                ss = SkillStateManager.getStateById(msg.playerName, msg.stateID);
                if (ss == null)
                    break;
                ss.onUpdate(msg.nbt);
                break;

            case FINISH:
            case ABORT:
                ss = SkillStateManager.getStateById(msg.playerName, msg.stateID);
                if (ss == null)
                    break;
                ss.finishSkill(msg.action == Action.FINISH);
                break;

            }
            return null;
        }

    }
}