Сохранение структуры большого размера

Версия Minecraft
1.12.2
5,018
47
783
Всем привет. В общем, кто в теме, тот шарит, что в 1.12(или 1.11) была добавлена такая фича как struckture_block. Данными блоками можно выделить регион и сохранить кусок мира в нбт для последующего использования в генерациях. Разработчики поступили неверно, ограничив максимальный обьем куба 32 блоками.
Короче говоря, мне этого маленького кубика 32на32на32 не хватает для того чтобы уместить мои советские гигантские постройки. Сначала думал сделать аналогичный свой блок, но потом решил, что гораздо быстрее будет исправить это недоразумение в ванилле. Собственно, вся проблема заключается в том, что метод для хука то статичный, а в статичном нельзя вызвать суперметод readFromNBT. Ну и общем говоря, вставляя вот такой хук, я сталкиваюсь с проблемой, что тайл попросту не сохраняется.
Что я делаю не так? Как мне вызвать суперметод, без которого не хочет работать readFromNBT?
hohserg предложил мне просто взять и тело суперметода скопипастить себе в хук. Возникла проблема - джве переменных, которые там используются, приватные. Казалось бы, фигня, АТ наше все? А вот нет. После запуска АТ, когда я указал изменить ФСЕ модификаторы в классе TileEntity на публик, и билд сасесшфули, но почему то именно эти две переменных остались приватными.

P.S В ванилле эти глу.. developers the mainkraft зачем то генерят большую структуру по кускам. (лесной дом того перца например, или как там). Догадываюсь зачем, но мне плевать, я хочу целиком:)

Java:
    @Hook(returnCondition = ReturnCondition.ALWAYS)
       public static void readFromNBT(TileEntityStructure tyu,NBTTagCompound compound)
        {
     
        //    tyu.readFromNBT(compound);
         
            tyu.setName(compound.getString("name"));
        //    tyu.author = compound.getString("author");
            tyu.setMetadata(compound.getString("metadata"));
                int i = MathHelper.clamp(compound.getInteger("posX"), -64, 64);
                int j = MathHelper.clamp(compound.getInteger("posY"), -64, 64);
                int k = MathHelper.clamp(compound.getInteger("posZ"), -64, 64);
                tyu.setPosition(new BlockPos(i, j, k));
                int l = MathHelper.clamp(compound.getInteger("sizeX"), 0, 64);
                int i1 = MathHelper.clamp(compound.getInteger("sizeY"), 0, 64);
                int j1 = MathHelper.clamp(compound.getInteger("sizeZ"), 0, 64);
                tyu.setSize(new BlockPos(l, i1, j1));

                try
                {
                    tyu.setRotation(Rotation.valueOf(compound.getString("rotation")));
                }
                catch (IllegalArgumentException var11)
                {
                    tyu.setRotation(Rotation.NONE);
                }

                try
                {
                    tyu.setMirror(Mirror.valueOf(compound.getString("mirror")));
                }
                catch (IllegalArgumentException var10)
                {
                    tyu.setMirror(Mirror.NONE);
                }

                try
                {
                    tyu.setMode(TileEntityStructure.Mode.valueOf(compound.getString("mode")));
                }
                catch (IllegalArgumentException var9)
                {
                    tyu.setMode(TileEntityStructure.Mode.DATA);
                }

          //      tyu.ignoreEntities = compound.getBoolean("ignoreEntities");
                tyu.setPowered(compound.getBoolean("powered"));
                tyu.setShowAir(compound.getBoolean("showair"));
                tyu.setShowBoundingBox(compound.getBoolean("showboundingbox"));

                if (compound.hasKey("integrity"))
                {
                    tyu.setIntegrity(compound.getFloat("integrity"));
                }
                else
                {
                    tyu.setIntegrity(1.0F);
                }

                tyu.setSeed(compound.getLong("seed"));
             
             
                if (tyu.getWorld() != null)
                {
                    BlockPos blockpos = tyu.getPos();
                    IBlockState iblockstate = tyu.getWorld().getBlockState(blockpos);

                    if (iblockstate.getBlock() == Blocks.STRUCTURE_BLOCK)
                    {
                        tyu.getWorld().setBlockState(blockpos, iblockstate.withProperty(BlockStructure.MODE, tyu.getMode()), 2);
                    }
                }
        }
 
