Jump to content

Capabilities


LaurentOutang

Recommended Posts

public static final Capability<IMentalTemperature> MentalTemperature_CAP = null;
private IMentalTemperature instance = MentalTemperature_CAP.getDefaultInstance();

 

That code turns into this:

 

public static final Capability<IMentalTemperature> MentalTemperature_CAP;
private IMentalTemperature instance;
static {
    MentalTemperature_CAP = null;
    instance = MentalTemperature_CAP.getDefaultInstance();
}

 

Now, when you see that, isn't the issue OBVIOUS!?! MentalTemprature_CAP WILL ALWAYS BE NULL when you try to call it to set instance. (Also resisting urge to yell at you about code style)

@CapabilityHolders are only populated when someone registers a capability.

That's the entire freaking point. It's a soft dependency on that class.

1st) You're trying to make a soft dependacy so making a field of that exist type is not recommended. So instance should be Object. 

2nd) You should delay creating that instance until it's needed, Or until you are told that that capability exists. You can annotate a method with @CapabilityInject and a single argument of a CapabilityHolder and it'll be called whenever that apropriate cap is registered.

I do Forge for free, however the servers to run it arn't free, so anything is appreciated.
Consider supporting the team on Patreon

Link to comment
Share on other sites

IMentalTemperature

package com.laurentoutang.hardmod.capabilities;

public interface IMentalTemperature {

	public void consumeMental(float points);
	public void fillMental(float points);
	public void setMental(float points);
	public float getMental();
	
	public void consumeTemperature(float points);
	public void fillTemperature(float points);
	public void setTemperature(float points);
	public float getTemperature();
}

MentalTemperature

package com.laurentoutang.hardmod.capabilities;

import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;

public class MentalTemperature implements IMentalTemperature{

	private float mental = 100.f;
	private float temperature = 100.f;
	
	public MentalTemperature(float mental, float temperature)
	{
		this.mental = mental;
		this.temperature = temperature;
	}
	public MentalTemperature()
	{
		
	}
	
	@Override
	public void consumeMental(float points) 
	{
		if(mental-points < 0)
			mental = 0;
		else
			mental -= points;
	}

	@Override
	public void fillMental(float points) 
	{
		if(mental + points > 100)
			mental = 100;
		else
			mental += points;
	}

	@Override
	public void setMental(float points) 
	{
		mental = points;
	}

	@Override
	public float getMental() 
	{
		return mental;
	}	

	public void consumeTemperature(float points)
	{
		if(temperature-points < 0)
			temperature = 0;
		else
			temperature -= points;
	}
	public void fillTemperature(float points)
	{
		if(temperature + points > 100)
			temperature = 100;
		else
			temperature += points;
	}
	public void setTemperature(float points)
	{
		temperature = points;
	}
	public float getTemperature()
	{
		return temperature;
	}
}

MentalTemperatureProvider

package com.laurentoutang.hardmod.capabilities;

import java.util.concurrent.Callable;


import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTPrimitive;
import net.minecraft.nbt.NBTTagFloat;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.capabilities.Capability.IStorage;

public class MentalTemperatureProvider implements ICapabilitySerializable<NBTBase>{

	@CapabilityInject(IMentalTemperature.class)
	public static final Capability<IMentalTemperature> MentalTemperature_CAP = null;
	
	private IMentalTemperature instance = MentalTemperature_CAP.getDefaultInstance(); 

	
	

	 
	 @Override
	 public boolean hasCapability(Capability<?> capability, EnumFacing facing)
	 {
		 
		 return capability == MentalTemperature_CAP;

	 }

	 
	 @Override
	 public <T> T getCapability(Capability<T> capability, EnumFacing facing)
	 {
		 if (MentalTemperature_CAP != null && capability == MentalTemperature_CAP) return MentalTemperature_CAP.<T> cast(this.instance);
		 return null;
	 }
	 
	 
	 @Override
	 public NBTBase serializeNBT()
	 {

		 return MentalTemperature_CAP.getStorage().writeNBT(MentalTemperature_CAP, this.instance, null);

	 }

	 
	 @Override
	 public void deserializeNBT(NBTBase nbt)
	 {

		 MentalTemperature_CAP.getStorage().readNBT(MentalTemperature_CAP, this.instance, null, nbt);

	 } 

}

