Jump to content

Recommended Posts

Posted

I have a custom entity class that has a constructor that doesn't seem to be working.  The entity is designed to die when it hits certain kinds of blocks, and it's correctly done so.  The problem was, the block it was sent from can be the same kind as it can die on, so I wanted to store the source block's blockPos in the entity class so I can make sure it doesn't die on the source block.  I also have an orientation variable that changes the color of the entity depending on its value.  The problem is I tried to set these in a constructor, but said constructor doesn't seem to be setting these values.  I found a work-around for the position part, but the orientation part I can't seem to fix.  Can anyone see what might be going wrong?

 

[spoiler=entity class]

package com.trekkiecub.oddsandends.entity;

import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.projectile.EntityThrowable;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

import com.trekkiecub.oddsandends.blocks.Block_Sceptre_Top;
import com.trekkiecub.oddsandends.util.OAE_Func;

public class Entity_PowerOrb extends EntityThrowable {
private int initX = -1;
private int initY = -1;
private int initZ = -1;
private int lifeTimer = 0;
private int orientation = 0;
private int timerMax = 300;
private int texFrames = 3;
public Entity_PowerOrb(World worldIn) {
	super(worldIn);
	this.setSize(0.25F, 0.25F);
}
public Entity_PowerOrb(World worldIn, double d, double e, double f, int orientation)
{
	super(worldIn, d, e, f);
	this.initX = MathHelper.floor_double(d);
	this.initY = MathHelper.floor_double(e);
	this.initZ = MathHelper.floor_double(f);
	this.setSize(0.25F, 0.25F);
	this.orientation = orientation;
}

public void setOrientation(int o)
{
	this.orientation = o;
}

public int getOrientation() {return orientation;}

public Entity_PowerOrb(World worldIn, EntityLivingBase throwerIn)
{
	super(worldIn, throwerIn);
}

@Override
protected void entityInit() {
	// TODO Auto-generated method stub

}

public void readEntityFromNBT(NBTTagCompound compound) {
	super.readEntityFromNBT(compound);
	this.orientation = compound.getInteger("orientation");
	this.lifeTimer = compound.getInteger("lifeTimer");
	this.initX = compound.getInteger("initX");
	this.initY = compound.getInteger("initY");
	this.initZ = compound.getInteger("initZ");

}

public void writeEntityToNBT(NBTTagCompound compound) {
	super.writeEntityToNBT(compound);
	compound.setInteger("orientation", this.orientation);
	compound.setInteger("lifeTimer", this.lifeTimer);
	compound.setInteger("posX", this.initX);
	compound.setInteger("posY", this.initY);
	compound.setInteger("posZ", this.initZ);
}

public void onUpdate()
{
	// Kill entity if too old
	lifeTimer++;
	if (lifeTimer > timerMax)
	{
		this.kill();
	}

	this.lastTickPosX = this.posX;
        this.lastTickPosY = this.posY;
        this.lastTickPosZ = this.posZ;
        
        // Ray Tracing
        
        Vec3d vec3d = new Vec3d(this.posX, this.posY, this.posZ);
        Vec3d vec3d1 = new Vec3d(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
        RayTraceResult raytraceresult = this.worldObj.rayTraceBlocks(vec3d, vec3d1);
        vec3d = new Vec3d(this.posX, this.posY, this.posZ);
        vec3d1 = new Vec3d(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);

        if (raytraceresult != null)
        {
            vec3d1 = new Vec3d(raytraceresult.hitVec.xCoord, raytraceresult.hitVec.yCoord, raytraceresult.hitVec.zCoord);
        }
        
        if (raytraceresult != null)
        {
        	this.onImpact(raytraceresult);
        }
        
        // Update Initial Position
        if (this.initY < 0)
        {
        	this.initX = MathHelper.floor_double(this.posX);
        	this.initY = MathHelper.floor_double(this.posY);
        	this.initZ = MathHelper.floor_double(this.posZ);
        }
        
        BlockPos source = new BlockPos(this.initX, this.initY, this.initZ);
        if (!source.equals(this.getPosition()))
        {
        	if (this.worldObj.getBlockState(this.getPosition()).getBlock() instanceof Block_Sceptre_Top)
        	{
        		Vec3d currentCenter = OAE_Func.blockCenter(this.getPosition());
            	if (vec3d.distanceTo(currentCenter) < 0.25D)
            	{
            		this.kill();
            	}	
        	}
        }
        
        
	this.posX += this.motionX;
	this.posY += this.motionY;
	this.posZ += this.motionZ;
	this.setPosition(this.posX, this.posY, this.posZ);
}

@Override
public boolean func_189652_ae()
{
	return true;
}

@SideOnly(Side.CLIENT)
    public boolean isInRangeToRenderDist(double distance)
    {
        double d0 = this.getEntityBoundingBox().getAverageEdgeLength() * 4.0D;

        if (Double.isNaN(d0))
        {
            d0 = 4.0D;
        }

        d0 = d0 * 64.0D;
        return distance < d0 * d0;
    }
public int getTexByLifetime()
{
	if (lifeTimer%(2*texFrames) < texFrames)
	{
		return lifeTimer%texFrames;
	}
	else
	{
		return texFrames - 1 - (lifeTimer%texFrames);
	}
}

protected void onImpact(RayTraceResult result) {
	if (result.typeOfHit == RayTraceResult.Type.BLOCK && !(this.worldObj.getBlockState(result.getBlockPos()).getBlock() instanceof Block_Sceptre_Top))
	{
		this.orientation = 1 - this.orientation;
	}
	else if (result.typeOfHit == RayTraceResult.Type.ENTITY && result.entityHit instanceof Entity_PowerOrb)
	{
		this.kill();
	}
}


}

 

 

[spoiler=tile entity onUpdate]

public void updateEntity()
{
	if (!this.worldObj.isRemote)
	{
		cooldown++;
		cooldown = cooldown%maxCooldown;
		if (cooldown == 0 && destinations.size() != 0)
		{
			BlockPos targetPos;
			for (int i = 0; i < destinations.size(); i++)
			{
				targetPos = destinations.get(i).getBlockPos();
				Entity_PowerOrb entity = new Entity_PowerOrb(this.worldObj, this.pos.getX()+.5, this.pos.getY()+.375, this.pos.getZ()+.5, this.worldObj.rand.nextInt(2));
				entity.setThrowableHeading(targetPos.getX() + .5 - entity.posX, targetPos.getY() + .375 - entity.posY, targetPos.getZ() + .5 - entity.posZ, 0.05F, 0);
				this.worldObj.spawnEntityInWorld(entity);
			}
		}
		markDirty();
	}
}

 

 

[spoiler=Renderer]

package com.trekkiecub.oddsandends.render;

import com.trekkiecub.oddsandends.entity.Entity_PowerOrb;

import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.VertexBuffer;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

@SideOnly(Side.CLIENT)
public class RenderPowerOrb extends Render<Entity_PowerOrb>{
private static final ResourceLocation EXPERIENCE_ORB_TEXTURES = new ResourceLocation("textures/entity/experience_orb.png");
public RenderPowerOrb(RenderManager renderManager) {
	super(renderManager);
	this.shadowSize = 0.15F;
        this.shadowOpaque = 0.75F;
}

/**
     * Renders the desired {@code T} type Entity.
     */
@Override
    public void doRender(Entity_PowerOrb entity, double x, double y, double z, float entityYaw, float partialTicks)
    {
        if (!this.renderOutlines)
        {
            GlStateManager.pushMatrix();
            GlStateManager.translate((float)x, (float)y, (float)z);
            this.bindEntityTexture(entity);
            RenderHelper.enableStandardItemLighting();
            int i = entity.getTexByLifetime();
            float f = (float)(i % 4 * 16 + 0) / 64.0F;
            float f1 = (float)(i % 4 * 16 + 16) / 64.0F;
            float f2 = (float)(i / 4 * 16 + 0) / 64.0F;
            float f3 = (float)(i / 4 * 16 + 16) / 64.0F;
            float f4 = 1.0F;
            float f5 = 0.5F;
            float f6 = 0.25F;
            int j = entity.getBrightnessForRender(partialTicks);
            int k = j % 65536;
            int l = j / 65536;
            OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)k, (float)l);
            GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
            float f8 = 255.0F;
            float f9 = ((float)entity.getOrientation() * 100 + partialTicks) / 2.0F;
            