Последнее редактирование:
5,018
47
783
Вот кстати как это работает. Куб выделяется верно какой надо, а сохраняется опять же ток 32

Java:
[23:54:07] [main/INFO]: [CHAT] Успешно рассчитан размер конструкции «hut»
[23:54:07] [Server thread/INFO] [STDOUT]: [gloomyfolken.hooklib.sovietHook.AnnotationHooks:writeToNBT:99]: write BlockPos{x=19, y=74, z=54}
[23:54:50] [Server thread/INFO] [STDOUT]: [gloomyfolken.hooklib.sovietHook.AnnotationHooks:writeToNBT:99]: write BlockPos{x=19, y=74, z=54}
[23:54:51] [Server thread/INFO] [STDOUT]: [gloomyfolken.hooklib.sovietHook.AnnotationHooks:writeToNBT:99]: write BlockPos{x=19, y=32, z=32}
[23:54:51] [main/INFO]: [CHAT] Конструкция сохранена в файл «hut»
[23:54:55] [Server thread/INFO]: Saving and pausing game...
[23:54:55] [Server thread/INFO]: Saving chunks for level 'Новый мир'/overworld
[23:54:55] [Server thread/INFO] [STDOUT]: [gloomyfolken.hooklib.sovietHook.AnnotationHooks:writeToNBT:99]: write BlockPos{x=19, y=32, z=32}
 
1,038
57
229
Сохрани в свой формат, зачем тебе эта возня...
txt, xml, json, свой личный формат.
 
5,018
47
783
зачем тебе эта возня...
txt, xml, json, свой личный формат.
Гениальный, блин совет. Напишешь мне кастомный загрузчик и обработчик этого формата, м?
Я не спрашивал, как лучше сделать, тут про конкретную проблему вопрос, бро
 

tox1cozZ

aka Agravaine
8,454
598
2,890
А чего hohserg не предложил заюзать свои якоря в хук либе? (HookLib with anchors)
Вот такой хук получится:
@Hook(at = @At(point = InjectionPoint.METHOD_CALL, target = "readFromNBT"), returnCondition = ReturnCondition.ALWAYS)
Ну и дальше скопируй весь код из метода, кроме вызова супера readFromNBT.
 
5,018
47
783
Ща попробуем, никуда не уходи)
Ничего не изменилось, собственно. Рассчитывается хукнутый, сохраняется в файл ток ванильный. Я все классы, связанные с этим, уже перелазил в поисках этих заветных символов "32", которые надо изменить... . Не Нашел!
Короче говоря, после сохранения в файл сетаются ванильные максималки размеров, а не мои
 
Последнее редактирование:
3,005
192
592
Расскажи ка Махик, в чем проблема сделать так?
Делаешь к примеру через WorldEdit аддон или onBlockActivation / через ПКМ эвент или команду или хоть где, где можно получить сервер мир..
Потом вписываешь тот код, что есть в методе сохранения структуры?
Вроде бы из TileEntityStructure#save.
Расчитать нижний левый угол, верхний правый угол.
Нижний левы - это старт, а разница между верхним правым и нижнем левым - сайз.
Нужен takeBlocksFromWorld и writeTemplate..
 
5,018
47
783
Я не хочу писать никаких аддонов, делать еще один проект и производить так много действий для проблемы, которая в общем то, не критическая. Грубо говоря, я не хочу сильно запариваться над фигней. Сюда отписал, может кто поможет по моему костылю. В данном случае мне наплевать как хорошо будет работать, как будет выглядеть код. Мне главное чтоб работало, так как это создается сугубо для моего удобства.
 