MentalTemperatureStorage

package com.laurentoutang.hardmod.capabilities;

import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTPrimitive;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagFloat;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.Capability.IStorage;
import net.minecraftforge.common.capabilities.CapabilityManager;

public class MentalTemperatureStorage implements IStorage<IMentalTemperature>{

	
	 @Override
	 public NBTBase writeNBT(Capability<IMentalTemperature> capability, IMentalTemperature instance, EnumFacing side)
	 {
		 NBTTagCompound tag = new NBTTagCompound();
		 tag.setFloat("Mental", instance.getMental());
		 tag.setFloat("Temperature", instance.getTemperature());
		 
		 return tag;
	 }
	 
	 @Override
	 public void readNBT(Capability<IMentalTemperature> capability, IMentalTemperature instance, EnumFacing side, NBTBase nbt)
	 {
		 NBTTagCompound tag = ((NBTTagCompound)nbt);
		 instance.setMental(tag.getFloat("Mental"));
		 instance.setTemperature(tag.getFloat("Temperature"));
	 }
	
}

ClientProxy

package com.laurentoutang.hardmod.proxy;

import com.laurentoutang.hardmod.capabilities.IMentalTemperature;
import com.laurentoutang.hardmod.capabilities.MentalTemperature;
import com.laurentoutang.hardmod.capabilities.MentalTemperatureStorage;
import com.laurentoutang.hardmod.util.handlers.CapabilityHandler;
import com.laurentoutang.hardmod.util.handlers.MessageCapabilitiesHandler;

import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.util.IThreadListener;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.relauncher.Side;

public class ClientProxy extends CommonProxy {
	
	public void init() 
	{		
		MinecraftForge.EVENT_BUS.register(new MessageCapabilitiesHandler());
	}
	public IThreadListener getListener(MessageContext ctx) {
		return ctx.side == Side.CLIENT ? Minecraft.getMinecraft() : super.getListener(ctx);
	}

	public EntityPlayer getPlayer(MessageContext ctx) {
		return ctx.side == Side.CLIENT ? Minecraft.getMinecraft().player : super.getPlayer(ctx);
	}
	public void registerItemRenderer(Item item, int meta, String id) 
	{
		ModelLoader.setCustomModelResourceLocation(item,  meta,  new ModelResourceLocation(item.getRegistryName(), id));
	}
}

CommonProxy

package com.laurentoutang.hardmod.proxy;



import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.util.IThreadListener;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;

public class CommonProxy 
{
	public void init() {
		
	}
	
	public IThreadListener getListener(MessageContext ctx) {
		return (WorldServer) ctx.getServerHandler().player.getServerWorld();
	}

	public EntityPlayer getPlayer(MessageContext ctx) {
		return ctx.getServerHandler().player;
	}
	public void registerItemRenderer(Item item, int meta, String id)
	{
		
	}
	
}

CapabilityHandler

package com.laurentoutang.hardmod.util.handlers;

import com.laurentoutang.hardmod.capabilities.MentalTemperatureProvider;
import com.laurentoutang.hardmod.util.Reference;

import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;

@EventBusSubscriber
public class CapabilityHandler {
	
	 public static final ResourceLocation MentalTemperature_CAP = new ResourceLocation(Reference.MOD_ID, "mentaltemperature");

	 
	 @SubscribeEvent

	 public static void attachCapability(AttachCapabilitiesEvent<Entity> event)
	 {
		 if (event.getObject() instanceof EntityPlayer)
		 {
			 event.addCapability(MentalTemperature_CAP, new MentalTemperatureProvider());	
		 }
	 }
}

EventHandler

package com.laurentoutang.hardmod.util.handlers;

import com.laurentoutang.hardmod.capabilities.IMentalTemperature;
import com.laurentoutang.hardmod.capabilities.MentalTemperatureProvider;
import com.laurentoutang.hardmod.util.Reference;

