Jump to content

Recommended Posts

Posted

Hey guys,

 

So I have been working on a small mod for the past week or so. Now I have some problems that I can't seem to fix myself.

My first problem is, that I can't place torches on my custom walls, I have tried to use canPlaceTorchOnTop(), but that didn't work at all.

 

Here's my custom walls class.

public class BlockWall2 extends BlockWall
{

public BlockWall2(Block block)
{
	super(block);
	this.setResistance(10.0F);
	this.setHardness(1.5F);
}

public int damageDropped(int meta)
{
	return meta;
}

public boolean canConnectTo(IBlockAccess worldIn, BlockPos pos)
    {
        Block block = worldIn.getBlockState(pos).getBlock();
        return block == Blocks.barrier ? false : (((block != this && !(block instanceof BlockFenceGate) && !(block instanceof BlockWall2) && !(block instanceof BlockWall))) ? (block.getMaterial().isOpaque() && block.isFullCube() ? block.getMaterial() != Material.gourd : false) : true);
    }
}

 

My second problem is that for every new custom wall I make there's two blocks in the creativeTab, there should just be one. Minor thing but I want to fix it...

 

My last problem is, that vanilla walls don't want to connect to my custom walls, but my custom walls want to connect to vanilla walls. I want them to connect. I have no idea how to make that happen, so if anyone could give me some advice I would apriciate it.

Posted

1) Return true from canPlaceTorchOnTop. Use the @Override annotation to guarantee that you're really overriding it.

 

2) You're not showing enough code to say why you appear twice in menu. Where's registration etc?

 

3) I don't think you can fix the vanilla walls willingness to connect. What I ended up doing was recreating cobble and mossy cobble walls in my own mod. Player who want connections must avoid vanilla walls.

 

4) My own walls mod stopped extending BlockWalls when I ported to mc 1.8 and its blockstates. Now that I know a little more about blockstates, I might be able to extend BlockWalls again without encountering the issues that fazed me last year. Then at least your walls could connect to mine and vice versa.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Posted

1) Return true from . Use the @Override annotation to guarantee that you're really overriding it.

 

2) You're not showing enough code to say why you appear twice in menu. Where's registration etc?

 

3) I don't think you can fix the vanilla walls willingness to connect. What I ended up doing was recreating cobble and mossy cobble walls in my own mod. Player who want connections must avoid vanilla walls.

 

4) My own walls mod stopped extending BlockWalls when I ported to MC 1.8 and its blockstates. Now that I know a little more about blockstates, I might be able to extend BlockWalls again without encountering the issues that fazed me last year. Then at least your walls could connect to mine and vice verse.

 

1) I have tried that, sadly it didn't work.

 

2) I believe that they appear twice because I extend BlockWall. BlockWall is working in subBlocks, and have two variants, and that is why. At least that's my theory. I just don't know how to remove the subBlock from the code.

 

3) That's a bummer, I was hoping that I could add some piece of code somewhere, so they could connect. Oh well guess I can't have everything :)

 

4) I have had no real problem extending BlockWall in 1.8 and using Forge's Blockstates, makes it pretty easy to make the blockstates for custom walls.

 

Link for Forge's Blockstates.

http://mcforge.readthedocs.org/en/latest/blockstates/forgeBlockstates/

Posted

1) I have tried that, sadly it didn't work.

 

What do you mean it "didn't work"?

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

1) I have tried that, sadly it didn't work.

 

What do you mean it "didn't work"?

What I mean is that I still can't place a torch on my custom wall.

Posted

Time to set some break points and step through the torch placement in the debugger (trying again to return true from  canPlaceTorchOnTop).

 

I am revisiting my own walls mod to see if I can coax it back into being an extension of BlockWalls. Maybe I'll run into a gotcha and remember exactly what made me extend from class Block.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Posted

Time to set some break points and step through the torch placement in the debugger (trying again to return true from  canPlaceTorchOnTop).

 

I am revisiting my own walls mod to see if I can coax it back into being an extension of BlockWalls. Maybe I'll run into a gotcha and remember exactly what made me extend from class Block.

Yeah, I just suck at debugging, oh well only one way to get better

Posted