5,018
47
783
Вроде бы из TileEntityStructure#save.
там не так просто. там сначала структура сохраняется по обычному, парсится в значения, сохраняется в нбт и только потом создается нбтфайл в который записывается это все. Цепочка потянется с кучей копираста...
 
1,038
57
229
Ну вот блин, Doc всё испортил, я только хотел мод написать))
 
3,005
192
592
я только хотел мод написать
Как минимум уже есть схематика.
Парсер уже был на форуме.
~
А так..
зачем то генерят большую структуру по кускам
но мне плевать, я хочу целиком
Судя по этим словам - ему плевать на всех, кто будет юзать мод.
 
5,018
47
783
Сколько же тут копипаста, час копировал, да..
Java:
if (!world.isRemote) {
    if (!playerIn.isSneaking()) {
        WorldServer worldserver = (WorldServer) world;
        MinecraftServer minecraftserver = world.getMinecraftServer();
        TemplateManager templatemanager = worldserver.getStructureTemplateManager();
        Template template = templatemanager.getTemplate(minecraftserver, new ResourceLocation("haHAA"));
        template.takeBlocksFromWorld(world, pos.up(), new BlockPos(15, 15, 15), true, Blocks.STRUCTURE_VOID);
        template.setAuthor("FuckUMaxik");
        boolean b = templatemanager.writeTemplate(minecraftserver, new ResourceLocation("haHAA"));
        System.out.println(">>> " + b);
    } else {
        WorldServer worldserver = (WorldServer)world;
        MinecraftServer minecraftserver = world.getMinecraftServer();
        TemplateManager templatemanager = worldserver.getStructureTemplateManager();
        Template template = templatemanager.get(minecraftserver, new ResourceLocation("haHAA"));
        PlacementSettings placementsettings = (new PlacementSettings()).setMirror(Mirror.NONE).setRotation(Rotation.NONE).setIgnoreEntities(true).setChunk(null).setReplacedBlock(null).setIgnoreStructureBlock(false);
        template.addBlocksToWorldChunk(world, pos.up(), placementsettings);
    }
}
Без шифта - сохранение.
С шифтом - загрузка.
Ага. Два метода выдрал из структуры. Я их видел и тоже самое мог бы и сам сделать. А регион выделять? А сохранять первый\второй блок(позицию) в WSD? Я же говорю, твой вариант слишком геморный. Попробуй пожалуйста помочь конкретно по проблеме, которая описана в вопросе.
 
7,099
324
1,509
of the mainkraft
А чего hohserg не предложил заюзать свои якоря в хук либе? (HookLib with anchors)
Потому, что я не смотрел особо че там у него и можно ли обойтись без копирования всего метода. А вообще идея хорошая

Макс, попробуй так
Java:
@Hook(at = @At(point = InjectionPoint.METHOD_CALL, target = "readFromNBT"), returnCondition = ReturnCondition.ALWAYS)
public static void readFromNBT(TileEntityStructure this1, NBTTagCompound compound){
    System.ouy.println("test")
    this1.setName(compound.getString("name"));
    this1.author = compound.getString("author");
    this1.metadata = compound.getString("metadata");
    int i = compound.getInteger("posX")
    int j = compound.getInteger("posY")
    int k = compound.getInteger("posZ")
    this1.position = new BlockPos(i, j, k);
    int l = compound.getInteger("sizeX")
    int i1 = compound.getInteger("sizeY")
    int j1 = compound.getInteger("sizeZ")
    this1.size = new BlockPos(l, i1, j1);
    //и так далее
}
Если так уже пробовал и не заработало, то скорее всего имя супер-метода отличается от имени обычно метода при вызове
 
5,018
47
783
Привет! Проблема все еще не решена. Помогите кто чем может. Я никак не могу найти пресловутый метод, который таки сохраняет 32х по максимуму.
Кратко диспозиция: хук работает, регион выделяется такой какой надо, расчитывается успешно, но сохраняется лишь ванильного макс.размера 32х.
 
