Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Featured Replies

Posted

Good afternoon. I'm doing a mod for role-playing game and I want to transfer to the server an object that contains in itself all the necessary information for the dice roll: the number of dice faces, the name of the characteristic, additional modifiers to throw etc. I serialized my object and made sure that the same byte array was passed between toByte and fromByte. From these bytes in fromByte, I need to recreate the DiceRoll object, but for some reason o.readObject () returns null.

RollPacketToServer.java + inner handler

package ru.rarescrap.network.packets;

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;
import io.netty.buffer.ByteBuf;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.ChatComponentText;

import net.minecraft.util.StatCollector;
import ru.rarescrap.rsstats.utils.DiceRoll;
import ru.rarescrap.rsstats.utils.RollModificator;
       
/**
 * Этот пакет отсылается сервера
 * @author RareScrap
 */
public class RollPacketToServer implements IMessage {
    private DiceRoll diceRollMessage;
    
    /**
     * Необходимый конструктор по умолчанию. Он необходим для того, чтобы на
     * стороне-обработчике создать объект и распаковать в него буффер. 
     */
    public RollPacketToServer() {}

    public RollPacketToServer(DiceRoll message) {
        System.out.print("const");
        this.diceRollMessage = message;
    }
    
    @Override
    public void fromBytes(ByteBuf buf) {
        byte[] bytes = buf.array();
        ByteArrayInputStream b = new ByteArrayInputStream(bytes);
        ObjectInputStream o = null;
        try {
            o = new ObjectInputStream(b);
            this.diceRollMessage = (DiceRoll) o.readObject();
        } catch (IOException ex) {
            Logger.getLogger(RollPacketToServer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(RollPacketToServer.class.getName()).log(Level.SEVERE, null, ex);
        }
        if (o != null)
            try {
                o.close();
        } catch (IOException ex) {
            Logger.getLogger(RollPacketToServer.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        
        // ГОВНО
        FileOutputStream out = null;
        try {
            out = new FileOutputStream("D:\\Users\\rares\\Downloads\\checkstyle1.txt");
            out.write(bytes);
           
        } catch (FileNotFoundException ex) {
            Logger.getLogger(RollPacketToServer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(RollPacketToServer.class.getName()).log(Level.SEVERE, null, ex);
        }
        if (out != null)
            try {
                out.close();
        } catch (IOException ex) {
            Logger.getLogger(RollPacketToServer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void toBytes(ByteBuf buf) {
        ByteArrayOutputStream b = new ByteArrayOutputStream();
        ObjectOutputStream o = null;
        try {
            o = new ObjectOutputStream(b);
            o.writeObject(diceRollMessage);
        } catch (IOException ex) {
             Logger.getLogger(RollPacketToServer.class.getName()).log(Level.SEVERE, null, ex);
        }
        if (o != null)
            try {
                o.close();
        } catch (IOException ex) {
            Logger.getLogger(RollPacketToServer.class.getName()).log(Level.SEVERE, null, ex);
        }
        //ByteBufUtils.writeUTF8String(buf, b.);
        buf.writeBytes(b.toByteArray());
               
        
        
        // ГОВНО
        FileOutputStream out = null;
        try {
            out = new FileOutputStream("D:\\Users\\rares\\Downloads\\checkstyle.txt");
            out.write(buf.array());
           
        } catch (FileNotFoundException ex) {
            Logger.getLogger(RollPacketToServer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(RollPacketToServer.class.getName()).log(Level.SEVERE, null, ex);
        }
        if (out != null)
            try {
                out.close();
        } catch (IOException ex) {
            Logger.getLogger(RollPacketToServer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * Этот внутренний класс обрабатывает пришедший пакет НА СТОРОНЕ СЕРВЕРА
     */
    public static class MessageHandler implements IMessageHandler<RollPacketToServer, IMessage> {
        // Do note that the default constructor is required, but implicitly defined in this case
        public MessageHandler() {}

        @Override
        public IMessage onMessage(RollPacketToServer message, MessageContext ctx) {
            // This is the player the packet was sent to the server from
            EntityPlayerMP serverPlayer = ctx.getServerHandler().playerEntity;
            
            System.out.print("onMessage");
            if (message.diceRollMessage == null)
                throw new NullPointerException("diceRollMessage is null");
            
            String result = message.diceRollMessage.roll();
            // и вывести его в чат
            serverPlayer.addChatComponentMessage(new ChatComponentText(result));
            
            
            /*
            String maxS = new String();
            String stat = new String();
            int i = 0;
            for (; amount.charAt(i) != '_'; i++) {
                maxS += amount.charAt(i);
            }
            i++;
            for (; i < amount.length(); i++) {
                stat += amount.charAt(i);
            }
            
            int min = 1;
            int max = Integer.parseInt(maxS);
            
            String result = StatCollector.translateToLocalFormatted("item.StatItem.rollChatMessage", stat) + ": ";
            int resultInt = 0;
            int randomNum = ThreadLocalRandom.current().nextInt(min, max + 1);
            resultInt += randomNum;
            while(randomNum == max) {
                result += String.valueOf(randomNum)+ "+";
                resultInt += randomNum;
                randomNum = ThreadLocalRandom.current().nextInt(min, max + 1);
                
            }
            result += String.valueOf(randomNum)+ "= " + resultInt+randomNum;
            resultInt += randomNum;
            
            
            // Заменить на нормальное вычисление
            serverPlayer.addChatComponentMessage(new ChatComponentText(result));
            */
            return null;
        }
    }

}


StatItem, which send a message by right click

@Override
    public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer entityplayer) {
        // If нужен, чтобы броить бросок только один раз
        if (world.isRemote) { // TODO: На какой стороне вычисляется бросок?
            //String num = String.valueOf( basicRolls[ Integer.parseInt(itemstack.getIconIndex().toString()) ].dice );
            String statName = StatCollector.translateToLocalFormatted( localePrefix + ".name");
            int lvl = itemstack.getItemDamage();
            
            // TODO ХЗ зачем
            //String str = itemstack.getIconIndex().getIconName();
            //str = str.replaceAll("[^\\d.]", "");
            
            basicRolls.get(lvl).setStatName(statName);
            
            RollPacketToServer rp = new RollPacketToServer(basicRolls.get(lvl));
            INSTANCE.sendToServer(rp); // "123" // itemstack.getIconIndex(
            entityplayer.addChatComponentMessage(new ChatComponentText(basicRolls.get(lvl).dice + " " + statName));
        }
        //entityplayer.addChatComponentMessage(new ChatComponentText(this.roll()));
        
        return itemstack;
        //return super.onItemRightClick(itemstack, world, entityplayer); //To change body of generated methods, choose Tools | Templates.
    }


I am registering a message in CommonProxy.java
 

public void preInit(FMLPreInitializationEvent e, ArrayList<DiceRoll> dices) {
        // Регистрация сообщения о пробросе статы
        INSTANCE.registerMessage(RollPacketToServer.MessageHandler.class, RollPacketToServer.class, 0, Side.SERVER);
        ...
    }


I compared the byte array in toBytes() and fromBytes(). As you can see, they are almost the same:
toBytes output()

59a2961d5db79_(48).png.e6a71928a364fd656c8c883b1674a378.png
 

fromBytes() output:
59a296404a104_(49).png.9587b63d1e12152b14a68cc0e80a2801.png


When I want to run my mod on the server, I get an exception:

Spoiler

17:23:02] [Server thread/ERROR] [FML]: There was a critical exception handling a packet on channel rsstats
java.lang.NullPointerException: diceRollMessage is null
    at ru.rarescrap.network.packets.RollPacketToServer$MessageHandler.onMessage(RollPacketToServer.java:138) ~[RollPacketToServer$MessageHandler.class:?]
    at ru.rarescrap.network.packets.RollPacketToServer$MessageHandler.onMessage(RollPacketToServer.java:127) ~[RollPacketToServer$MessageHandler.class:?]
    at cpw.mods.fml.common.network.simpleimpl.SimpleChannelHandlerWrapper.channelRead0(SimpleChannelHandlerWrapper.java:37) ~[SimpleChannelHandlerWrapper.class:?]
    at cpw.mods.fml.common.network.simpleimpl.SimpleChannelHandlerWrapper.channelRead0(SimpleChannelHandlerWrapper.java:17) ~[SimpleChannelHandlerWrapper.class:?]
    at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:98) ~[SimpleChannelInboundHandler.class:?]
    at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) ~[DefaultChannelHandlerContext.class:?]
    at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) ~[DefaultChannelHandlerContext.class:?]
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) ~[MessageToMessageDecoder.class:?]
    at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?]
    at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) ~[DefaultChannelHandlerContext.class:?]
    at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) ~[DefaultChannelHandlerContext.class:?]
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) ~[DefaultChannelPipeline.class:?]
    at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) ~[EmbeddedChannel.class:?]
    at cpw.mods.fml.common.network.internal.FMLProxyPacket.func_148833_a(FMLProxyPacket.java:77) [FMLProxyPacket.class:?]
    at net.minecraft.network.NetworkManager.func_74428_b(NetworkManager.java:212) [ej.class:?]
    at net.minecraft.network.NetworkSystem.func_151269_c(NetworkSystem.java:165) [nc.class:?]
    at net.minecraft.server.MinecraftServer.func_71190_q(MinecraftServer.java:659) [MinecraftServer.class:?]
    at net.minecraft.server.dedicated.DedicatedServer.func_71190_q(DedicatedServer.java:334) [lt.class:?]
    at net.minecraft.server.MinecraftServer.func_71217_p(MinecraftServer.java:547) [MinecraftServer.class:?]
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:427) [MinecraftServer.class:?]
    at net.minecraft.server.MinecraftServer$2.run(MinecraftServer.java:685) [li.class:?]
[17:23:02] [Server thread/INFO] [net.minecraft.network.NetHandlerPlayServer]: RareScrap lost connection: TextComponent{text='A fatal error has occured, this connection is terminated', siblings=[], style=Style{hasParent=false, color=null, bold=null, italic=null, underlined=null, obfuscated=null, clickEvent=null, hoverEvent=null}}
[17:23:02] [Server thread/INFO] [net.minecraft.server.MinecraftServer]: RareScrap left the game

 

 

What am I doing wrong? Why can not I re-create a file in fromBytes?

 

Valuable advice and recommendations are welcome
All files is avalable in my Githab: https://github.com/RareScrap/RSMod---RSBase/tree/RSStats_clickActions/RSStats

 

1) 1.7.10 is not supported on this forum. Update

2) The client lies - do all your logic and storage of data on the server

Did you really need to know?

  • Guest locked this topic
Guest
This topic is now closed to further replies.

Important Information

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

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.