Мастер-класс реализует Parcelable, массив подклассов, выдающий ошибку.ANDROID - PullRequest
0 голосов
/ 25 сентября 2019

У меня есть небольшой игровой проект, в котором я использую множество массивов с подклассами с расширенной парцелой.

Что ж, я получаю "Класс не найден, когда unmarshalling: class".

В целом,код не работает, например: https://github.com/GPgabigob07/WKFF

Класс клаза:

package org.gpginc.ntateam.apptest.runtime;

import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;

import org.gpginc.ntateam.apptest.CurrentPlayer;
import org.gpginc.ntateam.apptest.R;
import org.gpginc.ntateam.apptest.SkillRun;
import org.gpginc.ntateam.apptest.runtime.activity.RuntimeActivity;
import org.gpginc.ntateam.apptest.runtime.util.GameClazz;
import org.gpginc.ntateam.apptest.runtime.util.InstanciableSkill;
import org.gpginc.ntateam.apptest.runtime.util.Skill;
import org.gpginc.ntateam.apptest.runtime.util.enums.Rarity;

import java.util.ArrayList;
import java.util.List;


public class Clazz implements GameClazz<Clazz>
{
    @StringRes
    private final int name;
    @Nullable
    private Player cPlayer;
    @DrawableRes
    private final int icon;
    public final boolean needInstance;
    private final ArrayList<ClazzSkill> SKILLS = new ArrayList<>();

    private Resources resources;

    public void setResources(Resources resources) {
        this.resources = resources;
    }

    private final Rarity RARITY;


    public boolean enabled = true;

    public int getIcon() {
        return icon;
    }

    public Clazz(@StringRes int name, Rarity r, @DrawableRes int icon, boolean needBase){
        this.name = name;
        this.RARITY = r;
        this.icon = icon;
        Main.p(this.getName());
        if(!needBase)
        {
            Clazzs.CLAZZS.add(this);
            Clazzs.CLAZZ_MAP.put(this.name, this);
        }
        this.needInstance = needBase;
    }

    protected Clazz setAllSkills(List<ClazzSkill> skills)
    {
        for (ClazzSkill sk : skills)
        {
            this.bindSkill(sk, 0);
        }
        return this;}

    /**
     * Use this constructor for SPY based clazzs
     */
    public Clazz()
    {
        this.needInstance = false;
        this.name = R.string.clazz_spy;
        this.icon= R.drawable.botao_adicionar;
        this.RARITY = Rarity.MASTERRARE;
    }


    public Rarity getRARITY() {
        return RARITY;
    }

    protected Clazz(Parcel in) {
        name = in.readInt();
        cPlayer = in.readParcelable(Player.class.getClassLoader());
        this.needInstance = in.readByte() ==1;
        enabled = in.readByte() != 0;
        RARITY = Rarity.withName(in.readString());
        icon = in.readInt();
        Bundle b = in.readBundle();
        for(String s : b.getStringArrayList("NAMES"))
        {
            this.SKILLS.add((ClazzSkill)b.getParcelable(s)); //Problem is here, form the console
        }
    }


    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(name);
        dest.writeParcelable(cPlayer, flags);
        dest.writeByte((byte) (this.needInstance ? 1 : 0));
        dest.writeByte((byte) (enabled ? 1 : 0));
        dest.writeString(this.RARITY.R());
        dest.writeInt(this.icon);
        Bundle b = new Bundle();
        ArrayList<String> names = new ArrayList<>();
        for(ClazzSkill sk : this.SKILLS)
        {
            names.add(sk.getName());
            b.putParcelable(sk.getName(), sk);
        }
        b.putStringArrayList("NAMES", names);
        dest.writeBundle(b);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<Clazz> CREATOR = new Creator<Clazz>() {
        @Override
        public Clazz createFromParcel(Parcel in) {
            return new Clazz(in);
        }

        @Override
        public Clazz[] newArray(int size) {
            return new Clazz[size];
        }
    };

