Jump to content

[1.8] How to manipulate textures for entities?


Warix

Recommended Posts

Hello, i need to change look of texture ( change its color ) , eg. when i right click with some item on mob it will make it blue. Any clue how to do this? Besides making custom entity with different texture and replacing it with existing entity.

Something like this ( i done it with replacing and custom textures , but i need it other way)

width=800 height=423http://s18.postimg.org/95r39k115/2015_08_25_19_53_17.png[/img]

:D
Link to comment
Share on other sites

I think you should register custom renderer for the entity.

You can process some GL calls in the Render#doRender(...), and call the original renderer's Render#doRender there.

 

And to change color, you can call GL11.glColor(r, g, b, alpha) or GL11.glColor(r, g, b).

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

IEEP:

 

package ga.warixmods.akamegakillmod.events.extendedproperties;

 

import net.minecraft.entity.Entity;

import net.minecraft.entity.EntityLiving;

import net.minecraft.nbt.NBTTagCompound;

import net.minecraft.world.World;

import net.minecraftforge.common.IExtendedEntityProperties;

 

public class EntityExtendedProperties implements IExtendedEntityProperties {

protected EntityLiving theEntity;

protected World theWorld;

protected boolean isFrozen;

public final static String extendedPropertiesName = "AGKM:EPEntity";

 

@Override

public void saveNBTData(NBTTagCompound parCompound) {

NBTTagCompound compound = new NBTTagCompound();

compound.setBoolean("AGKM:isFrozen", false);

 

}

 

public static EntityExtendedProperties get(EntityLiving living)

{

return (EntityExtendedProperties) living.getExtendedProperties(extendedPropertiesName);

}

@Override

public void loadNBTData(NBTTagCompound compound) {

        this.isFrozen = compound.getBoolean("AGKM:isFrozen");

 

 

}

 

@Override

public void init(Entity entity, World world) {

theEntity = (EntityLiving) entity;

theWorld = world;

 

}

public void setFrozen(boolean state)

{

this.isFrozen = state;

}

public boolean getFrozen()

{

return this.isFrozen;

}

}

 

 

Rendering:

 

package ga.warixmods.akamegakillmod.events;

 

import org.lwjgl.opengl.GL11;

 

import ga.warixmods.akamegakillmod.events.extendedproperties.EntityExtendedProperties;

import net.minecraft.client.renderer.GlStateManager;

import net.minecraft.client.renderer.OpenGlHelper;

import net.minecraft.entity.EntityLiving;

import net.minecraft.util.ResourceLocation;

import net.minecraftforge.client.event.RenderLivingEvent;

import net.minecraftforge.common.MinecraftForge;

import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

 

public class OnRenderEntityLiving {

 

private boolean isFrozen;

 

public OnRenderEntityLiving()

{

MinecraftForge.EVENT_BUS.register(this);

}

@SubscribeEvent

public void RenderLivingEvent(RenderLivingEvent.Pre event)

{

 

EntityExtendedProperties props = EntityExtendedProperties.get((EntityLiving) event.entity);

isFrozen = props.getFrozen();

if(isFrozen)

{

GlStateManager.pushMatrix();

GL11.glColor3f(1.2f, 1.0f, 0.8f);

GlStateManager.popMatrix();

 

}

 

}

}

 

 

Entity constructing:

 

package ga.warixmods.akamegakillmod.events;

 

import ga.warixmods.akamegakillmod.events.extendedproperties.EntityExtendedProperties;

import net.minecraft.entity.EntityLiving;

import net.minecraftforge.common.MinecraftForge;

import net.minecraftforge.event.entity.EntityEvent.EntityConstructing;

import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

 

public class OnEntityConstructing {

public OnEntityConstructing()

{

MinecraftForge.EVENT_BUS.register(this);

}

 

@SubscribeEvent

public void onEntityConstructing(EntityConstructing event) {

 

if(event.entity instanceof EntityLiving)

{

 

event.entity.registerExtendedProperties("AGKM:EPEntity", new EntityExtendedProperties());

 

 

}

 

}

}

 

 

Setting data:

 

package ga.warixmods.akamegakillmod.events;