import Network.MessageCapabilities;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.EnumHand;
import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.entity.player.PlayerWakeUpEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent;
import net.minecraftforge.fml.relauncher.Side;

@EventBusSubscriber
public class EventHandler {

	@SubscribeEvent
	 public static void onPlayerLogsIn(PlayerLoggedInEvent event)
	 {

		 EntityPlayer player = event.player;

		 
		 
		 IMentalTemperature capabilities = player.getCapability(MentalTemperatureProvider.MentalTemperature_CAP, null);
		 if(capabilities != null)
		 {
			 capabilities.consumeMental(2.f);
			 String message = String.format("Logged in : mental = " + capabilities.getMental());
			 player.sendMessage(new TextComponentString(message));
		 }		
	 }	 
	 @SubscribeEvent
	 public static void onPlayerInteract(PlayerInteractEvent event)
	 {
		 EntityPlayer player = event.getEntityPlayer();
		 if(event.getHand() == EnumHand.MAIN_HAND)
		 {
			 IMentalTemperature capabilities = player.getCapability(MentalTemperatureProvider.MentalTemperature_CAP, null);
			 if(capabilities != null)
			 {
				 capabilities.consumeMental(1.f);
				 String message = String.format("Player interact mental = " + capabilities.getMental());
				 player.sendMessage(new TextComponentString(message));
			 }	
		 }
		 	
	 }
	 
}

MessageCapabilityHandler

package com.laurentoutang.hardmod.util.handlers;

import java.util.List;

import com.laurentoutang.hardmod.capabilities.IMentalTemperature;
import com.laurentoutang.hardmod.capabilities.MentalTemperatureProvider;

import Network.MessageCapabilities;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.IThreadListener;
import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.relauncher.Side;


@EventBusSubscriber(value = Side.CLIENT)
public class MessageCapabilitiesHandler implements IMessageHandler<MessageCapabilities, IMessage>{

	@Override
	public IMessage onMessage(MessageCapabilities message, MessageContext ctx) 
	{
		
		
		final float mental = message.getMental();
		final float temperature = message.getTemperature();
		Minecraft minecraft = Minecraft.getMinecraft();
	    final WorldClient worldClient = minecraft.world;
	    minecraft.addScheduledTask(new Runnable()
	    {
	      public void run() {
	        processMessage(worldClient, message);
	      }
	    });
		return null;
	}
	 void processMessage(WorldClient worldClient, MessageCapabilities message)
	  {
		List<EntityPlayer> players = worldClient.playerEntities;
	    for(int i = 0; i < players.size(); i++)
	    {
	    	players.get(i).sendMessage(new TextComponentString("You have " + message.getMental() + " mental left and " + message.getTemperature() + " temperature left"));
	    }
	    return;
	  }


}

PacketHandler

package com.laurentoutang.hardmod.util.handlers;

import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;

public class PacketHandler {
	public static final SimpleNetworkWrapper NETWORK = NetworkRegistry.INSTANCE.newSimpleChannel("hm");
}

MessageCapability

package Network;

import io.netty.buffer.ByteBuf;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;

public class MessageCapabilities implements IMessage{
	
	private float mentalToSend, temperatureToSend;
	
	public MessageCapabilities() {}
	
	public MessageCapabilities(float mentalToSend, float temperatureToSend)
	{
		this.mentalToSend = mentalToSend;
		this.temperatureToSend = temperatureToSend;
	}
	
	@Override
	public void fromBytes(ByteBuf buf) 
	{
		this.mentalToSend = buf.readFloat();
		this.temperatureToSend = buf.readFloat();	
	}

	@Override
	public void toBytes(ByteBuf buf) 
	{
		buf.writeFloat(this.mentalToSend);
		buf.writeFloat(this.temperatureToSend);		
	}
	public float getMental()
	{
		return mentalToSend;
	}
	public float getTemperature()
	{
		return temperatureToSend;
	}

}

Main

package com.laurentoutang.hardmod;