5,018
47
783
Тик ток, тип топ.
Внимание всем. В общем, я сделал свой подобный инструмент, и он почти работает, за исключением того что не совсем!
Воообщем. Я для начала сделал свой инструмент выделения региона. Блок тут, блок тут, сохраняем в нбт.

Java:
public class GetPosEvent {


    public static int[] calcSize(World world) {
        SetPos wsd = SetPos.get(world);
        int xSize = wsd.x2 - wsd.x1;
        int ySize = wsd.y2 - wsd.y1;
        int zSize = wsd.z2 - wsd.z1;

        int[] size = {xSize, ySize, zSize};

        return size;

    }
  
    @SubscribeEvent
    public void getPosLeft(PlayerInteractEvent.LeftClickBlock e) {

        //e.getWorld().setBlockState(e.getPos(), e.getWorld().getBlockState(e.getPos()));
        if(e.getWorld().isRemote) {
            SetPos wsd = SetPos.get(e.getWorld());
            if(e.getItemStack().getItem() == Items.STICK) {

                wsd.x1 = e.getPos().getX();
                wsd.y1 = e.getPos().getY();
                wsd.z1 = e.getPos().getZ();

                System.out.println("pos1 " + wsd.x1 + " : " + wsd.y1 + " : " + wsd.z1);

            }
        }
    }

    @SubscribeEvent
    public void getPosRight(PlayerInteractEvent.RightClickBlock e) {
        if(e.getWorld().isRemote) {
            SetPos wsd = SetPos.get(e.getWorld());

            if(e.getItemStack().getItem() == Items.STICK) {
                wsd.x2 = e.getPos().getX();
                wsd.y2 = e.getPos().getY();
                wsd.z2 = e.getPos().getZ();

                System.out.println("pos2 " + wsd.x2 + " : " + wsd.y2 + " : " + wsd.z2);
                System.out.println("size " + Math.abs(this.calcSize(e.getWorld())[0]) + ":" +  Math.abs(this.calcSize(e.getWorld())[1]) + ":" +   Math.abs(this.calcSize(e.getWorld())[2]) );
            }
        }
    }


    public static class SetPos extends WorldSavedData {
        private static final String name = "wsdName";

        public int x1;
        public int y1;
        public int z1;

        public int x2;
        public int y2;
        public int z2;


        public SetPos(String name) {
            super(name);
        }

        @Override
        public void readFromNBT(NBTTagCompound nbt) {

            x1 = nbt.getInteger("x1");
            y1 = nbt.getInteger("y1");
            z1 = nbt.getInteger("z1");
            x2 = nbt.getInteger("x2");
            y2 = nbt.getInteger("y2");
            z2 = nbt.getInteger("z2");

        }

        @Override
        public NBTTagCompound writeToNBT(NBTTagCompound nbt) {

            nbt.setInteger("x1", x1);
            nbt.setInteger("y1", y1);
            nbt.setInteger("z1", z1);
            nbt.setInteger("x2", x2);
            nbt.setInteger("y2", y2);
            nbt.setInteger("z2", z2);


            return nbt;
        }

        public static SetPos get(World world) {
            MapStorage storage = world.getMapStorage();
            SetPos instance = (SetPos) storage.getOrLoadData(SetPos.class, name);
            if (instance == null) {
                instance = new SetPos(name);
                storage.setData(name, instance);
                instance.markDirty();
            }
            return instance;
        }
    }
}

Клик, клик, получаем выход:
[00:53:38] [main/INFO] [STDOUT]: [ru.lg.SovietMod.Event.GetPosEvent:getPosLeft:46]: pos1 -498 : 3 : -159
[00:53:41] [main/INFO] [STDOUT]: [ru.lg.SovietMod.Event.GetPosEvent:getPosRight:62]: pos2 -501 : 6 : -167
[00:53:41] [main/INFO] [STDOUT]: [ru.lg.SovietMod.Event.GetPosEvent:getPosRight:63]: size 3:3:8