import java.util.Random;

 

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozen;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenBat;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenBlaze;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenCaveSpider;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenChicken;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenCreeper;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenDragon;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenEnderMite;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenEnderman;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenGhast;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenGolem;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenGuardian;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenHorse;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenMagmaCube;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenMooshroom;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenOcelot;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenPig;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenPigZombie;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenRabbit;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenSheep;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenSilverfish;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenSkeleton;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenSlime;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenSpider;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenSquid;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenVillager;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenWitch;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenWither;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenWolf;

import ga.warixmods.akamegakillmod.entity.frozen.EntityFrozenZombie;

import ga.warixmods.akamegakillmod.entity.special.EntityRocketLauncher;

import ga.warixmods.akamegakillmod.events.extendedproperties.EntityExtendedProperties;

import ga.warixmods.akamegakillmod.init.AkameItems;

import net.minecraft.entity.Entity;

import net.minecraft.entity.EntityLiving;

import net.minecraft.entity.boss.EntityDragon;

import net.minecraft.entity.boss.EntityWither;

import net.minecraft.entity.monster.EntityBlaze;

import net.minecraft.entity.monster.EntityCaveSpider;

import net.minecraft.entity.monster.EntityCreeper;

import net.minecraft.entity.monster.EntityEnderman;

import net.minecraft.entity.monster.EntityEndermite;

import net.minecraft.entity.monster.EntityGhast;

import net.minecraft.entity.monster.EntityGolem;

import net.minecraft.entity.monster.EntityGuardian;

import net.minecraft.entity.monster.EntityMagmaCube;

import net.minecraft.entity.monster.EntityPigZombie;

import net.minecraft.entity.monster.EntitySilverfish;

import net.minecraft.entity.monster.EntitySkeleton;

import net.minecraft.entity.monster.EntitySlime;

import net.minecraft.entity.monster.EntitySpider;

import net.minecraft.entity.monster.EntityWitch;

import net.minecraft.entity.monster.EntityZombie;

import net.minecraft.entity.passive.EntityBat;

import net.minecraft.entity.passive.EntityChicken;

import net.minecraft.entity.passive.EntityCow;

import net.minecraft.entity.passive.EntityHorse;

import net.minecraft.entity.passive.EntityMooshroom;

import net.minecraft.entity.passive.EntityOcelot;

import net.minecraft.entity.passive.EntityPig;

import net.minecraft.entity.passive.EntityRabbit;

import net.minecraft.entity.passive.EntitySheep;

import net.minecraft.entity.passive.EntitySquid;

import net.minecraft.entity.passive.EntityVillager;

import net.minecraft.entity.passive.EntityWolf;

import net.minecraft.entity.player.EntityPlayer;

import net.minecraft.nbt.NBTTagCompound;

import net.minecraft.potion.PotionEffect;

import net.minecraft.world.World;

import net.minecraftforge.common.MinecraftForge;

import net.minecraftforge.event.entity.player.EntityInteractEvent;

import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

 

public class FreezeEntity {

 

 

public FreezeEntity()

{

MinecraftForge.EVENT_BUS.register(this);

}

@SubscribeEvent

    public void EntityInteractEvent(EntityInteractEvent event) {

World worldIn = event.entityPlayer.worldObj;

EntityPlayer playerIn = event.entityPlayer;

Entity target = event.target;

Random rand = new Random();

 

if(playerIn.getHeldItem() != null)

{

 

 

 

//freeze wand

if(playerIn.getHeldItem().hasTagCompound() && event.entityPlayer.getHeldItem().getItem() == AkameItems.demons_extract_wand)

{

if( event.entityPlayer.getHeldItem().getTagCompound().hasKey("id") && event.entityPlayer.getHeldItem().getTagCompound().getInteger("id") == 3)

{

EntityFrozenChicken e = new EntityFrozenChicken(worldIn);

 

boolean is = false;

boolean is2 = true;

boolean isFrozen = false;

if(target instanceof EntityLiving)

{

EntityExtendedProperties props = EntityExtendedProperties.get((EntityLiving) target);

props.setFrozen(true);

 

}

 

 

//lands of closed braces

 

 

}

}

}

 

}

 

 

}

 

   

 

 

 

:D
Link to comment
Share on other sites