import org.apache.logging.log4j.core.jmx.Server;

import com.laurentoutang.hardmod.capabilities.IMentalTemperature;
import com.laurentoutang.hardmod.capabilities.MentalTemperature;
import com.laurentoutang.hardmod.capabilities.MentalTemperatureStorage;
import com.laurentoutang.hardmod.proxy.CommonProxy;
import com.laurentoutang.hardmod.util.Reference;
import com.laurentoutang.hardmod.util.handlers.MessageCapabilitiesHandler;
import com.laurentoutang.hardmod.util.handlers.PacketHandler;

import Network.MessageCapabilities;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.server.MinecraftServer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.event.entity.player.PlayerWakeUpEvent;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.Mod.Instance;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartedEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;

@Mod(modid = Reference.MOD_ID, name = Reference.NAME, version  = Reference.VERSION)
public class Main {
	
	
	
	
	@Instance
	public static Main instance;
	
	@SidedProxy(clientSide = Reference.CLIENT_PROXY_CLASS, serverSide = Reference.COMMON_PROXY_CLASS)
	public static CommonProxy proxy;
	
	@EventHandler
	public static void PreInit(FMLPreInitializationEvent event)
	{
		CapabilityManager.INSTANCE.register(IMentalTemperature.class, new MentalTemperatureStorage(), MentalTemperature::new);
		PacketHandler.NETWORK.registerMessage(MessageCapabilitiesHandler.class, MessageCapabilities.class, 0, Side.SERVER);
	}
	
	@EventHandler
	public static void init(FMLInitializationEvent event)
	{
	}
	
	@EventHandler
	public static void PostInit(FMLPostInitializationEvent event)
	{
		
	}
	
	
}


Here is the code. The problem is that in EventHandler class the two events do not give the same value for mental. When I connect i see a value that is modified at each connection (fine) but when i click, it starts from 100 everytime. So I created packets (thanks to tutorials) but I do not know how to sync capabilities with it ? 

public static final Capability<IMentalTemperature> MentalTemperature_CAP = null;
private IMentalTemperature instance = MentalTemperature_CAP.getDefaultInstance();

for these lines I found it on 2 different tutorials. I dont't know how I should instantiate the MentalTemperature_CAP otherwise. Thank you for you help and your attention

Edited by LaurentOutang
Link to comment
Share on other sites

I found a trick i modified the EventHandler class like that 

package com.laurentoutang.hardmod.util.handlers;

import com.laurentoutang.hardmod.capabilities.IMentalTemperature;
import com.laurentoutang.hardmod.capabilities.MentalTemperatureProvider;
import com.laurentoutang.hardmod.util.Reference;

import Network.MessageCapabilities;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.EnumHand;
import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.entity.player.PlayerWakeUpEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent;
import net.minecraftforge.fml.relauncher.Side;

@EventBusSubscriber
public class EventHandler {
	static IMentalTemperature capabilities;
	@SubscribeEvent
	 public static void onPlayerLogsIn(PlayerLoggedInEvent event)
	 {

		 EntityPlayer player = event.player;

		 
		 
		 capabilities = player.getCapability(MentalTemperatureProvider.MentalTemperature_CAP, null);
		 if(capabilities != null)
		 {
			 capabilities.consumeMental(2.f);
			 String message = String.format("Logged in : mental = " + capabilities.getMental());
			 player.sendMessage(new TextComponentString(message));
		 }		
	 }	 
	 @SubscribeEvent
	 public static void onPlayerInteract(PlayerInteractEvent event)
	 {
		 EntityPlayer player = event.getEntityPlayer();
		 if(event.getHand() == EnumHand.MAIN_HAND)
		 {
			 if(capabilities != null)
			 {
				 capabilities.consumeMental(1.f);
				 String message = String.format("Player interact mental = " + capabilities.getMental());
				 player.sendMessage(new TextComponentString(message));
			 }	
		 }
		 	
	 }
	 
}

Because the log player event is the first that is called for what I need, it works. But I'm pretty sure there is a better way to do it...

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.