Jump to content

Recommended Posts

Posted (edited)

hay good nights 
i made an structure and save it to nbt using the minecraft:StructureBlock
the idea basically is a sewer i have to made all the sections and later joint them in the level

 

i wanna to create a wand to spawn this same structure on right click and i need to apply the offset soo the sewer section spawn buried underground 

i put the nbt file in 
/src/main/resources/data/basemmod/structures/tunel_i.nbt 

but i dont know how to call it from code to make it spanw in the world 

 

i need something like 

	    // ########## ########## ########## ##########
    @Override
    public InteractionResultHolder<ItemStack> use(Level warudo, Player pe, InteractionHand hand) {
        System.out.println("use( Spawn Structure at target Block using Player.getDirection() to define rotation );");
        
	        Target target = new Target(warudo, pe, 20);
        Vec3 vh = target.getVh();// util.calcularVectores(pe, 10 , 0.0F );//
	        
        System.out.println("use();" + warudo.isClientSide );
        if(!warudo.isClientSide) 
        {
	                IdontKnowWhatClass  idkn =   IdontKnowWhatClass.loadStructure("basemmod:tunel_i");
	                idkn.setPosition( target.getBlockPos() );
                idkn.setOffset( -2, - 6, 0  );
	                idkn.spanwStructure();
	        }    
	        return InteractionResultHolder.pass(pe.getItemInHand(hand));
    }
	 
	

thanks for your attention 

 

Edited by perromercenary00
Posted

I have a similar feature on my own mod (though I think my solution is a bit overkill).

I put my .nbt files in src/main/resources/data/<modid>/structures

And I read the files in with these functions:

    public static ArrayList<BuildingBlock> getBuildingBlocks(String structureName, LevelAccessor level) {
        ResourceManager resourceManager;
        if (level.isClientSide())
            resourceManager = Minecraft.getInstance().getResourceManager();
        else
            resourceManager = level.getServer().getResourceManager();

        CompoundTag nbt = getBuildingNbt(structureName, resourceManager);
        ArrayList<BuildingBlock> blocks = new ArrayList<>();

        // load in blocks (list of blockPos and their palette index)
        ListTag blocksNbt = nbt.getList("blocks", 10);

        ArrayList<BlockState> palette = getBuildingPalette(nbt);

        for(int i = 0; i < blocksNbt.size(); i++) {
            CompoundTag blockNbt = blocksNbt.getCompound(i);
            ListTag blockPosNbt = blockNbt.getList("pos", 3);

            blocks.add(new BuildingBlock(
                new BlockPos(
                    blockPosNbt.getInt(0),
                    blockPosNbt.getInt(1),
                    blockPosNbt.getInt(2)
                ),
                palette.get(blockNbt.getInt("state"))
            ));
        }
        return blocks;
    }

    public static CompoundTag getBuildingNbt(String structureName, ResourceManager resManager) {
        try {
            ResourceLocation rl = new ResourceLocation("reignofnether", "structures/" + structureName + ".nbt");
            Optional<Resource> rs = resManager.getResource(rl);
            return NbtIo.readCompressed(rs.get().open());
        }
        catch (Exception e) {
            System.out.println(e);
            return null;
        }
    }

    public static ArrayList<BlockState> getBuildingPalette(CompoundTag nbt) {
        ArrayList<BlockState> palette = new ArrayList<>();
        // load in palette (list of unique blockstates)
        ListTag paletteNbt = nbt.getList("palette", 10);
        for(int i = 0; i < paletteNbt.size(); i++)
            palette.add(NbtUtils.readBlockState(paletteNbt.getCompound(i)));
        return palette;
    }

BuildingBlock is just my own class that combines BlockPos, BlockState and has a checker to see if it exists in the world yet.