public class EntityExtendedProperties implements IExtendedEntityProperties
{
protected EntityLivingBase theEntity;
protected boolean isFrozen;
public final static String IEEP_NAME = "AGKMEPEntity";

public static EntityExtendedProperties get(EntityLivingBase entity)
{
	return (EntityExtendedProperties) entity.getExtendedProperties(IEEP_NAME);
}

@Override
public void saveNBTData(NBTTagCompound nbt)
{
	NBTTagCompound data = new NBTTagCompound();
	data.setBoolean("isFrozen", this.isFrozen());
	nbt.setTag(IEEP_NAME, data);
}

@Override
public void loadNBTData(NBTTagCompound nbt)
{   
	NBTTagCompound data = nbt.getCompoundTag(IEEP_NAME);
	this.isFrozen = data.getBoolean("isFrozen");
}

@Override
public void init(Entity entity, World world)
{
	this.theEntity = (EntityLivingBase) entity;
}

public boolean isFrozen()
{
	return this.isFrozen;
}

public void setFrozen(boolean state)
{
	this.isFrozen = state;
}
}

 

* Don't use colons, bro, jsut don't.

* You don't need world field - its alredy inside entity.

* Use EntityLivingBase, not EntityLiving.

* That's how you use NBT.

* Learn Java conventions (static = capitals)

1.7.10 is no longer supported by forge, you are on your own.

Link to comment
Share on other sites

I just changed what you said:

IEEP:

 

package ga.warixmods.akamegakillmod.events.extendedproperties;

 

import net.minecraft.entity.Entity;

import net.minecraft.entity.EntityLivingBase;

import net.minecraft.nbt.NBTTagCompound;

import net.minecraft.world.World;

import net.minecraftforge.common.IExtendedEntityProperties;

 

public class EntityExtendedProperties implements IExtendedEntityProperties {

protected EntityLivingBase theEntity;

protected boolean isFrozen;

public final static String IEEP_NAME = "AGKMEPEntity";

 

public static EntityExtendedProperties get(EntityLivingBase entity)

{

return (EntityExtendedProperties) entity.getExtendedProperties(IEEP_NAME);

}

 

@Override

public void saveNBTData(NBTTagCompound nbt)

{

NBTTagCompound data = new NBTTagCompound();

data.setBoolean("isFrozen", this.isFrozen());

nbt.setTag(IEEP_NAME, data);

}

 

@Override

public void loadNBTData(NBTTagCompound nbt)

NBTTagCompound data = nbt.getCompoundTag(IEEP_NAME);

this.isFrozen = data.getBoolean("isFrozen");

}

 

@Override

public void init(Entity entity, World world)

{

this.theEntity = (EntityLivingBase) entity;

}

 

public boolean isFrozen()

{

return this.isFrozen;

}

 

public void setFrozen(boolean state)

{

this.isFrozen = state;

}

}

 

Rendering:

 

package ga.warixmods.akamegakillmod.events;

 

import org.lwjgl.opengl.GL11;

 

import ga.warixmods.akamegakillmod.events.extendedproperties.EntityExtendedProperties;

import net.minecraft.client.renderer.GlStateManager;

import net.minecraft.entity.EntityLivingBase;

import net.minecraftforge.client.event.RenderLivingEvent;

import net.minecraftforge.common.MinecraftForge;

import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

 

public class OnRenderEntityLiving {

 

private boolean isFrozen;

 

public OnRenderEntityLiving()

{

MinecraftForge.EVENT_BUS.register(this);

}

@SubscribeEvent

public void RenderLivingEvent(RenderLivingEvent.Pre event)

{

 

EntityExtendedProperties props = EntityExtendedProperties.get((EntityLivingBase) event.entity);

isFrozen = props.isFrozen();

if(isFrozen)

{

GlStateManager.pushMatrix();

GL11.glColor3f(1.2f, 1.0f, 0.8f);

GlStateManager.popMatrix();

 

}

 

}

}

 

 

 

Setting data:

 

package ga.warixmods.akamegakillmod.events;

import ga.warixmods.akamegakillmod.entity.special.EntityRocketLauncher;

import ga.warixmods.akamegakillmod.events.extendedproperties.EntityExtendedProperties;

import ga.warixmods.akamegakillmod.init.AkameItems;

import net.minecraft.entity.Entity;

import net.minecraft.entity.EntityLiving;

import net.minecraft.entity.EntityLivingBase;

import net.minecraft.entity.player.EntityPlayer;

import net.minecraft.potion.PotionEffect;

import net.minecraft.world.World;

import net.minecraftforge.common.MinecraftForge;