After doing some tinkering, I got the torch thing to work, after adding this piece of code to my custom wall class

public boolean isSideSolid(IBlockAccess world, BlockPos pos, EnumFacing side)
{
	IBlockState state = this.getActualState(world.getBlockState(pos), world, pos);

        if (this instanceof BlockWall2 && side == EnumFacing.UP)
        {
            return true;
        }
	return false;
}

public boolean canPlaceTorchOnTop()
{
	return true;
}

Posted

I was going to take a guess at isSideSolid, earlier, but I would have thought that BlockWall did that already.

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

I was going to take a guess at isSideSolid, earlier, but I would have thought that BlockWall did that already.

Yeah, I thought so too. But I managed to figure it out :)

Posted

I'm on a roll today :D

 

After some more tinkering I was able to remove the unneeded extra blocks, from the CreativeTab, I used this code to fix the problem

@SideOnly(Side.CLIENT)
    public void getSubBlocks(Item itemIn, CreativeTabs tab, List<ItemStack> list)
    {
        for (int i = 0 ; i < 1 ; i ++)
        {
        	if (i == 0)
        	{
            	list.add(new ItemStack(itemIn, 1, i));
        	}
        	else
        	{
        		list.remove(new ItemStack(itemIn, 1, i));
        	}
        }
    }

 

It's probably not the best way to do it, but it works.

 

And that leaves me with the last problem with the connecting to vanilla walls failure, I'll leave this one open if someone knows of a way to get it working, otherwise this post is solved. Thanks for the help guys, I really appreciate it :)

Posted

 for (int i = 0 ; i < 1 ; i ++)

 

That can be simplified.  E.g. by removing it entirely, because you're only going to get 1 item stack from that loop, so why bother with a loop?

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

That can be simplified.  E.g. by removing it entirely, because you're only going to get 1 item stack from that loop, so why bother with a loop?

You are absolutly right all I really need is this.

@SideOnly(Side.CLIENT)
    public void getSubBlocks(Item itemIn, CreativeTabs tab, List<ItemStack> list)
    {
          list.add(new ItemStack(itemIn, 1, 0));
    }

 

To be fair I wasn't sure if that would work, when BlockWall has two in its getSubBlocks, so I just figured that I had to add one, and still remove the other one, but that isn't the case. Thanks mate :)

Posted

Walls do not have "solid" sides because they don't occupy whole blocks (and therefore you can't put torches on the sides of wall blocks).

 

I wonder if the trouble with torch-on-top is peculiar to 1.8.9... or maybe it's something about extending BlockWall in 1.8+ (which might be why I changed my design when porting from 1.7.10). I'll be looking at that today.

 

PS: Add an @Override annotation to your getSubBlocks method so you'll always be sure that you're really overriding the vanilla one. This annotation becomes especially valuable when porting to a new MC release in which some methods change their parameter lists, breaking override matchups. When that happens, your annotated methods all get flagged for immediate fixing. Non-annotated methods simply sit there not being called anymore and it might take you much hair-pulling to figure that out. Long story short: Always annotate every override.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Posted

Walls do not have "solid" sides because they don't occupy whole blocks (and therefore you can't put torches on the sides of wall blocks).

 

I wonder if the trouble with torch-on-top is peculiar to 1.8.9... or maybe it's something about extending BlockWall in 1.8+ (which might be why I changed my design when porting from 1.7.10). I'll be looking at that today.

 

PS: Add an @Override annotation to your getSubBlocks method so you'll always be sure that you're really overriding the vanilla one. This annotation becomes especially valuable when porting to a new MC release in which some methods change their parameter lists, breaking override matchups. When that happens, your annotated methods all get flagged for immediate fixing. Non-annotated methods simply sit there not being called anymore and it might take you much hair-pulling to figure that out. Long story short: Always annotate every override.

 

I think the problem came with forge 1.8 or 1.8.9 as I remember it working fine in 1.7.10.

 

Most of the time when I use the @Override annotation, my eclipse tells me to remove it again, I don't really know why. But does it have any impact to use it anyway, and ignore eclipse in this case? Because if it has no impact and will work fine with the annotations being there, I will definitely add them :D

 