            l = (int)((MathHelper.sin(f9 + 0.0F) + 1.0F) * 0.5F * 255.0F);
            int i1 = 255;
            int j1 = (int)((MathHelper.sin(f9 + 4.1887903F) + 1.0F) * 0.1F * 255.0F);
            
            GlStateManager.translate(0.0F, 0.1F, 0.0F);
            GlStateManager.rotate(180.0F - this.renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
            GlStateManager.rotate((float)(this.renderManager.options.thirdPersonView == 2 ? -1 : 1) * -this.renderManager.playerViewX, 1.0F, 0.0F, 0.0F);
            float f7 = 0.3F;
            GlStateManager.scale(0.3F, 0.3F, 0.3F);
            Tessellator tessellator = Tessellator.getInstance();
            VertexBuffer vertexbuffer = tessellator.getBuffer();
            vertexbuffer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR_NORMAL);
            double redMult = entity.getOrientation();
            double greenMult = 0.2 + 0.3*(1 - entity.getOrientation());
            double blueMult = 1 - entity.getOrientation();
            int red = (int) (255 * redMult);
            int green = (int) (255 * greenMult);
            int blue = (int) (255 * blueMult);
            vertexbuffer.pos(-0.5D, -0.25D, 0.0D).tex((double)f, (double)f3).color(red, green, blue, 128).normal(0.0F, 1.0F, 0.0F).endVertex();
            vertexbuffer.pos(0.5D, -0.25D, 0.0D).tex((double)f1, (double)f3).color(red, green, blue, 128).normal(0.0F, 1.0F, 0.0F).endVertex();
            vertexbuffer.pos(0.5D, 0.75D, 0.0D).tex((double)f1, (double)f2).color(red, green, blue, 128).normal(0.0F, 1.0F, 0.0F).endVertex();
            vertexbuffer.pos(-0.5D, 0.75D, 0.0D).tex((double)f, (double)f2).color(red, green, blue, 128).normal(0.0F, 1.0F, 0.0F).endVertex();
            tessellator.draw();
            GlStateManager.disableBlend();
            GlStateManager.disableRescaleNormal();
            GlStateManager.popMatrix();
            super.doRender(entity, x, y, z, entityYaw, partialTicks);
        }
    }

