Jump to content

Recommended Posts

Posted

Forgive me if this isn't the right place to post this, but..

 

Can anyone teach me or point me towards a good tutorial for making

TileEntities

?

All of my Googling has proven fruitless and I want to play around with making said

TileEntites

.

GameSlayar

Forgive my noobiness!

Posted

1. Create a class that extends TileEntity

2. Implement ITileEntityProvider in your Block class and return an instance of the TileEntity class you just created from #createNewTileEntity

3. Register your TileEntity:

GameRegistry.registerTileEntity(YourTileEntityClass.class, ModInfo.ID + ":tileEntityUniqueName");

 

That's pretty much it. I like to use the mod_id in the registration to help prevent potential conflicts with other mods.

 

So now you have a TileEntity... but what do you want it for?

Posted

In short, I want to create a campfire block that can be lit and extinguished by right clicking. I wasn't sure how to use

#onBlockActivated

since I couldn't actually right click the block in-game.

So I assumed that to be right-clicked, a block must be/have a

TileEntity

.

 

I hope I'm right in that regard. If not, please correct me.

GameSlayar

Forgive my noobiness!

Posted

Well, here's my code for my block. It seems (as usual) that I forgot to put

@Override

before the method. But now it seems to work.

Almost.

 

Now the problem is that whenever I try to right click the block, it triggers

#onBlockActivated

twice.

I end up with something like this in the console:

//Me trying to right-click the block
true
false

//Trying to click again
true
false

 

Anyways, here's the actual block code:

 

package gameslayar.practice.common.blocks;

import java.util.Random;

import gameslayar.practice.common.PracticeCreativeTab;
import gameslayar.practice.common.PracticeMain;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

public class CampfireCoaled extends Block {

private final String name = "campfireCoaled";
private boolean active = false;
private final float[] bounds = { //(In pixels)
		2F,     //Min X
		0F,     //Min Y
		2F,     //Min Z
		16F,    //Max X
		9.5F,   //Max Y
		16F     //Max Z
};

//Basic Properties
public CampfireCoaled() {
	super(Material.wood);
	setUnlocalizedName(PracticeMain.MODID + "_" + name);
	setCreativeTab(PracticeCreativeTab.campingTab);
	setHarvestLevel("axe", 0);
	setHardness(2);
	setLightLevel(5);
	setBlockBounds(
			(1F/16F * bounds[0]),
			(1F/16F * bounds[1]),
			(1F/16F * bounds[2]),
			(1F/16F * bounds[3]),
			(1F/16F * bounds[4]),
			(1F/16F * bounds[5])
			);
	GameRegistry.registerBlock(this, name);

}

//***

//Makes sure that all the blocks around are rendered as well because 
//this isn't a full 1x1x1 block
@Override
public boolean isOpaqueCube() {
	return false;
}
//Corrects lighting around the block
@Override
public boolean isFullCube() {
	return false;
}

@Override
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumFacing side, float hitX, float hitY, float hitZ) {
	if(active) {
		active = false;
		System.out.println(active);
		return false;
	} else {
		active = true;
		System.out.println(active);
		return true;
	}
}

//Particle effects. Fancy fire & smoke.
@Override
@SideOnly(Side.CLIENT)
public void randomDisplayTick(World world, BlockPos pos, IBlockState state, Random random) {
	if(active) {
		float f1 = (float)(pos.getX()+0.5F);
		float f2 = (float)(pos.getY()+0.7F);
		float f3 = (float)(pos.getZ()+0.5F);
		float f4 = random.nextFloat() * 0.1F;
		float f5 = random.nextFloat() * -0.1F;

		world.spawnParticle(
				EnumParticleTypes.FLAME,
				(float)(f1+f4),
				(float)(f2),
				(float)(f3+f5),
				0.0D,
				0.0D,
				0.0D,
				new int[0]
				);

		f4 = (float)random.nextFloat() * 0.3F - 0.1F;
		f5 = (float)random.nextFloat() * -0.3F + 0.1F;

		world.spawnParticle(
				EnumParticleTypes.SMOKE_LARGE,
				(float)(f1+f4),
				(float)(f2+0.3F),
				(float)(f3+f5),
				0.0D,
				0.0D,
				0.0D,
				new int[0]
				);
	}
}