import net.minecraftforge.event.entity.player.EntityInteractEvent;

import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

 

public class FreezeEntity {

 

 

public FreezeEntity()

{

MinecraftForge.EVENT_BUS.register(this);

}

@SubscribeEvent

    public void EntityInteractEvent(EntityInteractEvent event) {

World worldIn = event.entityPlayer.worldObj;

 

EntityPlayer playerIn = event.entityPlayer;

Entity target = event.target;

 

 

if(playerIn.getHeldItem() != null)

{

 

 

 

//freeze wand

if(playerIn.getHeldItem().hasTagCompound() && event.entityPlayer.getHeldItem().getItem() == AkameItems.demons_extract_wand)

{

if( event.entityPlayer.getHeldItem().getTagCompound().hasKey("id") && event.entityPlayer.getHeldItem().getTagCompound().getInteger("id") == 3)

{

 

 

boolean is = false;

boolean is2 = true;

boolean isFrozen = false;

if(target instanceof EntityLivingBase)

{

EntityExtendedProperties props = EntityExtendedProperties.get((EntityLivingBase) target);

props.setFrozen(true);

 

}

 

 

 

 

 

}

}

}

 

}

 

 

}

 

   

 

 

 

 

Registering on entity construction:

 

package ga.warixmods.akamegakillmod.events;

 

import ga.warixmods.akamegakillmod.events.extendedproperties.EntityExtendedProperties;

import net.minecraft.entity.EntityLivingBase;

import net.minecraftforge.common.MinecraftForge;

import net.minecraftforge.event.entity.EntityEvent.EntityConstructing;

import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

 

public class OnEntityConstructing {

public OnEntityConstructing()

{

MinecraftForge.EVENT_BUS.register(this);

}

 

@SubscribeEvent

public void onEntityConstructing(EntityConstructing event) {

 

if(event.entity instanceof EntityLivingBase)

{

 

event.entity.registerExtendedProperties("AGKMEPEntity", new EntityExtendedProperties());

 

 

}

 

}

}

 

 

 

:D
Link to comment
Share on other sites

It does save, you need packets to synch cows after they load (loading is server side).

 

Also, I've cleaned up your code:

public class EntityExtendedProperties implements IExtendedEntityProperties
{
protected EntityLivingBase theEntity;
protected boolean isFrozen;
public final static String IEEP_NAME = "AGKMEPEntity";

public EntityExtendedProperties(EntityLivingBase entity)
{
	this.theEntity = entity;
}

public static void register(EntityLivingBase entity)
{
	entity.registerExtendedProperties(IEEP_NAME, new EntityExtendedProperties(entity));
}

public static EntityExtendedProperties get(EntityLivingBase entity)
{
	return (EntityExtendedProperties) entity.getExtendedProperties(IEEP_NAME);
}

@Override
public void saveNBTData(NBTTagCompound nbt)
{
	NBTTagCompound data = new NBTTagCompound();
	data.setBoolean("isFrozen", this.isFrozen());
	nbt.setTag(IEEP_NAME, data);
	System.out.println(nbt);
}

@Override
public void loadNBTData(NBTTagCompound nbt)
{
	NBTTagCompound data = nbt.getCompoundTag(IEEP_NAME);
	this.isFrozen = data.getBoolean("isFrozen");
	System.out.println(nbt);
}

@Override
public void init(Entity entity, World world)
{}

public boolean isFrozen()
{
	return this.isFrozen;
}

public void setFrozen(boolean state)
{
	this.isFrozen = state;
}
}

public class ForgeEvents
{
@SubscribeEvent
public void onEntityConstructing(EntityConstructing event)
{
	if (event.entity instanceof EntityLivingBase)
	{
		EntityExtendedProperties.register((EntityLivingBase) event.entity);
	}
}

@SubscribeEvent
public void EntityInteractEvent(EntityInteractEvent event)
{
	if (event.entityPlayer.getHeldItem() != null)
	{
		if (event.entityPlayer.getHeldItem().getItem() == Items.apple)
		{
			if (event.target instanceof EntityLivingBase)
			{
				EntityExtendedProperties.get((EntityLivingBase) event.target).setFrozen(true);
			}
		}
	}
}
}