@Override
protected ResourceLocation getEntityTexture(Entity_PowerOrb entity) {
	// TODO Auto-generated method stub
	return EXPERIENCE_ORB_TEXTURES;
}

}

 

 

Posted

At the moment, in the renderer.  The renderer is working perfectly, as it switches over if I change the orientation value manually in the entity class.

How are you changing it, I feel the problem is that orientation is not synced between client and server... Look into DataWatcher

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted

The renderer code does not modify anything in the entity class, just pull information from it.  As I said, the renderer works fine if I change the orientation value in the entity class itself.  The problem is that the constructor is not setting the value for the orientation when supplied via constructor.  I'll include the renderer code in my original post if something is wrong there.

 

I was also looking at my renderer code and noticed I was overriding the doRender function, and I'm not sure if I'm supposed to do that as I call the super class's doRender function.  Whether I overrode the parent function didn't change the outcome.

Posted

You should never set a value in the constructor.  There are something like three different constructors for entities, which are all used in different places.  Depending on which one you're using, that value might be being overwriten when the entity gets an update from the server that tells it what the server knows/sends to the client.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

The constructor I'm using is a custom one for the entity itself.  You can find the constructor in the code I supplied.

 

I'm trying to set values that will change from instance to instance of this entity.  How am I supposed to set said values without using a constructor (btw, a setter isn't working either)?

Posted

The client side doesnt care about your custom constructor.

It just gets told you have a entity on the server so it creates a new one using the World constructor. And then makes it read from NBT.

So As stated, there is no real reason to use custom constructors for entities, make sure your data is stored and sent to the client.

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

Posted

The renderer code does not modify anything in the entity class, just pull information from it.  As I said, the renderer works fine if I change the orientation value in the entity class itself. 

 

Although your main problem is with the custom constructor, as mentioned above, I think you still don't get the full scope of what I was explaining. There is the entity class and then there are instances of the entity class. For every entity that spawns in the game, there are actually two instances -- one on client and one on server. The fields in these instances can only be synced up through network packets. The built-in fields like position are automatically kept in sync through built-in packets.

 

Furthermore, the syncing isn't necessarily in both ways. Like if you update the position only on the client, it won't take effect for long because the next time the server sync's it will return to the old value.

 

So, from within a client side class like the renderer, you cannot actually change things like position, at least without sending a custom packet and handling it on the server.

 

It may appear to work for something that is visual like orientation because the visual effect is processed on the client. For example, if you had a custom field in your entity that controlled whether the entity glowed, if you set that on the client the glowing would probably work. However, if you save the game, you'd lose that glow because the save information only happens on the server side.

 

Not sure if that was clear, but it is an important concept. Basically the thing to remember there are two entity instances running in parallel and the server side is the master and they won't be synced unless you use custom packets.

 

