I'm making a jetpack, and am using the durability as the fuel amount. The fuel system works fine, just when I use up fuel (lower durability), and then take the armor off, the durability returns to the value it was before I put it on. I really need to fix this; any help will be appreciated!
That's because you are changing the damage on the client, which has no effect except 'visually' - the armor stack's real damage value is on the server, which is the only place you should ever change it. The client will be updated automatically when the server stack takes damage.
Incidentally, since you want to use a key press, you will have to send packets.
I suggest looking here. It tells you how to setup a PacketHandler, etc. If you want an example, let me know!
Dude, that tutorial is from 1.6.4. and earlier.
Diesieben07 has a decent and up-to-date tutorial, and I have a slightly more complex implementation that I detail here. Or you could check out my latest implementation that was inspired by Vic.
The code that would work in my situation. I understand the concepts behind it, but can't seem to make it work correctly.
Okay, so what did you try?
Did you make a new channel with the SimpleNetworkWrapper for your mod?
Did you make a class implementing IMessage?
Did you make an IMessageHandler for your message class?
Did you register your message and handler to the appropriate Side (SERVER, in your case)?
Did you then send the message from your KeyInputEvent to the server?
There is a lot of code involved, but none of it is especially complicated. Show us what you've tried and we can help you fix what is wrong.
Simply put, my package handler class is full if errors. The Handler class claims to have illegal modifiers (public and static), and the fromBytes and toBytes want to have the @Override annotation removed.
public PacketMessage(String text) {
this.text = text;
public static class Handler implements IMessageHandler<PacketMessage, IMessage>{
@Override
public IMessage onMessage(PacketMessage message, MessageContext ctx) {
System.out.println(String.format("Received %s from %s", message.text, ctx.getServerHandler().playerEntity.getDisplayName()));
return null; // no response in this case
}
@Override
public void fromBytes(ByteBuf buf) {
// TODO Auto-generated method stub
text = ByteBufUtils.readUTF8String(buf); // this class is very useful in general for writing more complex objects
}
@Override
public void toBytes(ByteBuf buf) {
// TODO Auto-generated method stub
ByteBufUtils.writeUTF8String(buf, text);
}
That's because you put the Handler class inside of the message class constructor, along with everything else...
public PacketMessage(String text) {
this.text = text;
// uh oh, you forgot a closing brace here to end the constructor!
// add '}'
} // <== there
// now put the rest of your code out here
Glad you've come back to the topic of packet handling. Have you been able to resolve some of your earlier frustrations with the network handling ?-- you had some valid points of complaint before. But I liked your desire to make it easy and generic.
I've found diesieben07's implementation is sufficient for my needs. But would be interested to see advantages of what you've been developing.
Glad you've come back to the topic of packet handling. Have you been able to resolve some of your earlier frustrations with the network handling ?-- you had some valid points of complaint before. But I liked your desire to make it easy and generic.
I've found diesieben07's implementation is sufficient for my needs. But would be interested to see advantages of what you've been developing.
The basic implementation is indeed sufficient, but it's fun to tweak xD If you follow that link, you will see what mine has turned into now - it's sort of a melding together of my previous changes with the implementation Vic explained in another thread, plus a few extra tweaks.
Fixed that. Now PacketHandler in public class line says must inherit abstract method fromBytes, and fromBytes and toBytes still want to remove the @Override
Wait: never mind. Forgot to put the fromBytes and toBytes in the class function.
EDIT: Now how do I add it in my jetpack class to send the packet?
Fixed that. Now PacketHandler in public class line says must inherit abstract method fromBytes, and fromBytes and toBytes still want to remove the @Override
Wait: never mind. Forgot to put the fromBytes and toBytes in the class function.
EDIT: Now how do I add it in my jetpack class to send the packet?
You will need to do key bindings. Subscribe to this event: InputEvent.KeyPressEvent - but make sure that you are ONLY doing it client side (use a proxy). Here is an example of what you must do.
@SubscribeEvent
public void onKeyPress(Inputevent.KeyPressEvent) {
if (theSpaceIsPressed) {
Mod.network.sendToServer(new MyPacketToUseJetpack());
}
}
You don't actually send the packet in the jetpack class at all; instead you use an event handler.
All of the effects that take place when you press space (e.g. make the player go upwards due to jetpack propulsion) should be handled in your packet handler.
KeyInputEvent is a Forge Event - you can technically put it almost anywhere, but typically people make a KeyHandler class which includes all of their custom KeyBindings and subscribes to the KeyInputEvent (i.e. handles the key input).
Since key input is all done on the CLIENT side, you should only register this specific event handler from your ClientProxy, and note that it is on the FML event bus.
public PacketMessage(String text) {
this.text = text;
}
@Override
public void fromBytes(ByteBuf buf) {
text = ByteBufUtils.readUTF8String(buf); // this class is very useful in general for writing more complex objects
}
@Override
public void toBytes(ByteBuf buf) {
ByteBufUtils.writeUTF8String(buf, text);
}
public static class Handler implements IMessageHandler<PacketMessage, IMessage>{
@Override
public IMessage onMessage(PacketMessage message, MessageContext ctx) {
System.out.println(String.format("Received %s from %s", message.text, ctx.getServerHandler().playerEntity.getDisplayName()));
return null; // no response in this case
}
}
}
public PacketMessage(String text) {
this.text = text;
}
@Override
public void fromBytes(ByteBuf buf) {
text = ByteBufUtils.readUTF8String(buf); // this class is very useful in general for writing more complex objects
}
@Override
public void toBytes(ByteBuf buf) {
ByteBufUtils.writeUTF8String(buf, text);
}
public static class Handler implements IMessageHandler<PacketMessage, IMessage>{
@Override
public IMessage onMessage(PacketMessage message, MessageContext ctx) {
System.out.println(String.format("Received %s from %s", message.text, ctx.getServerHandler().playerEntity.getDisplayName()));
return null; // no response in this case
}
}
}
You still didn't remove the keybind thingy from your jetpack - I recommend removing it now that you use packets to activate the jetpack instead.
Do you know how to program? "I think I'm not actually telling the packet to do anything: I'm not sure." does not seem like you really know what you're doing
Unless you don't know what to put inside your message handler. There it is simple. Just make the player get boosted upwards.
Jetpack File:
package com.webs.geckistudios.muffinmod;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemArmor.ArmorMaterial;
import net.minecraft.world.World;
public class ItemMuffinJetpack extends ItemArmor {
public ItemMuffinJetpack(ArmorMaterial armourMaterial, int renderIndex,
int armourType) {
super(armourMaterial, renderIndex, armourType);
this.maxStackSize = 1;
}
@Override
public String getArmorTexture(ItemStack stack, Entity entity, int slot, String type){
return "mm:textures/models/armor/jetpackArmor.png";
}
@Override
public void onArmorTick(World world, EntityPlayer player, ItemStack itemStack) {
player.fallDistance = 0;
if (world.isRemote && Minecraft.getMinecraft().gameSettings.isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindJump)) {
{
if (itemStack.getItemDamage() < 239) {
player.addVelocity(0, 0.13, 0);
itemStack.damageItem(1, player);
for (int i = 0; i < 8; ++i)
{
MuffinMod.proxy.spawnParticle(player.worldObj, player.posX, player.posY - 1, player.posZ, "muffinpoof");
}
}
}
}
}
}
Incidentally, since you want to use a key press, you will have to send packets.
Hello!
Dude, that tutorial is from 1.6.4. and earlier.
Diesieben07 has a decent and up-to-date tutorial, and I have a slightly more complex implementation that I detail here. Or you could check out my latest implementation that was inspired by Vic.
Hello!
The last link IS an example, unless by 'example' you mean exact code that will work in your situation.
Okay, so what did you try?
Did you make a new channel with the SimpleNetworkWrapper for your mod?
Did you make a class implementing IMessage?
Did you make an IMessageHandler for your message class?
Did you register your message and handler to the appropriate Side (SERVER, in your case)?
Did you then send the message from your KeyInputEvent to the server?
There is a lot of code involved, but none of it is especially complicated. Show us what you've tried and we can help you fix what is wrong.
package com.webs.geckistudios.muffinmod;
import io.netty.buffer.ByteBuf;
import cpw.mods.fml.common.network.ByteBufUtils;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
public class PacketMessage implements IMessage{
private String text;
public PacketMessage() { }
public PacketMessage(String text) {
this.text = text;
public static class Handler implements IMessageHandler<PacketMessage, IMessage>{
@Override
public IMessage onMessage(PacketMessage message, MessageContext ctx) {
System.out.println(String.format("Received %s from %s", message.text, ctx.getServerHandler().playerEntity.getDisplayName()));
return null; // no response in this case
}
@Override
public void fromBytes(ByteBuf buf) {
// TODO Auto-generated method stub
text = ByteBufUtils.readUTF8String(buf); // this class is very useful in general for writing more complex objects
}
@Override
public void toBytes(ByteBuf buf) {
// TODO Auto-generated method stub
ByteBufUtils.writeUTF8String(buf, text);
}
}
}
}
Glad you've come back to the topic of packet handling. Have you been able to resolve some of your earlier frustrations with the network handling ?-- you had some valid points of complaint before. But I liked your desire to make it easy and generic.
I've found diesieben07's implementation is sufficient for my needs. But would be interested to see advantages of what you've been developing.
The basic implementation is indeed sufficient, but it's fun to tweak xD If you follow that link, you will see what mine has turned into now - it's sort of a melding together of my previous changes with the implementation Vic explained in another thread, plus a few extra tweaks.
Wait: never mind. Forgot to put the fromBytes and toBytes in the class function.
EDIT: Now how do I add it in my jetpack class to send the packet?
You will need to do key bindings. Subscribe to this event: InputEvent.KeyPressEvent - but make sure that you are ONLY doing it client side (use a proxy). Here is an example of what you must do.
You don't actually send the packet in the jetpack class at all; instead you use an event handler.
All of the effects that take place when you press space (e.g. make the player go upwards due to jetpack propulsion) should be handled in your packet handler.
ClothingCraft - Highly customizable and realistic clothing! No more silly leather armor!
Since key input is all done on the CLIENT side, you should only register this specific event handler from your ClientProxy, and note that it is on the FML event bus.
PacketMessage.java
package com.webs.geckistudios.muffinmod;
import io.netty.buffer.ByteBuf;
import cpw.mods.fml.common.network.ByteBufUtils;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
public class PacketMessage implements IMessage{
private String text;
public PacketMessage() { }
public PacketMessage(String text) {
this.text = text;
}
@Override
public void fromBytes(ByteBuf buf) {
text = ByteBufUtils.readUTF8String(buf); // this class is very useful in general for writing more complex objects
}
@Override
public void toBytes(ByteBuf buf) {
ByteBufUtils.writeUTF8String(buf, text);
}
public static class Handler implements IMessageHandler<PacketMessage, IMessage>{
@Override
public IMessage onMessage(PacketMessage message, MessageContext ctx) {
System.out.println(String.format("Received %s from %s", message.text, ctx.getServerHandler().playerEntity.getDisplayName()));
return null; // no response in this case
}
}
}
ItemMuffinJetpack.java
package com.webs.geckistudios.muffinmod;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemArmor.ArmorMaterial;
import net.minecraft.world.World;
public class ItemMuffinJetpack extends ItemArmor {
public ItemMuffinJetpack(ArmorMaterial armourMaterial, int renderIndex,
int armourType) {
super(armourMaterial, renderIndex, armourType);
this.maxStackSize = 1;
}
@Override
public String getArmorTexture(ItemStack stack, Entity entity, int slot, String type){
return "mm:textures/models/armor/jetpackArmor.png";
}
@Override
public void onArmorTick(World world, EntityPlayer player, ItemStack itemStack) {
player.fallDistance = 0;
if (world.isRemote && Minecraft.getMinecraft().gameSettings.isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindJump)) {
{
if (itemStack.getItemDamage() < 239) {
player.addVelocity(0, 0.13, 0);
itemStack.damageItem(1, player);
for (int i = 0; i < 8; ++i)
{
MuffinMod.proxy.spawnParticle(player.worldObj, player.posX, player.posY - 1, player.posZ, "muffinpoof");
}
//MuffinMod.Network.sendToServer(message);
}
}
}
}
}
ClientProxy.java
package com.webs.geckistudios.muffinmod;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.InputEvent.KeyInputEvent;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.EntityBreakingFX;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.init.Items;
import net.minecraft.world.World;
public class ClientProxy extends CommonProxy
{
@SubscribeEvent
public void onKeyPress(KeyInputEvent event) {
if (Minecraft.getMinecraft().gameSettings.isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindJump)) {
MuffinMod.Network.sendToServer(new PacketMessage());
}
}
@Override
public void spawnParticle(World world, double posX, double posY, double posZ, String type)
{
Minecraft minecraft = Minecraft.getMinecraft();
if (minecraft != null && minecraft.renderViewEntity != null && minecraft.effectRenderer != null)
{
int particleSetting = minecraft.gameSettings.particleSetting;
if (particleSetting == 1 && world.rand.nextInt(3) == 0)
{
particleSetting = 2;
}
double entityX = minecraft.renderViewEntity.posX - posX;
double entityY = minecraft.renderViewEntity.posY - posY;
double entityZ = minecraft.renderViewEntity.posZ - posZ;
if (entityX * entityX + entityY * entityY + entityZ * entityZ > 16.0D * 16.0D)
{
return;
}
else if (particleSetting > 1)
{
return;
}
else
{
EntityFX particle = null;
if (type.equals("muffinpoof"))
{
particle = new EntityBreakingFX(world, posX, posY, posZ, MuffinMod.itemMuffinChocolateChip);
}
else if (type.equals("rainbowmuffinpoof"))
{
particle = new EntityBreakingFX(world, posX, posY, posZ, MuffinMod.itemMuffinRainbow);
}
if (particle != null)
{
minecraft.effectRenderer.addEffect(particle);
}
}
}
}
}
You still didn't remove the keybind thingy from your jetpack - I recommend removing it now that you use packets to activate the jetpack instead.
Do you know how to program? "I think I'm not actually telling the packet to do anything: I'm not sure." does not seem like you really know what you're doing
Unless you don't know what to put inside your message handler. There it is simple. Just make the player get boosted upwards.
ClothingCraft - Highly customizable and realistic clothing! No more silly leather armor!