public class ForgeEventsClient
{
@SubscribeEvent
public void RenderLivingEvent(RenderLivingEvent.Pre event)
{
	if (EntityExtendedProperties.get(event.entity).isFrozen())
	{
		GlStateManager.pushMatrix();
		GL11.glColor3f(0.5f, 2.0f, 10.0f);
		GlStateManager.popMatrix();
	}
}
}

 

* Have 2 classes for Forge events - common and client. Same goes if you ever use FML events.

* Don't register event class in its own constructor - it is not safe (bad practice to pass "this" from constructor).

* Register ForgeEventsClient in ClientProxy, logically ForgeEvents go to CommonProxy.

* Packets tutorials:

Long: http://www.minecraftforum.net/forums/mapping-and-modding/mapping-and-modding-tutorials/2137055-1-7-2-customizing-packet-handling-with

Cut and dried: http://www.minecraftforge.net/forum/index.php/topic,20135.0.html

 

You will be sending packet from PlayerEvent.StartTracking - occuring whenever player loads some entity on client. Event fires ONLY on server and should handle sending packets to players.

1.7.10 is no longer supported by forge, you are on your own.

Link to comment
Share on other sites

I'm still new to modding, so i don't really understand how world and client side work.How do i know which code run on which side ? Also from what i understood i have to send nbt data of entity that player start tracking to its client? I tried that and i don't know how to access that entity on client side.

my packet code:

 

package ga.warixmods.akamegakillmod;

 

import io.netty.buffer.ByteBuf;

import net.minecraft.client.Minecraft;

import net.minecraft.nbt.NBTTagCompound;

import net.minecraft.util.IThreadListener;

import net.minecraft.world.WorldServer;

import net.minecraftforge.fml.common.network.ByteBufUtils;

import net.minecraftforge.fml.common.network.simpleimpl.IMessage;

import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;

import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;

 

public class SendPacket implements IMessage {

 

private String text;

private int num,recieved,id = 0;

private NBTTagCompound nbt;

public SendPacket() {}

 

public SendPacket(String text)

{

this.text = text;

this.recieved = 0;

}

 

public SendPacket(int num)

{

this.num = num;

this.recieved = 1;

}

 

public SendPacket(NBTTagCompound nbt,int id) {

this.nbt = nbt;

this.id = id;

 

 

}

 

@Override

public void fromBytes(ByteBuf buf) {

switch(this.recieved)

{

    case 0:

   

this.text = ByteBufUtils.readUTF8String(buf);

break;

    case 1:

   

this.num = ByteBufUtils.readVarInt(buf, Integer.MAX_VALUE);

    break;

    case 2:

    this.nbt = ByteBufUtils.readTag(buf);

    this.id = ByteBufUtils.readVarInt(buf, Integer.MAX_VALUE);

}

}

 

@Override

public void toBytes(ByteBuf buf) {

switch(this.recieved)

{

    case 0:

   

ByteBufUtils.writeUTF8String(buf, this.text);

break;

    case 1:

   

ByteBufUtils.writeVarInt(buf,this.num, Integer.MAX_VALUE);

    break;

    case 2:

    ByteBufUtils.writeTag(buf, this.nbt);

    ByteBufUtils.writeVarInt(buf, this.id, Integer.MAX_VALUE);

}

}

public static class Handler implements IMessageHandler<SendPacket, IMessage>{

 

@Override

public IMessage onMessage(final SendPacket message, final MessageContext ctx)

{

IThreadListener mainThread = (WorldServer) ctx.getServerHandler().playerEntity.worldObj;

IThreadListener mainThreadClient = Minecraft.getMinecraft();

if(ctx.side.isServer())

{

        mainThread.addScheduledTask(new Runnable()

        {

      @Override

      public void run()

        {

        //this is from other parts of mod

        switch(message.recieved)

        {

       

        case 0:

        String text = message.text;

        int num = message.num;

       

        String idS = text.substring(3, 4);

        int idI = Integer.parseInt(idS);

       

        text = text.substring(4);

        switch(idI)

        {

        case 0:

       

        ctx.getServerHandler().playerEntity.getHeldItem().getTagCompound().setInteger("id",Integer.parseInt(text));

        break;

        case 1:

       

        ctx.getServerHandler().playerEntity.getHeldItem().getTagCompound().setInteger("id", Integer.parseInt(text));

        break;

        case 2:

       

        ctx.getServerHandler().playerEntity.getHeldItem().getTagCompound().setInteger("idU",Integer.parseInt(text));

        break;

        case 3:

       

        ctx.getServerHandler().playerEntity.getHeldItem().getTagCompound().setInteger("id"+Integer.parseInt(text),0);

        break;

       

        }

        break;

        case 1:

        break;

        }

        }});

}

//and i guess i have to sync it here?

                        else

{

mainThreadClient.addScheduledTask(new Runnable()

        {

      @Override

      public void run()

        {

    EntityLivingBase target =

       

                }

        });}

return null;

}

 

 

 

 

}

}

 

 