    public Clazz bindSkill(ClazzSkill skill)
    {
        this.SKILLS.add(skill);
        Main.p("Skill: " + skill.getName() + " added to " + this.getName());
        return this;
    }
    public Clazz bindSkill(ClazzSkill skill, int flag)
    {
        if(flag == 0)
        {
            if(skill instanceof InstanciableSkill)
            {
                this.SKILLS.add(((InstanciableSkill) skill).newInstance());
            }
            else
            {
                this.SKILLS.add(skill);
            }
        } else this.SKILLS.add(skill);
        return this;
    }
    public ArrayList<ClazzSkill> getSkills() {
        // TODO Auto-generated method stub
        return this.SKILLS;
    }
    public ClazzSkill getSkillAt(int index)
    {
        return index >=0 && index < this.SKILLS.size() ? this.SKILLS.get(index) : null;
    }
    public boolean hasSkills() {
        // TODO Auto-generated method stub
        return this.SKILLS.size() > 0;
    }
    public void runPassive(CurrentPlayer player)
    {
        for(ClazzSkill s : this.SKILLS)
        {
            if(s.isPassive())
            {
                s.setLastAct(player);
                if(s.hasLayout()) {
                    Intent skill = new Intent(player, SkillRun.class);
                    skill.putExtra("cskill", s.getName());
                    skill.putExtra("PLAYER_EXECUTE", player.currentPlayer());
                    player.startActivity(skill);
                } else {
                    s.runSkill(player.currentPlayer());
                }
            }
        }
    }
    public void runAttackTrigger(RuntimeActivity player)
    {
        for(ClazzSkill s : this.SKILLS)
        {
            if(s.isAttackTriggered())
            {
                s.setLastAct(player);
                if(s.hasLayout()) {
                    Intent skill = new Intent(player, SkillRun.class);
                    skill.putExtra("cskill", s.getName());
                    skill.putExtra("PLAYER_EXECUTE", player.currentPlayer());
                    player.startActivity(skill);
                } else {
                    s.runSkill(player.currentPlayer());
                }
            }
        }
    }
    public Player getCurrentPlayer()
    {
        return this.cPlayer;
    }
    public Clazz setCurrentPlayer(@Nullable Player p)
    {
        this.cPlayer = p;
        return this;
    }
    public void renew()
    {
        for(ClazzSkill s : this.SKILLS)
        {
            s.setPassiveRun(false);
        }
    }
    @StringRes
    public int getName()
    {
        return this.name;
    }

    public String getNameLikeStr(Resources rs){return rs.getString(this.name);}

    @NonNull
    @Override
    public String toString() {
        return String.valueOf(this.getName());
    }

    public boolean equals(Clazz clazz)
    {
        return clazz.getName() == this.getName();
    }

    @Override
    public Clazz newInstance()
    {
        return new Clazz(this.getName(), this.RARITY, this.icon, this.needInstance).setAllSkills(this.SKILLS);
    }

    @Override
    public Clazz base() {
        Clazzs.CLAZZS.add(this);
        Clazzs.CLAZZ_MAP.put(this.name, this);
        return this;
    }
}

Журнал консоли:

E/Parcel: Class not found when unmarshalling: org.gpginc.ntateam.apptest.runtime.skills.MagicianCounter
    java.lang.ClassNotFoundException: org.gpginc.ntateam.apptest.runtime.skills.MagicianCounter
        at java.lang.Class.classForName(Native Method)
        at java.lang.Class.forName(Class.java:453)
        at android.os.Parcel.readParcelableCreator(Parcel.java:2814)
        at android.os.Parcel.readParcelable(Parcel.java:2768)
        at android.os.Parcel.readValue(Parcel.java:2671)
        at android.os.Parcel.readArrayMapInternal(Parcel.java:3045)
        at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:288)
        at android.os.BaseBundle.unparcel(BaseBundle.java:232)
        at android.os.BaseBundle.getStringArrayList(BaseBundle.java:1282)
        at android.os.Bundle.getStringArrayList(Bundle.java:1062)
        at org.gpginc.ntateam.apptest.runtime.Clazz.<init>(Clazz.java:97)
        at org.gpginc.ntateam.apptest.runtime.Clazz$1.createFromParcel(Clazz.java:131)
        at org.gpginc.ntateam.apptest.runtime.Clazz$1.createFromParcel(Clazz.java:128)
        at android.os.Parcel.readParcelable(Parcel.java:2777)
        at org.gpginc.ntateam.apptest.runtime.Player.<init>(Player.java:56)
        at org.gpginc.ntateam.apptest.runtime.Player$1.createFromParcel(Player.java:105)
        at org.gpginc.ntateam.apptest.runtime.Player$1.createFromParcel(Player.java:102)
        at android.os.Parcel.readParcelable(Parcel.java:2777)
        at android.os.Parcel.readValue(Parcel.java:2671)
        at android.os.Parcel.readListInternal(Parcel.java:3106)
        at android.os.Parcel.readArrayList(Parcel.java:2322)
        at android.os.Parcel.readValue(Parcel.java:2692)
        at android.os.Parcel.readArrayMapInternal(Parcel.java:3045)
        at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:288)
        at android.os.BaseBundle.unparcel(BaseBundle.java:232)
        at android.os.BaseBundle.getStringArrayList(BaseBundle.java:1282)
        at android.os.Bundle.getStringArrayList(Bundle.java:1062)
        at org.gpginc.ntateam.apptest.runtime.activity.RuntimeActivity.load(RuntimeActivity.java:142)
        at org.gpginc.ntateam.apptest.runtime.activity.RuntimeActivity.onCreate(RuntimeActivity.java:104)
        at org.gpginc.ntateam.apptest.PrePlayer.onCreate(PrePlayer.java:21)
        at android.app.Activity.performCreate(Activity.java:7224)
        at android.app.Activity.performCreate(Activity.java:7213)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2926)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3081)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:201)
        at android.app.ActivityThread.main(ActivityThread.java:6806)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
     Caused by: java.lang.ClassNotFoundException: org.gpginc.ntateam.apptest.runtime.skills.MagicianCounter
        at java.lang.Class.classForName(Native Method)
        at java.lang.BootClassLoader.findClass(ClassLoader.java:1346)
        at java.lang.BootClassLoader.loadClass(ClassLoader.java:1406)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at java.lang.Class.classForName(Native Method) 
        at java.lang.Class.forName(Class.java:453) 
        at android.os.Parcel.readParcelableCreator(Parcel.java:2814) 
        at android.os.Parcel.readParcelable(Parcel.java:2768) 
        at android.os.Parcel.readValue(Parcel.java:2671) 
        at android.os.Parcel.readArrayMapInternal(Parcel.java:3045) 
        at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:288) 
        at android.os.BaseBundle.unparcel(BaseBundle.java:232) 
        at android.os.BaseBundle.getStringArrayList(BaseBundle.java:1282) 
        at android.os.Bundle.getStringArrayList(Bundle.java:1062) 
        at org.gpginc.ntateam.apptest.runtime.Clazz.<init>(Clazz.java:97) 
        at org.gpginc.ntateam.apptest.runtime.Clazz$1.createFromParcel(Clazz.java:131) 
        at org.gpginc.ntateam.apptest.runtime.Clazz$1.createFromParcel(Clazz.java:128) 
        at android.os.Parcel.readParcelable(Parcel.java:2777) 
        at org.gpginc.ntateam.apptest.runtime.Player.<init>(Player.java:56) 
        at org.gpginc.ntateam.apptest.runtime.Player$1.createFromParcel(Player.java:105) 
        at org.gpginc.ntateam.apptest.runtime.Player$1.createFromParcel(Player.java:102) 
        at android.os.Parcel.readParcelable(Parcel.java:2777) 
        at android.os.Parcel.readValue(Parcel.java:2671) 
        at android.os.Parcel.readListInternal(Parcel.java:3106) 
        at android.os.Parcel.readArrayList(Parcel.java:2322) 
        at android.os.Parcel.readValue(Parcel.java:2692) 
        at android.os.Parcel.readArrayMapInternal(Parcel.java:3045) 
        at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:288) 
        at android.os.BaseBundle.unparcel(BaseBundle.java:232) 
        at android.os.BaseBundle.getStringArrayList(BaseBundle.java:1282) 
        at android.os.Bundle.getStringArrayList(Bundle.java:1062) 
        at org.gpginc.ntateam.apptest.runtime.activity.RuntimeActivity.load(RuntimeActivity.java:142) 
        at org.gpginc.ntateam.apptest.runtime.activity.RuntimeActivity.onCreate(RuntimeActivity.java:104) 
        at org.gpginc.ntateam.apptest.PrePlayer.onCreate(PrePlayer.java:21) 
        at android.app.Activity.performCreate(Activity.java:7224) 
        at android.app.Activity.performCreate(Activity.java:7213) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2926) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3081) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:201) 
        at android.app.ActivityThread.main(ActivityThread.java:6806) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873) 
     Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: org.gpginc.ntateam.apptest, PID: 8224
    java.lang.RuntimeException: Unable to start activity ComponentInfo{org.gpginc.ntateam.apptest/org.gpginc.ntateam.apptest.PrePlayer}: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: org.gpginc.ntateam.apptest.runtime.skills.MagicianCounter
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2946)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3081)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:201)
        at android.app.ActivityThread.main(ActivityThread.java:6806)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
     Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: org.gpginc.ntateam.apptest.runtime.skills.MagicianCounter
        at android.os.Parcel.readParcelableCreator(Parcel.java:2847)
        at android.os.Parcel.readParcelable(Parcel.java:2768)
        at android.os.Parcel.readValue(Parcel.java:2671)
        at android.os.Parcel.readArrayMapInternal(Parcel.java:3045)
        at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:288)
        at android.os.BaseBundle.unparcel(BaseBundle.java:232)
        at android.os.BaseBundle.getStringArrayList(BaseBundle.java:1282)
        at android.os.Bundle.getStringArrayList(Bundle.java:1062)
        at org.gpginc.ntateam.apptest.runtime.Clazz.<init>(Clazz.java:97)
        at org.gpginc.ntateam.apptest.runtime.Clazz$1.createFromParcel(Clazz.java:131)
        at org.gpginc.ntateam.apptest.runtime.Clazz$1.createFromParcel(Clazz.java:128)
        at android.os.Parcel.readParcelable(Parcel.java:2777)
        at org.gpginc.ntateam.apptest.runtime.Player.<init>(Player.java:56)
        at org.gpginc.ntateam.apptest.runtime.Player$1.createFromParcel(Player.java:105)
        at org.gpginc.ntateam.apptest.runtime.Player$1.createFromParcel(Player.java:102)
        at android.os.Parcel.readParcelable(Parcel.java:2777)
        at android.os.Parcel.readValue(Parcel.java:2671)
        at android.os.Parcel.readListInternal(Parcel.java:3106)
        at android.os.Parcel.readArrayList(Parcel.java:2322)
        at android.os.Parcel.readValue(Parcel.java:2692)
        at android.os.Parcel.readArrayMapInternal(Parcel.java:3045)
        at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:288)
        at android.os.BaseBundle.unparcel(BaseBundle.java:232)
        at android.os.BaseBundle.getStringArrayList(BaseBundle.java:1282)
        at android.os.Bundle.getStringArrayList(Bundle.java:1062)
        at org.gpginc.ntateam.apptest.runtime.activity.RuntimeActivity.load(RuntimeActivity.java:142)
        at org.gpginc.ntateam.apptest.runtime.activity.RuntimeActivity.onCreate(RuntimeActivity.java:104)
        at org.gpginc.ntateam.apptest.PrePlayer.onCreate(PrePlayer.java:21)
        at android.app.Activity.performCreate(Activity.java:7224)
        at android.app.Activity.performCreate(Activity.java:7213)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2926)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3081) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:201) 
        at android.app.ActivityThread.main(ActivityThread.java:6806) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873) 