Also I might have found a way to get vanilla walls to connect to my custom walls by using IExtendedEntityProperties, I just need to learn a bit more about how to use it, but I'll have to wait till tomorrow to do so.

Posted

Sometimes Eclipse will complain about a brand new @Override because its cache is dirty. Do the "clean" action from the project menu. If it still complains, then (like D7 said), you probably have some disagreement between your method and what it's supposed to override.

 

BTW, sometimes that disagreement is that the super method is private or final. In those cases, stronger measures (e.g. reflection) are required, and some just aren't worth the effort (unless you get an emotional payoff simply from overcoming such obstacles  :D)

 

Incidentally, I was able to revise my own wall class in MC 1.8 (Forge 1450) as an extension of BlockWall (and will port such to 1.9). It was not straightforward. To handle my metadata subtypes as well as connection geometry with a minimum of JSON fuss, I had replaced vanilla's many boolean connection properties with my own integer geometry property. This created havoc inside the mandatory super constructor where none of the vanilla properties existed. I hacked my way around that obstacle in a brute-force manner that I won't describe here because it might nauseate some readers.

 

Long story short: My next Anystone Walls revision should connect to other mods' walls that are extensions of BlockWall and programmed to likewise connect with instances of BlockWall. I encourage all modders to eschew vanilla's "block == " tests and instead use "instanceof <vanilla parent class>" in order to play nice with other mods that add blocks like yours (unless you have a special reason to be exclusive).

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Posted

Just coming with a small update on the 'problem' with vanilla wall blocks not connecting to my custom walls. I have made a fix, that was almost to simple to be true. I added this piece of code to my custom wall class. And it's working. However I'm not sure if this have any impact on the wall aspect of my blocks, but so far I have seen no issues.

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

 

Maybe someone will correct me if this is bad or the wrong way to do this. I do know that the vanilla BlockWall class has isFullCube() return false. But all I know is that everything seems to be working fine. I still have to do some more testing to see if returning isFullCube() true, gives any problems, but so far there's been none.

Posted

Never mind. I have already seen a lot of problems with doing so. Stuff like fences now also want to connect, a bit of a brain fart to think that there wouldn't be problems when doing so. Guess it's been a long day, and maybe I should just go to bed :D

Posted

Being a "full cube" might also do things to lighting and graphics occlusion. It's better to just add your own versions of cobble and mossy cobble to your list of variants.

 

BTW, Set yourself up to do more than one set of walls (separate your walls into an abstract class and a child set of walls). Then you can add another 16 compatible wall types by writing another extension of the abstract class. Mine is up to 2 sets (32 walls), and I have contemplated a 3rd set. Mine even have variable hardness, blast resistance etc, and a few give off light. My glowstone and sea-lantern walls are quite useful.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Posted

Being a "full cube" might also do things to lighting and graphics occlusion. It's better to just add your own versions of cobble and mossy cobble to your list of variants.

I guess I have to, I'm just not very happy to 'remove' vanilla stuff just to add in the same thing. I'm thinking more as a compatibility factor with other mods that might use cobble or mossy cobble in crafting. Personally I haven't found a mod that does this yet, but you never know.

 

BTW, Set yourself up to do more than one set of walls (separate your walls into an abstract class and a child set of walls). Then you can add another 16 compatible wall types by writing another extension of the abstract class. Mine is up to 2 sets (32 walls), and I have contemplated a 3rd set. Mine even have variable hardness, blast resistance etc, and a few give off light. My glowstone and sea-lantern walls are quite useful.

I don't think it will be necessary, as I'm only going to add about 10 new walls :)

Posted

I've heard of cobble and mossy cobble blocks being used in crafting, but not their walls.

 

I distinguished my walls recipes by taking 7 input blocks to produce 7 walls (add top-center to the vanilla wall recipe). That lets me use the same materials that would otherwise make vanilla stuff (like those cobbles, and window panes, and nether-brick fences). I can now contemplate a full set of wooden walls that won't be confused with fences either.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

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

    • 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() ); } }  
    • Do you use features of inventory profiles next (ipnext) or is there a change without it?
  • Topics

×
×
  • Create New...

Important Information

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