I spawn the building in with this function. Remember placing any block needs to be done serverside, so Level level here needs to be from a WorldTickEvent where level is serverside. I just call buildNextBlock() on every tick.

    private void buildNextBlock(Level level) {
        ArrayList<BuildingBlock> unplacedBlocks = new ArrayList<>(blocks.stream().filter(b -> !b.isPlaced).toList());
        int minY = getMinCorner(unplacedBlocks).getY();
        ArrayList<BuildingBlock> validBlocks = new ArrayList<>();

        // iterate through unplaced blocks and start at the bottom Y values
        for (BuildingBlock block : unplacedBlocks) {
            BlockPos bp = block.getBlockPos();
            if ((bp.getY() <= minY) &&
                (!level.getBlockState(bp.below()).isAir() ||
                 !level.getBlockState(bp.east()).isAir() ||
                 !level.getBlockState(bp.west()).isAir() ||
                 !level.getBlockState(bp.south()).isAir() ||
                 !level.getBlockState(bp.north()).isAir() ||
                 !level.getBlockState(bp.above()).isAir()))
                validBlocks.add(block);
        }
        if (validBlocks.size() > 0)
            validBlocks.get(0).place();
    }

BuildingBlock.place() is:

BlockPos bp = nextBlock.getBlockPos();
BlockState bs = nextBlock.getBlockState();
if (serverLevel.isLoaded(bp)) {
  serverLevel.setBlockAndUpdate(bp, bs);
  serverLevel.levelEvent(LevelEvent.PARTICLES_DESTROY_BLOCK, bp, Block.getId(bs));
  serverLevel.levelEvent(bs.getSoundType().getPlaceSound().hashCode(), bp, Block.getId(bs));
  blockPlaceQueue.removeIf(i -> i.equals(nextBlock));
}

The reason I say this is a bit overkill is my code builds the building over the course of a few seconds from the ground up (1 block per tick) with sound and particle effects - it's a pretty fancy way to do it but if you just want to place all the blocks at once with no effects, you can probably ignore that 2nd chunk of code and skip straight to serverLevel.setBlockAndUpdate()

  • perromercenary00 changed the title to [solved][1.19.2]spawn NBT structure from a rod
Posted