One last important thing, if you ever spawn an entity from the client side, it might appear to work but is really just a phantom that isn't fully recognized by the game. This is actually okay for something like a particle that is a temporary visual effect, but generally better to have server aware of all entities.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Hi here is an update. I was able to fix the code so my mod does not crash Minecraft. Please understand that I am new to modding but I honestly am having a hard time understanding how anyone can get this to work without having extensive programming and debugging experience as well as searching across the Internet, multiple gen AI bots (claude, grok, openai), and examining source code hidden in the gradle directory and in various github repositories. I guess I am wrong because clearly there are thousands of mods so maybe I am just a newbie. Ok, rant over, here is a step by step summary so others can save the 3 days it took me to figure this out.   1. First, I am using forge 54.1.0 and Minecraft 1.21.4 2. I am creating a mod to add a shotgun to Minecraft 3. After creating the mod and compiling it, I installed the .jar file to the proper directory in Minecraft and used 1.21.4-forge-54.1.0 4. The mod immediately crashed with the error: Caused by: java.lang.NullPointerException: Item id not set 5. Using the stack trace, I determined that the Exception was being thrown from the net.minecraft.world.item.Item.Properties class 6. It seems that there are no javadocs for this class, so I used IntelliJ which was able to provide a decompiled version of the class, which I then examined to see the source of the error. Side question: Are there javadocs? 7. This method, specifically, was the culprit: protected String effectiveDescriptionId() {      return this.descriptionId.get(Objects.requireNonNull(this.id, "Item id not set"));  } 8. Now my quest was to determine how to set this.id. Looking at the same source file, I determined there was another method:  public Item.Properties setId(ResourceKey<Item> pId) {             this.id = pId;             return this;   } 9. So now, I need to figure out how to call setId(). This required working backwards a bit. Starting from the constructor, I stubbed out the variable p which is of type Item.Properties public static final RegistryObject<Item> SHOTGUN = ITEMS.register("shotgun", () -> new ShotgunItem(p)); Rather than putting this all on one line, I split it up for readability like this: private static final Item.Properties p = new Item.Properties().useItemDescriptionPrefix().setId(rk); Here is was the missing function, setId(), which takes a type of ResourceKey<Item>. My next problem is that due to the apparent lack of documentation (I tried searching the docs on this site) I could not determine the full import path to ResourceKey. I did some random searching on the Internet and stumbled across a Github repository which gave two clues: import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; Then I created the rk variable like this: private static ResourceKey<Item> rk = ResourceKey.create(Registries.ITEM, ResourceLocation.parse("modid:shotgunmod")); And now putting it all together in order: private static ResourceKey<Item> rk = ResourceKey.create(Registries.ITEM, ResourceLocation.parse("modid:shotgunmod")); private static final Item.Properties p = new Item.Properties().useItemDescriptionPrefix().setId(rk); public static final RegistryObject<Item> SHOTGUN = ITEMS.register("shotgun", () -> new ShotgunItem(p)); This compiled and the mod no longer crashes. I still have more to do on it, but hopefully this will save someone hours. I welcome any feedback and if I missed some obvious modding resource or tutorial that has this information. If not, I might suggest we add it somewhere for people trying to write a mod that doesn't crash. Thank you !!!  
    • I will keep adding to this thread with more information in case anyone can help, or at the very least I can keep my troubleshooting organized. I decided to downgrade to 54.1.0 in the hopes that this would fix the issue but it didn't. At least now I am on a "recommended" version. The crash report did confirm my earlier post that the Exception is coming from effectiveDescriptionId(). I'll continue to see if I can find a way to set the ID manually.   Caused by: java.lang.NullPointerException: Item id not set         at java.base/java.util.Objects.requireNonNull(Objects.java:259) ~[?:?]         at TRANSFORMER/[email protected]/net.minecraft.world.item.Item$Properties.effectiveDescriptionId(Item.java:465) ~[forge-1.21.4-54.1.0-client.jar!/:?]         at TRANSFORMER/[email protected]/net.minecraft.world.item.Item.<init>(Item.java:111) ~[forge-1.21.4-54.1.0-client.jar!/:?]         at TRANSFORMER/[email protected]/com.example.shotgunmod.ShotgunItem.<init>(ShotgunItem.java:19) ~[shotgunmod-1.0.0.jar!/:1.0.0]         at TRANSFORMER/[email protected]/com.example.shotgunmod.ModItems.lambda$static$0(ModItems.java:15) ~[shotgunmod-1.0.0.jar!/:1.0.0]         at TRANSFORMER/[email protected]/net.minecraftforge.registries.DeferredRegister$EventDispatcher.lambda$handleEvent      
    • It just randomly stop working after a rebooted my dedicated server PLEASE HELP!   com.google.gson   Failed to start the minecraft server com.google.gson.JsonSyntaxException: Expected a com.google.gson.JsonObject but was com.google.gson.JsonPrimitive; at path $  
    • It was working perfectly fine last night but now I'm getting an exit code -1 with the textbox: The game crashed: rendering overlay Error: net.minecraftforge.fml.ModLoadingException: Supplementaries (supplementaries) encountered an error during the done event phase Here's the crash log: https://pastebin.com/KmesArYS Any help is apricated
    • Link to Crashlog: https://pastebin.com/bKqH9fx2 Trying to set up a custom mod pack, was going smoothly up until recently as the WorldLoader screen, (the one that appears when you select "create new world" in Singleplayer), was clicked to test that it was running fine. Most Recent Few mods added were; - Create (+ its addons) - Immersive Weathering [Forge] I've tried all I could think of since loading up the game worked fine and I've never had this issue before.  Any help is appreciated.  
  • Topics

×
×
  • Create New...

Important Information

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