Jump to content

Recommended Posts

Posted (edited)

Hey there,

 

I'm working on a mod that notifies the player whenever certain tasks are done. One of the tasks finishes when a block changes to a certain state.

I want the player to be able to select a specifc state and the server will then check whether or not the block has changed and then notify the player.

 

My issue is sending the blockstate with its properties to the server so it can handle it. So I wanted to ask if there's any way to send a blockstate to

the server with all it's properties. Sending the block as an ItemStack with damage didn't work for all states so I thought that it might be possible

to convert the blockstate to JSON and then send that to the server but I didn't have any luck finding a way to do that.


Here's the repository if anyone wants to look at it.

 

Thank's in advance!

 

Edit: Here's what I ended up using thanks to diesieben07 (not 100% finished)
 

Spoiler



 /**
     * ByteStreamExtensionsJavaCode.java
     * @author diesieben07
     * https://git.io/vbmWM
     */

    public static void writeState(ByteBuf to, IBlockState state) {
        Block b = state.getBlock();
        int meta = b.getMetaFromState(state);

        to.writeShort(Block.getIdFromBlock(b) | (meta << 12));

        IBlockState stateFromMeta = b.getStateFromMeta(meta);
        //to.writeInt(stateFromMeta.getPropertyKeys().size());
        writeNeededProperties(to, state, stateFromMeta);
    }

    public static IBlockState readState(ByteBuf from) {
        IBlockState state = Block.getStateById(from.readShort());
        BlockStateContainer container = state.getBlock().getBlockState();

        do {
            if (!from.isReadable())
                return state;
            String propertyName = ByteBufUtils.readUTF8String(from);
            if (propertyName != null) {
                String propertyValue = ByteBufUtils.readUTF8String(from);
                state = parseAndApply(propertyName, propertyValue, state, container);
            } else
                return state;
        } while(true);
    }

    private static IBlockState parseAndApply(@Nonnull String propertyName, @Nonnull String propertyValue, @Nonnull IBlockState state, @Nonnull BlockStateContainer stateContainer) {
        IProperty<?> property = stateContainer.getProperty(propertyName);
        if (property != null) {
            return applyValue(property, propertyValue, state);
        } else {
            return state;
        }
    }

    @SuppressWarnings("Guava")
    private static <T extends Comparable<T>> IBlockState applyValue(IProperty<T> property, String propertyValue, IBlockState state) {
        Optional<T> parsed = property.parseValue(propertyValue);
        return parsed.isPresent() ? state.withProperty(property, parsed.get()) : state;
    }

    private static void writeNeededProperties(@Nonnull ByteBuf buf, @Nonnull IBlockState fullState, @Nonnull IBlockState stateFromMeta) {
        for (IProperty<?> property : fullState.getPropertyKeys()) {
            writePropertyIfNeeded(buf, fullState, stateFromMeta, property);
        }
    }

    private static <T extends Comparable<T>> void writePropertyIfNeeded(ByteBuf buf, IBlockState fullState, IBlockState stateFromMeta, IProperty<T> property) {
        T fullValue = fullState.getValue(property);
        T metaValue = stateFromMeta.getValue(property);
        if (!Objects.equals(fullValue, metaValue)) {
            ByteBufUtils.writeUTF8String(buf, property.getName());
            ByteBufUtils.writeUTF8String(buf, property.getName(fullValue));
        }
    }


 

 

Edited by universaI
solved

Professional procrastinator | GitHub | Twitter | Steam

Posted

I'm sure vanilla manages this somewhere.

I'm sure you could look at it.

Even if that fails, I'm sure an IBlockState decomposes into a collection of values that can be contained within a packet.

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
53 minutes ago, diesieben07 said:

Usually sending the state ID is enough (Block.getStateId resp. Block.getStateById), it's 2 bytes.

But this only sends properties that are encoded into metadata using getMetaFromState / getStateFromMeta.

 

If you actually need to encode the whole property set of an IBlockState, use something like this: https://git.io/vbmcO (written in Kotlin, but the same can be done in Java).

Thanks! The latter did the trick. I think I can figure out the rest on my own.

Professional procrastinator | GitHub | Twitter | Steam

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



×
×
  • Create New...

Important Information

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