//***

public String getName() {
	return name;
}
}

 

GameSlayar

Forgive my noobiness!

Posted

Block#onBlockActivated

is called on both the client and server (like most methods).

 

You can't store mutable data in fields of your

Block

or

Item

classes, these are singletons so only one instance of the class exists per block/item type. Any changes you make will be shared between all occurrences of the block/item.

 

You need to use the block's

IBlockState

to store the activated state:

  • Create your properties (using the
    IProperty

    implementations) and store them as

    public static final

    fields

  • Override
    Block#createBlockState

    to return a new instance of

    BlockState

    , using

    this

    and the properties as constructor arguments

  • Override
    Block#getStateFromMeta

    and

    Block#getMetaFromState

    to convert between the

    IBlockState

    and metadata

  • Use
    blockState.getBaseState()

    to get the base state, then chain

    IBlockState#withProperty

    calls to set each property's value before passing the result to

    Block#setDefaultState

    in the constructor to set the default state

 

You can use

IBlockState#getValue

to get the value of a property and

World#setBlockState

to change the state at the specified position.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted

Thank you, but while your reply is probably well explained to most people, I can't help but have a little trouble understanding.

 

In short, your last bullet point confuses me. Would you mind explaining it in terms a less skilled modder would understand?

 

PS - In this method I'm confused about what I'm supposed to return exactly.

@Override
public int getMetaFromState(IBlockState state) {
    Boolean type = (Boolean) state.getValue(LIT);
    return type //Not sure how to return the metadata here
}

 

PPS - Sorry to be a pain in the ass

GameSlayar

Forgive my noobiness!

Posted

PS -

EDIT: I think I've got it. Is this how it works?

 

@Override
public int getMetaFromState(IBlockState state) {
    Boolean type = (Boolean) state.getValue(LIT);
    if(type) {
    	return(1);
    } else {
    	return(0);
    }
}

GameSlayar

Forgive my noobiness!

Posted

PS -

EDIT: I think I've got it. Is this how it works?

 

@Override
public int getMetaFromState(IBlockState state) {
    Boolean type = (Boolean) state.getValue(LIT);
    if(type) {
    	return(1);
    } else {
    	return(0);
    }
}

 

That should work, but I have a few minor nitpicks:

  • Name your variables properly.
    type

    isn't a type of any kind, it's the value of the

    LIT

    property so call it something like

    lit

    or

    isLit

    .

    • Use raw primitive types (
      boolean

      ) rather than boxed primitive types (

      Boolean

      ) when possible. Generic type arguments require boxed types, but Java will automatically box and unbox primitives as needed. See this page for more details on boxing.

    • There's no need for the parentheses around the returned values, you can have any amount of whitespace between
      return

      and the expression.

    • You can convert the
      if

      statement to a ternary expression.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted

Thanks, my code has been corrected!

 

Ah, and were you able to simplify this for me?

Thank you, but while your reply is probably well explained to most people, I can't help but have a little trouble understanding.

 

In short, your last bullet point confuses me. Would you mind explaining it in terms a less skilled modder would understand?

 

PPS - Sorry to be a pain in the ass

 

 

Use

blockState.getBaseState()

to get the base state, then chain

IBlockState#withProperty

calls to set each property's value before passing the result to

Block#setDefaultState

in the constructor to set the default state

GameSlayar

Forgive my noobiness!

Posted
public YourBlockClass() // Constructor of YourBlockClass
{
super(Material.rock);
setDefaultState(blockState.getBaseState().withProperty(SOME_PROPERTY, someDefaultValue).withProperty(OTHER_PROPERTY, otherDefaultValue));
}

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted

Last request. Promise.

I'm now stuck on the

World#setBlockState

bit, simply because I don't know what to put for the

state

argument.

 worldIn.setBlockState(pos, /* I have no idea what goes here */);

 

Should I have named the states in

#getStateFromMeta

?