yaa thats what i was looking for 
i change the code to work mi style 
i find than for some reason the vainilla BlockState.rotate() method dont works for mi custome blocks but just work around it


	package basemmod.util;
	import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
	import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
	public class NbtStructure {
	    public LevelAccessor warudo = null;
	    public LevelAccessor getWarudo() {
        return warudo;
    }
	    public void setWarudo(LevelAccessor warudo) {
        this.warudo = warudo;
    }
	    public String modname = "basemmod";
    public String structureName = "";
    public Rotation rot = Rotation.NONE;
	    private int ci_x = 0;
    private int ci_y = 0;
    private int ci_z = 0;
	    // ########## ########## ########## ########## ########## ##########
    // BlockMap part
    // ########## ########## ########## ########## ########## ##########
	    // X Z Y
    private Map<Integer, Map<Integer, Map<Integer, BlockState>>> map = new HashMap<Integer, Map<Integer, Map<Integer, BlockState>>>();
	    // Z Y
    private Map<Integer, Map<Integer, BlockState>> X = new HashMap<Integer, Map<Integer, BlockState>>();
	    // Y
    private Map<Integer, BlockState> Z = new HashMap<Integer, BlockState>();
	    public Set<BlockPos> block_list = new HashSet<BlockPos>();
	    private BlockState blkstate = null;
    private BlockPos blkpos = null;
	    private ResourceManager resourceManager = null;
	    // ########## ########## ########## ##########
    // sets the blockstate for this blockpos in the blockmap
    public boolean setBlockState(BlockPos pos, BlockState value) {
        return setBlockState(pos.getX(), pos.getY(), pos.getZ(), value);
    }
	    public boolean setBlockState(int bx, int by, int bz, BlockState value) {
	        X = map.get(bx);
	        if (X == null) {
            X = new HashMap<Integer, Map<Integer, BlockState>>();
            map.put(bx, X);
        }
	        if (X != null) {
            Z = X.get(bz);
	            if (Z == null) {
                Z = new HashMap<Integer, BlockState>();
                X.put(bz, Z);
            }
	            if (Z != null) {
                Z.put(by, value);
	                this.block_list.add(new BlockPos(bx, by, bz));
                return true;
            }
        }
	        return false;
    }
	    // ########## ########## ########## ##########
    // return the blockstate for this blockpos from the blockmap
    public BlockState getBlockState(BlockPos pos) {
        BlockState blkstate = getBlockState(pos.getX(), pos.getY(), pos.getZ());
        return blkstate;
    }
	    public BlockState getBlockState(int bx, int by, int bz) {
        BlockState blkstate = null;
	        X = map.get(bx);
	        if (X != null) {
            Z = X.get(bz);
	            if (X != null) {
                blkstate = Z.get(by);
            }
        }
	        return blkstate;
    }
	    public void print() {
	        int count = 0;
	        for (BlockPos cursor : block_list) {
            System.out.print("\n" + count + ") ");
            System.out.print(cursor.getX() + ", ");
            System.out.print(cursor.getY() + ", ");
            System.out.print(cursor.getZ() + " : ");
            System.out.print(get_blkfullname(this.getBlockState(cursor)) + "\n");
            count++;
        }
    }
	    // ########## ########## ########## ########## ########## ##########
    // main constructor
    // NBT part
    // ########## ########## ########## ########## ########## ##########
    public NbtStructure(Level warudo, String structureName) {
	        this.warudo = warudo;
        this.getResourceManager();
	        this.structureName = structureName;
        getBuildingBlocks(this.structureName);
	        this.print();
    }
	    public NbtStructure(Level warudo, String structureName, BlockPos cornerstone, Rotation rot) {
	        this.warudo = warudo;
        this.getResourceManager();
	        this.ci_x = cornerstone.getX();
        this.ci_y = cornerstone.getY();
        this.ci_z = cornerstone.getZ();
	        this.rot = rot;
	        this.structureName = structureName;
        getBuildingBlocks(this.structureName);
	        this.print();
    }
	    public NbtStructure(Level warudo, String structureName, BlockPos cornerstone, Direction facing) {
	        switch (facing) {
        default:
        case UP:
        case DOWN:
        case SOUTH:
            this.rot = Rotation.NONE;
            break;
        case NORTH:
            this.rot = Rotation.CLOCKWISE_180;
            break;
        case EAST:
            this.rot = Rotation.COUNTERCLOCKWISE_90;
            break;
        case WEST:
            this.rot = Rotation.CLOCKWISE_90;
            break;
        }
	        this.warudo = warudo;
        this.getResourceManager();
	        this.ci_x = cornerstone.getX();
        this.ci_y = cornerstone.getY();
        this.ci_z = cornerstone.getZ();
	        this.structureName = structureName;
        getBuildingBlocks(this.structureName);
	        this.print();
    }
	    
    // ########## ########## ########## ########## ########## ##########    
    public ResourceManager getResourceManager() {
	        if (resourceManager == null)
            if (this.warudo.isClientSide())
                this.resourceManager = Minecraft.getInstance().getResourceManager();
            else
                this.resourceManager = this.warudo.getServer().getResourceManager();
	        return resourceManager;
    }
	    // ########## ########## ########## ########## ########## ##########
    // load blocks from nbt.file to the blockmap
    // ########## ########## ########## ########## ########## ##########
    public void getBuildingBlocks(String structureName) {
        CompoundTag nbt = getBuildingNbt(structureName);
	        if (nbt == null) {
            System.out.println(" Structure not find ");
            return;
        }
	        // load in blocks (list of blockPos and their palette index)
        ListTag blocksNbt = nbt.getList("blocks", 10);
	        ArrayList<BlockState> palette = getBuildingPalette(nbt);
	        for (int i = 0; i < blocksNbt.size(); i++) {
            CompoundTag blockNbt = blocksNbt.getCompound(i);
            ListTag blockPosNbt = blockNbt.getList("pos", 3);
	            blkstate = palette.get(blockNbt.getInt("state"));
            blkpos = new BlockPos(blockPosNbt.getInt(0), blockPosNbt.getInt(1), blockPosNbt.getInt(2));
	            // rotate
            blkstate = rotate_blockstate(blkstate, this.rot);
            blkpos = rotate_blockpos(blkpos, this.rot);
	            // fit to corner stone block
            blkpos = (new BlockPos((blkpos.getX() + this.ci_x), (blkpos.getY() + this.ci_y),
                    (blkpos.getZ() + this.ci_z)));
	            // save to the hash map
            this.setBlockState(blkpos, palette.get(blockNbt.getInt("state")));
	            block_list.add(blkpos);
            // warudo.setBlock(blkpos, blkstate, 10);
        }
    }
	    // ########## ########## ########## ########## ########## ##########
    // writte the blocks to the world
    // ########## ########## ########## ########## ########## ##########
    public void setBlocks() {
        BlockState cursorstate = null;
        FluidState fluidstate = null;
        boolean waterlogged = false;
	        for (BlockPos cursor : this.block_list) {
            cursorstate = this.getBlockState(cursor);
            waterlogged = false;
            // especial blocks and stuff
	            if (cursorstate.hasProperty(BlockStateProperties.WATERLOGGED)) {
                waterlogged = cursorstate.getValue(BlockStateProperties.WATERLOGGED);
	                if (!waterlogged) {
                    fluidstate = this.warudo.getFluidState(cursor);
                    if (fluidstate.getType() == Fluids.WATER) {
                        cursorstate = cursorstate.setValue(BlockStateProperties.WATERLOGGED, true);
                    }
                }
            }
	            this.warudo.setBlock(cursor, cursorstate, 10);
        }
    }
	    // ########## ########## ########## ########## ########## ##########
    // ########## ########## ########## ########## ########## ##########
    public CompoundTag getBuildingNbt(String structureName) {
        try {
            ResourceLocation rl = new ResourceLocation(this.modname, "structures/" + structureName + ".nbt");
            Optional<Resource> rs = this.resourceManager.getResource(rl);
            return NbtIo.readCompressed(rs.get().open());
        } catch (Exception e) {
            // System.out.println(e);
            return null;
        }
    }
	    // ########## ########## ########## ########## ########## ##########
    public ArrayList<BlockState> getBuildingPalette(CompoundTag nbt) {
        ArrayList<BlockState> palette = new ArrayList<>();
        // load in palette (list of unique blockstates)
        ListTag paletteNbt = nbt.getList("palette", 10);
        for (int i = 0; i < paletteNbt.size(); i++)
            palette.add(NbtUtils.readBlockState(paletteNbt.getCompound(i)));
        return palette;
    }
	    // ########## ########## ########## ##########
    public BlockState rotate_blockstate(BlockState blkstate, Rotation rot) {
	        // Direccion
        Direction facing = null;
	        if (blkstate.hasProperty(BlockStateProperties.FACING)) {
            facing = blkstate.getValue(BlockStateProperties.FACING);
        }
	        if (blkstate.hasProperty(BlockStateProperties.HORIZONTAL_FACING)) {
            facing = blkstate.getValue(BlockStateProperties.HORIZONTAL_FACING);
        }
	        Direction.Axis axix = null;
        if (blkstate.hasProperty(BlockStateProperties.AXIS)) {
            axix = blkstate.getValue(BlockStateProperties.AXIS);
        }
	        if (blkstate.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) {
            axix = blkstate.getValue(BlockStateProperties.HORIZONTAL_AXIS);
        }
	        if (facing != null && facing != Direction.UP && facing != Direction.DOWN) {
            switch (rot) {
            default:
                NONE:
                // du nothing
                break;
            case CLOCKWISE_180:
                facing = facing.getOpposite();
                break;
            case CLOCKWISE_90:
                facing = facing.getClockWise();
                break;
            case COUNTERCLOCKWISE_90:
                facing = facing.getCounterClockWise();
                break;
            }
	            if (blkstate.hasProperty(BlockStateProperties.FACING)) {
                blkstate = blkstate.setValue(BlockStateProperties.FACING, facing);
            }
	            if (blkstate.hasProperty(BlockStateProperties.HORIZONTAL_FACING)) {
                blkstate = blkstate.setValue(BlockStateProperties.HORIZONTAL_FACING, facing);
            }
        }
	        // axis
        // Direction.Axis.valueOf(value.toUpperCase())
	        if (axix != null) {
	            switch (axix) {
            default:
            case Y:
                // du nuthing
                break;
            case X:
                axix = Direction.Axis.Z;
                break;
            case Z:
                axix = Direction.Axis.X;
                break;
            }
	            if (blkstate.hasProperty(BlockStateProperties.AXIS)) {
                blkstate = blkstate.setValue(BlockStateProperties.AXIS, axix);
            }
	            if (blkstate.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) {
                blkstate = blkstate.setValue(BlockStateProperties.HORIZONTAL_AXIS, axix);
            }
        }
	        // this thing dont works on mod made blocks
        if (axix == null && facing == null) {
            blkstate.rotate(rot);
        }
	        return blkstate;
    }
	
    // ########## ########## ########## ##########
    public BlockPos rotate_blockpos(BlockPos cursor, Rotation rot) {
        switch (rot) {
        default:
            // case NORTH:
            // du nuthing
            break;
	        case CLOCKWISE_90:
            cursor = new BlockPos(cursor.getZ() * -1, cursor.getY(), cursor.getX());
            break;
	        case CLOCKWISE_180:
            cursor = new BlockPos(cursor.getX() * -1, cursor.getY(), cursor.getZ() * -1);
            break;
	        case COUNTERCLOCKWISE_90:
            cursor = new BlockPos(cursor.getZ(), cursor.getY(), cursor.getX() * -1);
            break;
        }
	        return cursor;
    }
	    // ########## ########## ########## ########## ########## ##########    
    // ########## ########## ########## ########## ########## ##########
    //
    public static String get_blkfullname(BlockState blkstate) {
        if (blkstate == null) {
            return "NULL";
        }
	        String nnn = "" + blkstate.getBlock().getName().getString().toLowerCase();
	        return fix_blkfullname(nnn);
    }
	    // ########## ########## ########## ########## ########## ##########
    //
    public static String fix_blkfullname(String blkfullname) {
        if (blkfullname.contains(".")) {
            String[] split1 = blkfullname.split("\\."); // "\\."
	            if (split1.length > 1) {
                blkfullname = split1[split1.length - 1].replaceAll("_", " ");
            }
        }
	        return blkfullname.toLowerCase();
    }
	    // ########## ########## ########## ##########
    // ########## ########## ########## ##########
    public static BlockPos chunk_northwest_corner(Level warudo, BlockPos pos) {
        BlockPos min = null;
	        int subx = 0;
        int subz = 0;
        int abs = 0;
	        int factox = 0;
        int factoz = 0;
	        // si el valor es negativo
        if (pos.getX() < 0) {
            abs = Math.abs(pos.getX());
	            factox = (abs / 16);
            factox = ((abs % 16) > 0) ? factox + 1 : factox;
            subx = -16 * factox;
	        } else {
            subx = pos.getX() - (pos.getX() % 16);
        }
	        // si el valor es negativo
        if (pos.getZ() < 0) {
            abs = Math.abs(pos.getZ());
	            factoz = (abs / 16);
            factoz = ((abs % 16) > 0) ? factoz + 1 : factoz;
            subz = -16 * factoz;
	        } else {
            subz = pos.getZ() - (pos.getZ() % 16);
        }
	        min = new BlockPos(subx, pos.getY(), subz);
        return min;
    }
	    // ########## ########## ########## ########## ########## ##########
    // ########## ########## ########## ########## ########## ##########
    // ########## ########## ########## ########## ########## ##########
    // ########## ########## ########## ########## ########## ##########
}
 
	 
	

 

	    // ########## ########## ########## ##########
    @Override
    public InteractionResultHolder<ItemStack> use(Level warudo, Player pe, InteractionHand hand) {
	        Target target = new Target(warudo, pe, 20);
	//spanw full chunk structure aligned whit borders        
        if(!warudo.isClientSide) 
        {
            Postate postate = target.get_postate();
            //Direction facing = pe.getDirection();
	            BlockPos min = NbtStructure.chunk_northwest_corner( warudo, postate.get_blockpos() );
            NbtStructure structure  = new NbtStructure(warudo, "empty_chumk", min, Direction.SOUTH );
            
            structure.setBlocks(); //write the bocks 
	        }
        
        return InteractionResultHolder.pass(pe.getItemInHand(hand));
    }
	

 

 

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.