Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

Serializable: how to pass object to IMessage?


RareScrap
 Share

Recommended Posts

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

 

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
 Share



  • Recently Browsing

    No registered users viewing this page.

  • Posts

    • Basically, my attributes for my TankEntity are not going through. I'm DIRECTLY porting from 1.17, and it worked fine on 1.17 and 16, so I'm pretty confused here. The Entity extends Pig and within it, this is for creating the attributes. public static AttributeSupplier.Builder createAttributes() { return Pig.createLivingAttributes() .add(Attributes.MAX_HEALTH, 90.0D) .add(Attributes.MOVEMENT_SPEED, 0.14f) .add(Attributes.KNOCKBACK_RESISTANCE, 10.0D) .add(Attributes.FOLLOW_RANGE, 0.0D); } Then, in my EntityTypes Registry, I add the attributes.  @Mod.EventBusSubscriber(modid = TankMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) public class TankModEntityTypes { ..... @SubscribeEvent public static void entityAttributesInit(EntityAttributeCreationEvent event) { event.put(TANK_ENTITY_TYPE.get(), TankEntity.createAttributes().build()); } I just don't understand why its not working. This worked fine , before. The Entity spawns, but it weirdly just floats in the air, and when hit it goes red and doesn't stop being red. When the player rides it, its health also doesn't go down. Really strange stuff.  I looked at some other mods which have entity attributes, and it works fine in them. If there's anything else I need to show let me know.
    • Catch up with the last topic with rendering, this is something that I took a while to learn from nothing to this stage. (I only shoot from right side) public static List<Pair<BlockRayTraceResult, Float>> rayTraceAndPenetrateBlocks4(World world, List<Vector3d> vecs, float health, Function<BlockState, Float> getHealthReduction) { List<Pair<BlockRayTraceResult, Float>> results = new ArrayList<>(); if (vecs.isEmpty()) return results; Vector3d startVec = vecs.get(0); for (int i=0;i<vecs.size()-1;i++) { Vector3d vec = vecs.get(i); Vector3d next = vecs.get(i + 1); BlockPos pos = new BlockPos(vec); BlockPos pos2 = new BlockPos(next); BlockState blockstate = world.getBlockState(pos); BlockState blockstate2 = world.getBlockState(pos2); if (blockstate.getBlock() instanceof BarrierBlock && blockstate2.getBlock() instanceof BarrierBlock) continue; VoxelShape blockShape = blockstate.getCollisionShape(world, pos, ISelectionContext.dummy()); VoxelShape blockShape2 = blockstate2.getCollisionShape(world, pos2, ISelectionContext.dummy()); BlockRayTraceResult blockResult; boolean empty = blockShape.isEmpty() || blockShape.toBoundingBoxList().stream().noneMatch((bb) -> bb.offset(pos).contains(vec)); boolean empty2 = blockShape2.isEmpty() || blockShape2.toBoundingBoxList().stream().noneMatch((bb) -> bb.offset(pos2).contains(next)); if ((isRayTraceIgnorableBlock(blockstate, blockShape) && isRayTraceIgnorableBlock(blockstate2, blockShape2))) continue; if (empty && !empty2) blockResult = world.rayTraceBlocks(vec, next, pos2, blockShape2, blockstate2); else if (!empty && empty2) blockResult = world.rayTraceBlocks(next, vec, pos, blockShape, blockstate); else blockResult = world.rayTraceBlocks(vec, next, pos, blockShape, blockstate); if (blockResult != null) { health -= getHealthReduction.apply(blockstate); results.add(new Pair<>(blockResult, (float) startVec.distanceTo(blockResult.getHitVec()))); if (health <= 0) break; } } return results; } public static List<Vector3d> getAllVectors2(Vector3d startVec, Vector3d endVec, int distance) { List<Vector3d> vecs = new ArrayList<>(); Vector3d step = endVec.subtract(startVec).normalize(); int rayTraceCount = 20; for (int i=0;i<distance;i++) for (int j=0;j<rayTraceCount;j++) vecs.add(startVec.add(step.scale(i).add(step.scale((float) j / (float) rayTraceCount)))); return vecs; } The vecs passed into the first method comes from the second method. The concept is to gather a collection of vectors, and the do ray trace between each of them. The first method can be a lot more simplified but not on my case since I also do entity penetrations, with damage calculations...etc. Anyways, if you only do normal raytracing what you will get will be something like:   Black Block represents a solid block Gray Block represents air or empty shaped block Green dots represents the positions we ray trace between. Blue dots represents the ray trace hit result. As you can see, the ray trace hit will not (unlikely) hit the surface when coming out of a block, therefore we need to detect the situation and ray trace back wards: So we get the "entering" and "exiting" points.   Here comes the rendering part once again, once you have let the client know where is hit you can perform the rendering based on the ray trace result. private static void renderObjectAt(Minecraft minecraft, EnvironmentObjectEffect object, World world, MatrixStack stack, float size, float offsetScale, ResourceLocation texture) { Vector3d vec = object.getVec(); stack.push(); Vector3d view = Minecraft.getInstance().gameRenderer.getActiveRenderInfo().getProjectedView(); double x = vec.x - view.getX(); double y = vec.y - view.getY(); double z = vec.z - view.getZ(); if (Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2)) > 100.0F) return; stack.translate(x, y, z); Direction direction = object.getDirection(); if (direction != null) { Vector3i offset = direction.getDirectionVec(); stack.translate(offset.getX() * offsetScale, offset.getY() * offsetScale, offset.getZ() * offsetScale); rotateByDirection(stack, direction); } else { stack.rotate(minecraft.getRenderManager().getCameraOrientation()); stack.rotate(Vector3f.ZP.rotationDegrees(180.0F)); } if (object.doBlend()) { Color colour = new Color(world.getBlockState(object.getPos()).getMaterialColor(world, object.getPos()).colorValue); RenderSystem.color4f(colour.getRed() / 255.0F, colour.getGreen() / 255.0F, colour.getBlue() / 255.0F, object.getTransparency()); } AVAClientUtil.blit(stack, texture, -size, -size, size, size); RenderSystem.color4f(1.0F, 1.0F, 1.0f, 1.0F); stack.pop(); } direction is facing from the BlockRayTraceResult, and doBlend is true so it will look better with the block behind it. The offset is required otherwise it will be on the same level with the block, the offset scale is a small number so there will not be an obvious gap between the wall and the texture object, the scale also prevents multiple objects overlap, for example when I have multiple "renderable objects": for (EnvironmentObjectEffect bulletHole : AVACommonUtil.cap(world).getBulletHoles()) renderObjectAt(minecraft, bulletHole, world, stack, 0.075F, 0.01F, BULLET_HOLE); for (EnvironmentObjectEffect blood : AVACommonUtil.cap(world).getBloods()) renderObjectAt(minecraft, blood, world, stack, 0.525F, 0.011F, BLOOD); for (EnvironmentObjectEffect knifeHole : AVACommonUtil.cap(world).getKnifeHoles()) renderObjectAt(minecraft, knifeHole, world, stack, 0.095F, 0.0105F, KNIFE_HOLE); for (EnvironmentObjectEffect grenadeMark : AVACommonUtil.cap(world).getGrenadeMarks()) renderObjectAt(minecraft, grenadeMark, world, stack, 2.5F, 0.075F, GRENADE_MARK); bullet hole < knife hole < blood < grenade mark (level) Red Image    
    • Hi, this article is more of a experience sharing instead of a tutorial, the code themselves should be self-explanatory, and the way I do things may not be the best practice, or most efficient. Product:   I started with the textures, we need the textures/icons that are being rendered to the world, and the ones for the UI. The blue textures are used when the option is hovered. Then, we need to find out where the mouse is at and which one is selected, we can check the distance and angle from the screen center and decide which part it is on: private int getHoveringType(Minecraft minecraft) { double mX = minecraft.mouseHelper.getMouseX(); double mY = minecraft.mouseHelper.getMouseY(); double actualW = minecraft.getMainWindow().getWidth() / 2.0F; double actualH = minecraft.getMainWindow().getHeight() / 2.0F; double mX2 = mX - actualW; double mY2 = mY - actualH; double angle = AVAWeaponUtil.getAngleFromCoord(mX2, -mY2) + 30; if (Math.sqrt(mX2 * mX2 + mY2 * mY2) <= 15 * minecraft.getMainWindow().getGuiScaleFactor()) return -1; if (angle > 360 || angle <= 60) return 0; return ((int) angle / 60); } public static double getAngleFromCoord(double x, double y) { double angle; angle = abs(atan2(x, y) * 180.0D / PI); if (x < 0) angle = 360 - angle; return angle; } In this case the angle is 60 because 360 / 6 options = 60, and if the mouse is within radius of 15 from the screen center then no action is performed (-1) And then the rendering can be done. @Override public void render(Minecraft minecraft, PlayerEntity player, MatrixStack stack, IPlayerAction capability, float screenWidth, float screenHeight) { float x = screenWidth / 2.0F; float y = screenHeight / 2.0F; float size = 60; int type = getHoveringType(minecraft); AVAClientUtil.blit(stack, type == -1 ? UI_BG_LIT : UI_BG, x - size, y - size, x + size, y + size); for (int i = 0; i < 6; i++) { stack.push(); stack.translate(x, y, 0.0F); stack.rotate(Vector3f.ZP.rotationDegrees(i * 60)); stack.translate(-x, -y, 0.0F); AVAClientUtil.blit(stack, type == i ? UI_BG_2_LIT : UI_BG_2, x - size, y - size, x + size, y + size); stack.pop(); } AVAClientUtil.blit(stack, UI_BG_ICON_LAYER, x - size, y - size, x + size, y + size); } public static void blit(MatrixStack stack, @Nullable ResourceLocation texture, float x1, float y1, float x2, float y2) { if (texture != null) Minecraft.getInstance().getTextureManager().bindTexture(texture); Matrix4f matrix = stack.getLast().getMatrix(); Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferbuilder = tessellator.getBuffer(); bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX); bufferbuilder.pos(matrix, x1, y2, 0.0F).tex(0.0F, 1.0F).endVertex(); bufferbuilder.pos(matrix, x2, y2, 0.0F).tex(1.0F, 1.0F).endVertex(); bufferbuilder.pos(matrix, x2, y1, 0.0F).tex(1.0F, 0.0F).endVertex(); bufferbuilder.pos(matrix, x1, y1, 0.0F).tex(0.0F, 0.0F).endVertex(); tessellator.draw(); } If the type is -1, then the circle at the center use the blue texture. Otherwise if the type equals the index of the option, it uses the blue texture (or just use RenderSystem.color4f). By rotating an identical texture we don't need to have 6 different textures for each option.     public static boolean ACTIVE = false; public static Vector3d VEC = null; @Override public void tick(Minecraft minecraft, PlayerEntity player) { if (minecraft.isGameFocused() && minecraft.currentScreen == null && AVAClientConfig.ENABLE_PING_HOTKEY.get()) { if (AVAClientUtil.middleMouseDown()) { if (!ACTIVE) { Vector3d eye = AVAWeaponUtil.getEyePositionFor(player); BlockRayTraceResult result = player.world.rayTraceBlocks(new RayTraceContext(eye, eye.add(player.getLookVec().scale(100.0F)), RayTraceContext.BlockMode.VISUAL, RayTraceContext.FluidMode.NONE, player)); if (result.getType() != RayTraceResult.Type.MISS) { ACTIVE = true; minecraft.mouseHelper.ungrabMouse(); if (minecraft.gameSettings.keyBindPickBlock.getKey().getKeyCode() == GLFW.GLFW_MOUSE_BUTTON_MIDDLE) AVAClientUtil.unpressKeybind(minecraft.gameSettings.keyBindPickBlock); VEC = result.getHitVec(); } } } else { int type = getHoveringType(minecraft); if (ACTIVE && VEC != null && type != -1) AVAPackets.INSTANCE.sendToServer(new PingMessage(VEC, ActivePingEffect.Type.values()[type])); reset(minecraft); } } else reset(minecraft); } If player's focusing, the middle mouse is down, then we check if there's terrain (block) in player's sight within 100 blocks, if not, reset the vec, regrab the mouse and set active to false. MouseHelper#ungrabMouse call allows players to move mouse around the screen.   Once we have the VEC set (where the ping will occur), we can render a line between the center of the screen and the ping location. (White line) { ActiveRenderInfo info = minecraft.gameRenderer.getActiveRenderInfo(); Vector3f view = info.getViewVector(); Vector3d vec = info.getProjectedView().add(view.getX(), view.getY(), view.getZ()); drawLine(stack, (float) vec.x, (float) vec.y, (float) vec.z, (float) pingVec.x, (float) pingVec.y, (float) pingVec.z, 255, 255, 255, 1.0F) } public static void drawLine(MatrixStack stack, float x1, float y1, float z1, float x2, float y2, float z2, int r, int g, int b, float a) { AVAClientUtil.drawTransparent(true); IRenderTypeBuffer.Impl impl = IRenderTypeBuffer.getImpl(Tessellator.getInstance().getBuffer()); IVertexBuilder builder = impl.getBuffer(RenderType.LINES); Vector3d view = Minecraft.getInstance().gameRenderer.getActiveRenderInfo().getProjectedView(); stack.push(); stack.translate(-view.x, -view.y, -view.z); Matrix4f matrix = stack.getLast().getMatrix(); builder.pos(matrix, x1, y1, z1).color(r, g, b, (int) (a * 255.0F)).endVertex(); builder.pos(matrix, x2, y2, z2).color(r, g, b, (int) (a * 255.0F)).endVertex(); stack.pop(); impl.finish(); AVAClientUtil.drawTransparent(false); RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); } If you did not add the look offset to the camera position it will not be visible.   Then we send a packet to the server to notify all other players that I've ping the location. Once players receives the location of the pings, it's time to render them. RenderSystem.disableDepthTest(); AVAClientUtil.drawTransparent(true); Vector3d view = Minecraft.getInstance().gameRenderer.getActiveRenderInfo().getProjectedView(); Vector3d vec = activePing.getVec(); double distance = activePing.getVec().distanceTo(view); if (distance > 100.0F) continue; renderObjectAt(minecraft, activePing, world, stack, (float) (distance / 20.0F), 0.0F, activePing.getTexture()); double x = vec.x - view.getX(); double y = vec.y - view.getY(); double z = vec.z - view.getZ(); stack.push(); stack.translate(x, y, z); stack.rotate(minecraft.getRenderManager().getCameraOrientation()); stack.rotate(Vector3f.ZP.rotationDegrees(180.0F)); float size = (float) (distance / 200.0F); stack.scale(size, size, size); IRenderTypeBuffer.Impl impl = IRenderTypeBuffer.getImpl(Tessellator.getInstance().getBuffer()); String text = AVACommonUtil.round(distance, 2) + "m"; minecraft.fontRenderer.func_243247_a(new StringTextComponent(text), -minecraft.fontRenderer.getStringWidth(text) / 2.0F, 10, AVAConstants.AVA_HUD_TEXT_WHITE, false, stack.getLast().getMatrix(), impl, true, 0, 15728880); impl.finish(); stack.pop(); private static void renderObjectAt(Minecraft minecraft, EnvironmentObjectEffect object, World world, MatrixStack stack, float size, float offsetScale, ResourceLocation texture) { Vector3d vec = object.getVec(); stack.push(); Vector3d view = Minecraft.getInstance().gameRenderer.getActiveRenderInfo().getProjectedView(); double x = vec.x - view.getX(); double y = vec.y - view.getY(); double z = vec.z - view.getZ(); if (Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2)) > 100.0F) return; stack.translate(x, y, z); Direction direction = object.getDirection(); if (direction != null) { Vector3i offset = direction.getDirectionVec(); stack.translate(offset.getX() * offsetScale, offset.getY() * offsetScale, offset.getZ() * offsetScale); rotateByDirection(stack, direction); } else { stack.rotate(minecraft.getRenderManager().getCameraOrientation()); stack.rotate(Vector3f.ZP.rotationDegrees(180.0F)); } if (object.doBlend()) { Color colour = new Color(world.getBlockState(object.getPos()).getMaterialColor(world, object.getPos()).colorValue); RenderSystem.color4f(colour.getRed() / 255.0F, colour.getGreen() / 255.0F, colour.getBlue() / 255.0F, object.getTransparency()); } AVAClientUtil.blit(stack, texture, -size, -size, size, size); RenderSystem.color4f(1.0F, 1.0F, 1.0f, 1.0F); stack.pop(); }   In the code I change the size of the object according to the distance ( (distance / 20.0F) ), so the object will stay at similar size no matter the distance between them, and so does the text size. The direction is always null, and doBlend is false. They are used in my other renderings.      
    • Hello There! We got another Hunger Games for you guys and in this episode we get so lucky right off the bat and we get 4 diamonds so we knew as soon as we got this we had to win! However something happens that I am not gonna spoil but it doesn't change too much within us winning! There are some hilarious moments in this episode that I know you guys are gonna love! I hope you all enjoy this video and if you did please consider subscribing and liking the video while you are at it!  
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.