Далее, я полез создавать команду, которая бы выполняла код сохранения этого региона в файл. Но он не сохраняет! Причем, сохранялка выводит что все успешно сохранено(в файл... где еп?)

Java:
public class CommandSave extends CommandBase {

    public static final String NAME = "save", USAGE = "/save <message>";

    @Override
    public String getName() {

        return this.NAME;
    }

    @Override
    public String getUsage(ICommandSender sender) {

        return this.USAGE;
    }
    @Override
    public int getRequiredPermissionLevel()
    {
        return 2;
    }

    @Override
    public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException {

        if (sender instanceof EntityPlayer) {

            if (args.length == 0) {

                throw new WrongUsageException(this.getUsage(sender));
            }     

            ITextComponent message = this.getChatComponentFromNthArg(sender, args, 0, !(sender instanceof EntityPlayer));
          
            World world = FMLCommonHandler.instance().getMinecraftServerInstance().getServer().getEntityWorld();
            EntityPlayer player = this.getCommandSenderAsPlayer(sender); 

            WorldServer worldserver = (WorldServer) world;
            MinecraftServer minecraftserver = world.getMinecraftServer();
            TemplateManager templatemanager = worldserver.getStructureTemplateManager();
            SetPos wsd = SetPos.get(player.getEntityWorld());

            Template template = templatemanager.getTemplate(minecraftserver, new ResourceLocation(message.getFormattedText()));
            template.takeBlocksFromWorld(world, new BlockPos(wsd.x1, wsd.y1, wsd.z1), new BlockPos(wsd.x2, wsd.y2, wsd.z2), true, Blocks.STRUCTURE_VOID);
            template.setAuthor("yyy");
          
            templatemanager.writeTemplate(minecraftserver, new ResourceLocation(message.getFormattedText()));
          
            boolean save = templatemanager.writeTemplate(minecraftserver, new ResourceLocation(message.getFormattedText()));
            System.out.println("Save? " + save);
          
          
        }
    }
}
Получаем вывод:
[00:53:46] [Server thread/INFO] [STDOUT]: [ru.lg.SovietMod.Command.CommandSave:execute:85]: >>> true


Но файла нет((
 
3,005
192
592
А как ты проверял?
Поиск по названию делал?
~
Тот код, что кидал - работает 100% и файл есть.
~
run\saves\New World\structures
~
Зачем тебе кстати координаты хранить в WSD ?
~
А почему у тебя код выполняется только на клиенте?
 
5,018
47
783
Это клиент? я думал это сервер... постоянно путаю. Файл есть, да. я АТшками снял приват и прописал свой путь крч, чтобы не парится.

Зачем тебе кстати координаты хранить в WSD ?
Я почему то подумал, что это пригодится. Лишним не будет...
Я возможно в будущем сделаю более продвинутый, чтобы несколько регов можно было кучей делать.
В общем файл есть, но он пустой всегда.
Ну не совсем пустой. В нех он выглядит вот так
Java:
1F 8B 08 00 00 00 00 00  00 00 4D 8D CD 0A C2 30
10 84 07 5A 6B 13 2F BE  91 97 D2 5B 8F F5 BE 86
55 97 D4 44 92 2D 48 9F  DE FE 21 0E CC E1 9B 19
18 0B 18 94 59 26 2E 00  2C FE C9 A0 E6 A0 A2 C2
79 E7 EA 36 44 E7 37 AA  51 D1 A8 CF 98 60 DB D1
F9 BE A3 8F 78 83 E3 9B  06 56 E5 75 63 71 6E 63
7A 70 43 4A 57 4E 59 62  28 60 5E 12 D8 25 BA 2B
70 B8 CC 97 A7 BF 7A 8D  BE BD 7C 9C A6 94 00 00
00
но так он выглядит везде. То есть все эти двоичные символы одинаковые в любом моем файле
 
Последнее редактирование:
3,005
192
592
Попробуй делать без своего "чудо" варианта.
Мб он как раз и косячит.
 
5,018
47
783
Сверху