/**
* Copyright (c) Lambda Innovation, 2013-2016
* This file is part of the AcademyCraft mod.
* https://github.com/LambdaInnovation/AcademyCraft
* Licensed under GPLv3, see project root for more information.
*/
package cn.academy.misc.tutorial;
import cn.academy.core.AcademyCraft;
import cn.lambdalib.annoreg.core.Registrant;
import cn.lambdalib.annoreg.mc.RegPreInitCallback;
import cn.lambdalib.s11n.SerializeIncluded;
import cn.lambdalib.s11n.nbt.NBTS11n;
import cn.lambdalib.s11n.network.NetworkMessage.Listener;
import cn.lambdalib.util.datapart.DataPart;
import cn.lambdalib.util.datapart.EntityData;
import cn.lambdalib.util.datapart.RegDataPart;
import cn.lambdalib.util.generic.RandUtils;
import cn.lambdalib.util.helper.TickScheduler;
import com.google.common.base.Preconditions;
import cpw.mods.fml.relauncher.Side;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.MinecraftForge;
import java.util.BitSet;
import java.util.HashSet;
/**
* This class simply stores activate data that trigger-type condition needs.
*/
@Registrant
@RegDataPart(EntityPlayer.class)
public class TutorialData extends DataPart<EntityPlayer> {
@RegPreInitCallback
private static void __init() {
// Force the property to load, so it will be refreshed once after startup
canAcquireTutorial();
}
public static TutorialData get(EntityPlayer player) {
return EntityData.get(player).getPart(TutorialData.class);
}
private static final String MSG_ACTIVATE = "activate";
@SerializeIncluded
private BitSet savedConditions = new BitSet();
@SerializeIncluded
private HashSet<String> activatedTuts = new HashSet<>();
@SerializeIncluded
private boolean tutorialAcquired = false;
@SerializeIncluded
private int misakaID = -1;
private final TickScheduler scheduler = new TickScheduler();
private boolean dirty;
public TutorialData() {
setTick(true);
setClientNeedSync();
setNBTStorage();
misakaID = RandUtils.rangei(1000, 19000);
scheduler.every(3).atOnly(Side.SERVER).run(() -> {
if (dirty) {
dirty = false;
TutorialRegistry.enumeration().forEach(tut -> {
if (!activatedTuts.contains(tut.id) &&
tut.isActivated(getEntity()) &&
!tut.isDefaultInstalled()) {
activatedTuts.add(tut.id);
onTutorialActivate(tut.id);
sendToLocal(MSG_ACTIVATE, tut.id);
}
});
sync();
}
});
if (canAcquireTutorial()) {
scheduler.every(10).atOnly(Side.SERVER).run(() -> {
if (!tutorialAcquired) {
EntityPlayer player = getEntity();
player.worldObj.spawnEntityInWorld(new EntityItem(player.worldObj,
player.posX, player.posY + 1.0, player.posZ,
new ItemStack(ModuleTutorial.itemTutorial)));
tutorialAcquired = true;
}
});
}
}
@Override
public void tick() {
scheduler.runTick();
}
public int getMisakaID() {
return misakaID;
}
boolean isCondActivate(int index) {
return savedConditions.get(index);
}
void setCondActivate(int index) {
checkSide(Side.SERVER);
if (!savedConditions.get(index)) {
savedConditions.set(index);
dirty = true;
}
}
@Override
public void toNBT(NBTTagCompound tag) {
NBTS11n.write(tag, this);
}
@Override
public void fromNBT(NBTTagCompound tag) {
NBTS11n.read(tag, this);
}
@Listener(channel=MSG_ACTIVATE, side={Side.CLIENT, Side.SERVER})
private void onTutorialActivate(String tutName) {
ACTutorial tut = TutorialRegistry.getTutorial(tutName);
Preconditions.checkNotNull(tut);
MinecraftForge.EVENT_BUS.post(new TutorialActivatedEvent(getEntity(), tut));
}
private static boolean canAcquireTutorial() {
return AcademyCraft.config.getBoolean("giveCloudTerminal", "generic", true,
"Whether the player will be given MisakaCloud Terminal on first spawn.");
}
}