:D
Link to comment
Share on other sites

Minecraft cosists of 2 "code" sides and 4 "logical" sides (read: threads).

 

1. Looking as MC from logical side:

There are 4 threads:

Server

Client

Server-Netty

Client-Netty

 

1.1. When running Client.jar:

* SP: You have all 4 threads (4) (server is being ran in background)

* MP: You only have client threads (2), server threads are ran by server you connected to (meaning you don't have any access to it, only communication are packets)

Note that you also use packets when on SP - they are being sent "interanlly".

 

1.2. When running Dedicated.jar:

* Dedicated server has always ONLY 2 threads - server ones. Clients connect to it and server threads operate on data (save/load) while clients only display them.

 

2. Looking at MC from source view:

There is common code - used by both server and client threads, no matter if Client.jar or Dedicated.jar.

There is code reserved for client and for server.

Whenever you see/use:

@SideOnly(Side.SERVER)
@SideOnly(Side.CLIENT)

It means that given class/method/filed is present ONLY when run on either Client.jar or Dedicated.jar.

E.g: Minecraft.class is @SideOnly(Side.CLIENT), that means that class is NOT present (not loaded to VM) when you are running Dedicated.jar.

 

That is why you use proxies when you need some client/server specific getters/setters.

 

3. What thread use what code?

General rule is:

Netty threads should NEVER access game threads:

http://greyminecraftcoder.blogspot.com.au/2015/01/thread-safety-with-network-messages.html

 

Now to actual question:

Most of common code will be used by both threads (server/client). Whenever something gets calles you can perform "logical-check" with:

world.isRemote

true = this code is being ran by client thread

false = this code is being ran by server

 

Same code can and will often be used by both threads, that's why you can see those checks everywhere.

 

Rule is:

Manipulating data happens on server (!world.isRemote).

 

4. Synchronization:

Let's talk about events - most of Forge ones are being called on both logical sides.

Since you are here about IEEP interface:

EntityConstructing event is called on both sides.

Both client and server logical thread will assign new IEEP to given entity whenever it's being constructed.

Since most calculations should/will happen on server, only server updates given entity's IEEP values. Client needs to be notified.

That's where packets kick in. You send them, on client you handle them - generate new Runnable and put it into maing client thread.

 

Example of working with IEEP sync:

// in IEEP
public void setExp(long exp, boolean notify)
{
if (exp < 0) exp = 0;
this.exp = exp;
if (notify) // notify will be true only on server side (it's my method).
{
	Dispatcher.sendPacketTo(new PacketSendExp(this.player, this.getExp()), this.player);
}
}

public class PacketSendExp implements IMessage
{
private int playerId;
private long exp;

public PacketSendExp()
{}

public PacketSendExp(EntityPlayer player, long exp)
{
	this.playerId = player.getEntityId();
	this.exp = exp;
}

@Override
public void toBytes(ByteBuf buffer)
{
	buffer.writeInt(this.playerId);
	buffer.writeLong(this.exp);
}

@Override
public void fromBytes(ByteBuf buffer)
{
	this.playerId = buffer.readInt();
	this.exp = buffer.readLong();
}

public static class HandlerExp extends AbstractClientMessageHandler<PacketSendExp>
{
	@Override
	public void run(EntityPlayerSP player, PacketSendExp message)
	{
		Entity e = player.worldObj.getEntityByID(message.playerId);
		if (e instanceof EntityPlayer)
		{
			IEEP.get((EntityPlayer) e).setExp(message.exp, false);
		}
	}
}
}

 

Above will update (by sending packet) owner of given IEEP whenever server changes exp value.

 

Note to code above:

I have quite background abstraction there. the run() method is actually wrapped Runnable.

 

5. Just call me: Skype: ernio333

If you want more useful info (really useful).

1.7.10 is no longer supported by forge, you are on your own.

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.