Счетчик волшебников (как пример):

package org.gpginc.ntateam.apptest.runtime.skills;

import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Parcel;
import android.support.annotation.Nullable;

import org.gpginc.ntateam.apptest.R;
import org.gpginc.ntateam.apptest.SkillRun;
import org.gpginc.ntateam.apptest.runtime.ClazzSkill;
import org.gpginc.ntateam.apptest.runtime.Clazzs;
import org.gpginc.ntateam.apptest.runtime.Main;
import org.gpginc.ntateam.apptest.runtime.Player;
import org.gpginc.ntateam.apptest.runtime.activity.RuntimeActivity;
import org.gpginc.ntateam.apptest.runtime.util.CounterSkill;

import java.util.ArrayList;
import java.util.List;

public class MagicianCounter extends ClazzSkill implements CounterSkill<MagicianCounter>
{

    public MagicianCounter() {
        super("Magician Counter", ClazzSkill.Type.MAHOU, true);
        this.isCounter = true;
    }

    public MagicianCounter(Parcel in) {
        super(in);
        this.isCounter = true;
    }

    @Override
    public void runSkill(@Nullable Object o)
    {
        if(o!=null)
        {
            final Player p = (Player) o;
            if(p.attacked)
            {
                final List<Object> attackable = new ArrayList<>();
                final SkillRun sk = this.current;
                attackable.addAll(p.getAttackers());
                final Player countered = p.getAttackers().get(p.getAttackers().size() - 1);
                Main.p("COUNTER TARGET: " +countered.getName());

                final RuntimeActivity r = this.lastAct;
                final ClazzSkill thisSkill = this;


                //Dialog that says wo's attack was countered:
                final Dialog counterDialog = lastAct.getDialog(lastAct, (countered.getName()) + " " + lastAct.getResources().getString(R.string.countered));

                counterDialog.findViewById(R.id.doalog_cancel).setOnClickListener(r.dialogDismiss(counterDialog, false));
                counterDialog.findViewById(R.id.doalog_ok).setOnClickListener(r.dialogDismiss(counterDialog, false));
                counterDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
                    @Override
                    public void onDismiss(DialogInterface dialog) {
                        countered.giveDamage(lastAct, 1, true);
                        p.increaseLifeIn(1);
                        thisSkill.counteredTimes++;
                        lastAct.changePlayer(p);
                        lastAct.changePlayer(countered);
                        lastAct.goNext(counterDialog.findViewById(R.id.doalog_ok));
                    }
                });
                //Dialog that says you're at leats twice:
                final Dialog dzin = lastAct.getDialog(lastAct, R.string.magician_counter_info_attackers);
                dzin.setOnDismissListener(new DialogInterface.OnDismissListener() {
                    @Override
                    public void onDismiss(DialogInterface dialog) {
                        counterDialog.show();
                    }
                });

                //Dialog that alerts that cannot counter an certain attack
                final Dialog alertz = lastAct.getDialog(lastAct, R.string.you_cant_counter);
                alertz.setOnDismissListener(new DialogInterface.OnDismissListener() {
                    @Override
                    public void onDismiss(DialogInterface dialog) {
                        lastAct.goNext(counterDialog.findViewById(R.id.doalog_ok));
                    }
                });

                if(p.getDamage() >= 2)
                {
                    dzin.show();
                } else if (countered.getClazz().equals(Clazzs.ARCHERY) || countered.getClazz().equals(Clazzs.SWORDMAN) || countered.getClazz().equals(Clazzs.LANCER))
                {
                    counterDialog.show();
                }
                else
                {
                    alertz.show();
                }
            }
        }
    }

    @Override
    public Creator getCreator() {
        return CREATOR;
    }

    public static final Creator<MagicianCounter> CREATOR = new Creator<MagicianCounter>()
    {
        @Override
        public MagicianCounter createFromParcel(Parcel source) {
            return new MagicianCounter(source);
        }

        @Override
        public MagicianCounter[] newArray(int size) {
            return new MagicianCounter[size];
        }
    };

    @Override
    public MagicianCounter newInstance() {
        Main.p("\n|**************************************************|\n|------ CREATED NEW INSTANCE FROM SKILL: MAGICIAN COUNTER ---------|\n|***************************************|\n");
        return new MagicianCounter().setCounter(2);
    }

    @Override
    public MagicianCounter base() {
        Clazzs.SKILL_MAP.put(this.getName(), this);
        return this;
    }

    @Override
    public MagicianCounter setCounter(int maxCounterTimes) {
        this.isCounter = true;
        this.maxCounterTimes = maxCounterTimes;
        return this;
    }
}