Could you check through, maybe give me a hint as to what I'm doing wrong?

 

@Override
public IBlockState getStateFromMeta(int meta) {
    return getDefaultState().withProperty(LIT, meta == 0 ? false : true);
}

 

 

EDIT:

Is this okay?

worldIn.setBlockState(pos, getStateFromMeta(0));

 

 

DOUBLE EDIT:

Awesome, everything works - thanks!

GameSlayar

Forgive my noobiness!

Posted

Don't use metadata values yourself (the whole point of the blockstate system is to abstract away metadata), get the default state of a block (

Block#getDefaultState

) and then set each property to the desired value (chain

IBlockState#withProperty

calls).

 

Your

Block#getStateFromMeta

implementation can be simplified: comparison operators like

==

already return

boolean

values, you don't need to use a ternary expression here. Consider using the

!=

(not equal),

>

(greater than) or

!

(not) operators here.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Guest
This topic is now closed to further replies.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • It is 1.12.2 - I have no idea if there is a 1.12 pack
    • Okay, but does the modpack works with 1.12 or just with 1.12.2, because I need the Forge client specifically for Minecraft 1.12, not 1.12.2
    • Version 1.19 - Forge 41.0.63 I want to create a wolf entity that I can ride, so far it seems to be working, but the problem is that when I get on the wolf, I can’t control it. I then discovered that the issue is that the server doesn’t detect that I’m riding the wolf, so I’m struggling with synchronization. However, it seems to not be working properly. As I understand it, the server receives the packet but doesn’t register it correctly. I’m a bit new to Java, and I’ll try to provide all the relevant code and prints *The comments and prints are translated by chatgpt since they were originally in Spanish* Thank you very much in advance No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. MountableWolfEntity package com.vals.valscraft.entity; import com.vals.valscraft.network.MountSyncPacket; import com.vals.valscraft.network.NetworkHandler; import net.minecraft.client.Minecraft; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.Entity; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.network.PacketDistributor; public class MountableWolfEntity extends Wolf { private boolean hasSaddle; private static final EntityDataAccessor<Byte> DATA_ID_FLAGS = SynchedEntityData.defineId(MountableWolfEntity.class, EntityDataSerializers.BYTE); public MountableWolfEntity(EntityType<? extends Wolf> type, Level level) { super(type, level); this.hasSaddle = false; } @Override protected void defineSynchedData() { super.defineSynchedData(); this.entityData.define(DATA_ID_FLAGS, (byte)0); } public static AttributeSupplier.Builder createAttributes() { return Wolf.createAttributes() .add(Attributes.MAX_HEALTH, 20.0) .add(Attributes.MOVEMENT_SPEED, 0.3); } @Override public InteractionResult mobInteract(Player player, InteractionHand hand) { ItemStack itemstack = player.getItemInHand(hand); if (itemstack.getItem() == Items.SADDLE && !this.hasSaddle()) { if (!player.isCreative()) { itemstack.shrink(1); } this.setSaddle(true); return InteractionResult.SUCCESS; } else if (!level.isClientSide && this.hasSaddle()) { player.startRiding(this); MountSyncPacket packet = new MountSyncPacket(true); // 'true' means the player is mounted NetworkHandler.CHANNEL.sendToServer(packet); // Ensure the server handles the packet return InteractionResult.SUCCESS; } return InteractionResult.PASS; } @Override public void travel(Vec3 travelVector) { if (this.isVehicle() && this.getControllingPassenger() instanceof Player) { System.out.println("The wolf has a passenger."); System.out.println("The passenger is a player."); Player player = (Player) this.getControllingPassenger(); // Ensure the player is the controller this.setYRot(player.getYRot()); this.yRotO = this.getYRot(); this.setXRot(player.getXRot() * 0.5F); this.setRot(this.getYRot(), this.getXRot()); this.yBodyRot = this.getYRot(); this.yHeadRot = this.yBodyRot; float forward = player.zza; float strafe = player.xxa; if (forward <= 0.0F) { forward *= 0.25F; } this.flyingSpeed = this.getSpeed() * 0.1F; this.setSpeed((float) this.getAttributeValue(Attributes.MOVEMENT_SPEED) * 1.5F); this.setDeltaMovement(new Vec3(strafe, travelVector.y, forward).scale(this.getSpeed())); this.calculateEntityAnimation(this, false); } else { // The wolf does not have a passenger or the passenger is not a player System.out.println("No player is mounted, or the passenger is not a player."); super.travel(travelVector); } } public boolean hasSaddle() { return this.hasSaddle; } public void setSaddle(boolean hasSaddle) { this.hasSaddle = hasSaddle; } @Override protected void dropEquipment() { super.dropEquipment(); if (this.hasSaddle()) { this.spawnAtLocation(Items.SADDLE); this.setSaddle(false); } } @SubscribeEvent public static void onServerTick(TickEvent.ServerTickEvent event) { if (event.phase == TickEvent.Phase.START) { MinecraftServer server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(); if (server != null) { for (ServerPlayer player : server.getPlayerList().getPlayers()) { if (player.isPassenger() && player.getVehicle() instanceof MountableWolfEntity) { MountableWolfEntity wolf = (MountableWolfEntity) player.getVehicle(); System.out.println("Tick: " + player.getName().getString() + " is correctly mounted on " + wolf); } } } } } private boolean lastMountedState = false; @Override public void tick() { super.tick(); if (!this.level.isClientSide) { // Only on the server boolean isMounted = this.isVehicle() && this.getControllingPassenger() instanceof Player; // Only print if the state changed if (isMounted != lastMountedState) { if (isMounted) { Player player = (Player) this.getControllingPassenger(); // Verify the passenger is a player System.out.println("Server: Player " + player.getName().getString() + " is now mounted."); } else { System.out.println("Server: The wolf no longer has a passenger."); } lastMountedState = isMounted; } } } @Override public void addPassenger(Entity passenger) { super.addPassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(true)); } } } @Override public void removePassenger(Entity passenger) { super.removePassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is no longer mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(false)); } } } @Override public boolean isControlledByLocalInstance() { Entity entity = this.getControllingPassenger(); return entity instanceof Player; } @Override public void positionRider(Entity passenger) { if (this.hasPassenger(passenger)) { double xOffset = Math.cos(Math.toRadians(this.getYRot() + 90)) * 0.4; double zOffset = Math.sin(Math.toRadians(this.getYRot() + 90)) * 0.4; passenger.setPos(this.getX() + xOffset, this.getY() + this.getPassengersRidingOffset() + passenger.getMyRidingOffset(), this.getZ() + zOffset); } } } MountSyncPacket package com.vals.valscraft.network; import com.vals.valscraft.entity.MountableWolfEntity; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class MountSyncPacket { private final boolean isMounted; public MountSyncPacket(boolean isMounted) { this.isMounted = isMounted; } public void encode(FriendlyByteBuf buffer) { buffer.writeBoolean(isMounted); } public static MountSyncPacket decode(FriendlyByteBuf buffer) { return new MountSyncPacket(buffer.readBoolean()); } public void handle(NetworkEvent.Context context) { context.enqueueWork(() -> { ServerPlayer player = context.getSender(); // Get the player from the context if (player != null) { // Verifies if the player has dismounted if (!isMounted) { Entity vehicle = player.getVehicle(); if (vehicle instanceof MountableWolfEntity wolf) { // Logic to remove the player as a passenger wolf.removePassenger(player); System.out.println("Server: Player " + player.getName().getString() + " is no longer mounted."); } } } }); context.setPacketHandled(true); // Marks the packet as handled } } networkHandler package com.vals.valscraft.network; import com.vals.valscraft.valscraft; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.simple.SimpleChannel; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class NetworkHandler { private static final String PROTOCOL_VERSION = "1"; public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( new ResourceLocation(valscraft.MODID, "main"), () -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals ); public static void init() { int packetId = 0; // Register the mount synchronization packet CHANNEL.registerMessage( packetId++, MountSyncPacket.class, MountSyncPacket::encode, MountSyncPacket::decode, (msg, context) -> msg.handle(context.get()) // Get the context with context.get() ); } }  
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

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