ClazzSkill (суперкласс):

package org.gpginc.ntateam.apptest.runtime;


import android.os.Parcel;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;

import org.gpginc.ntateam.apptest.CurrentPlayer;
import org.gpginc.ntateam.apptest.SkillRun;
import org.gpginc.ntateam.apptest.runtime.activity.RuntimeActivity;
import org.gpginc.ntateam.apptest.runtime.util.Skill;


import java.io.Serializable;

public abstract class ClazzSkill implements Skill {
    private final String name;
    private boolean passiveRun = false;
    public boolean isCounter = false;
    public int maxCounterTimes = 0, counteredTimes = 0;
    public boolean external = false;
    public boolean isLoaded = false;

    /**
     * Commonly {@link CurrentPlayer}
     */
    @Nullable
    protected RuntimeActivity lastAct = null;
    protected SkillRun current;
    public final Type type;


    @LayoutRes
    @NonNull
    protected int layout = -1;

    public ClazzSkill(String name, Type type, boolean needBase)
    {
        //TODO need to change name from string to StringRes (int)
        this.name = name;
        this.type = type;
        if(!needBase)
        {
            Clazzs.SKILL_MAP.put(this.name, this);
        }
    }
    public ClazzSkill(String name, Type type, int layout, boolean needBase)
    {
        this(name, type, needBase);
        this.layout = layout;
    }

    public ClazzSkill(Parcel in)
    {
        this.name = in.readString();
        this.type = (Type) in.readSerializable();
        this.layout = in.readInt();
        this.external = in.readByte() == 1;
        this.maxCounterTimes = in.readInt();
        this.counteredTimes = in.readInt();
        this.isCounter = in.readByte() ==1;
        this.setLastAct((RuntimeActivity) in.readParcelable(RuntimeActivity.class.getClassLoader()));
    }
    @Override
    public void writeToParcel(Parcel dest, int flags)
    {
        dest.writeString(this.name);
        dest.writeSerializable(this.type);
        dest.writeInt(this.layout);
        dest.writeByte((byte) (this.external ? 1 : 0));
        dest.writeInt(this.maxCounterTimes);
        dest.writeInt(this.counteredTimes);
        dest.writeByte((byte) (this.isCounter ? 1 : 0));
        dest.writeParcelable(this.lastAct, flags);
    }
    public void setCurrent(SkillRun current)
    {
        this.current = current;
    }

    public String getName()
    {
        return this.name;
    }
    public boolean isPassive()
    {
        return this.type.equals(Type.PASSIVE);
    }
    public boolean isAttackTriggered()
    {
        return this.type.equals(Type.ATTACK_TRIGGER);
    }
    public boolean isPassiveRun() {
        return passiveRun;
    }
    public boolean isAttack(){return this.type.equals(Type.ATTACK);}
    public ClazzSkill setPassiveRun(boolean passiveRun) {
        this.passiveRun = passiveRun;
        return this;
    }

    public Type getType()
    {
        return this.type;
    }
    public boolean stillCounter() {return this.isCounter && counteredTimes < maxCounterTimes;}

    public String toString()
    {
        return this.isAttackTriggered() && this.lastAct.currentPlayer().attacked ? this.name + " COUNTER!" : this.name;
    }

    public int getLayout()
    {
        return this.layout;
    }

    public int describeContents()
    {
        return 0;
    }

    @Nullable
    public RuntimeActivity getLastAct() {
        return lastAct;
    }

    public void setLastAct(@Nullable RuntimeActivity lastAct) {
        this.lastAct = lastAct;
    }

    public ClazzSkill asExternalCall()
    {
        this.external = true;
        return this;
    }
    public boolean isExternal()
    {
        return this.external;
    }

    public boolean hasLayout()
    {
        return this.layout != -1;
    }

    protected void goNext(View v)
    {
        this.getLastAct().goNext(v);
        if(this.current!=null)this.current.finish();
    }

    public enum Type implements Serializable
    {
        MAHOU,
        ATTACK,
        PASSIVE,
        ATTACK_TRIGGER
    }
}

...