Follow along with the video below to see how to install our site as a web app on your home screen.
Примечание: This feature may not be available in some browsers.
world.setBlockState (если структура содержит пустоты)Если тебе нужно установить ровно 1 блок (и ничего больше) - то там не чего оптимизировать стандартными методами.world.setBlockState() ; не вариант он устонавливает 1 блок за тоже время за которое Template 1 структуру и возникает вопрос каккакатьставить быстро
Template - проходятся в цикле, рассчитывает поворот, отражение и много раз вызывают world.setBlockState(), оно физически не может быть быстрее простого world.setBlockState()Странно, просто делал черезоно физически не может быть быстрее простогоworld.setBlockState()
world.setBlockState() и одна и таже структура в Template размещалась за ~20ms а через мой цикл за ~1000ms public IBlockState getBS(int x, int y, int z) {
return blockStates[z][y][x];
}
@Override
public void please(World world, int xC, int yC, int zC) { // При установке вызывается только этот метод
for (int z = 0; z != blockStates.length; z++) {
for (int y = 0; y != blockStates[z].length; y++) {
for (int x = 0; x != blockStates[z][y].length; x++) {
world.setBlockState(new BlockPos(xC + x, yC + y, zC + z), getBS(x, y, z));
}
}
}
}
world.setBlockState (если структура содержит пустоты)Я знаю как ещё улучшить этот код. Вместо массива воспользоваться LinkedList<Triplet<Integer, Integer, Integer>>, тогда точно ускорится в 15 раз.естественно оно и будет тормозить
Наилучший вариант - писать свою установку в мир, как уже было сказано выше, ибо сам майн делает это тоже достаточно медленно.и возникает вопрос каккакатьставить быстро
Как 1 из вариантов исправления .. Хотя можно обойтись обычным int[] и бинарной математикойтогда точно ускорится в 15 раз.
3) Куча лишних вызововworld.setBlockState(если структура содержит пустоты)
O(n) на чтение, массив же O(1) (и ArrayList тоже, кстати). Хотя, в данном случае, он не отличается по скорости от связанного списка (и мб даже медленнее), ввиду особенностей хранения многомерных массивов ("первый" работает как надо - хранит все ссылки на массивы последовательно, но вот дальше происходит чухня, из-за которой и созданы "deep" методы в Arrays).public class CustomGenStructure {
private static final List<String> rawStructures = new ArrayList<>();
private static final Map<String, TRAStructure> structures = new HashMap<>();
public static void put(String name) {
rawStructures.add(name);
}
public static void register() {
for (String s : rawStructures) {
structures.put(s, new TRAStructure(s));
}
rawStructures.clear();
}
public static void please(World world, int x, int y, int z, String name) {
if (structures.containsKey(name)) {
structures.get(name).please(world, x, y, z);
} else {
throw new RuntimeException("invalid structure name: " + name);
}
}
public static void registerOrPlease(World world, int x, int y, int z, String name) {
if (structures.containsKey(name)) {
structures.get(name).please(world, x, y, z);
} else {
TRAStructure structure = new TRAStructure(name);
structures.put(name, structure);
structure.please(world, x, y, z);
}
}
}
public class TRAStructure {
protected final BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos();
protected final LinkedList<BlockInfo> blocks = new LinkedList<>();
public TRAStructure(String structureName) {
NBTTagCompound structureNBT = readStructureAsName(structureName);
NBTTagList palette = structureNBT.getTagList("palette", 10);
NBTTagList blocksNBT = structureNBT.getTagList("blocks", 10);
int air = -1;
IBlockState[] blocksNames = new IBlockState[palette.tagCount()];
for (int i = 0; i != palette.tagCount(); i++) {
blocksNames[i] = getBlockByString(palette.getCompoundTagAt(i).getString("Name")).getDefaultState();
if (getBlockByString(palette.getCompoundTagAt(i).getString("Name")) == Blocks.AIR) {
air = i;
}
}
for (int i = 0; i != blocksNBT.tagCount(); i++) {
NBTTagCompound compound = blocksNBT.getCompoundTagAt(i);
NBTTagList pos = compound.getTagList("pos", 3);
int state = compound.getInteger("state");
if (state != air) {
blocks.add(new BlockInfo(pos.getIntAt(0), pos.getIntAt(1), pos.getIntAt(2), blocksNames[state]));
}
}
}
private static NBTTagCompound readStructureAsName(String structureName) {
InputStream inputstream = MinecraftServer.class.getResourceAsStream("/assets/" + Referense.MODID + "/structures/" + structureName + ".nbt");
try {
assert inputstream != null;
return CompressedStreamTools.readCompressed(inputstream);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(inputstream);
}
}
public void please(World world, int x, int y, int z) {
for (BlockInfo block : blocks) {
world.setBlockState(mutablePos.setPos(block.x + x, block.y + y, block.z + z), block.state);
}
}
protected Block getBlockByString(String block) {
ResourceLocation resourcelocation = new ResourceLocation(block);
if (!Block.REGISTRY.containsKey(resourcelocation))
{
throw new RuntimeException(block);
}
else
{
return Block.REGISTRY.getObject(resourcelocation);
}
}
protected static class BlockInfo {
public final int x;
public final int y;
public final int z;
public final IBlockState state;
public BlockInfo(int x, int y, int z, IBlockState state) {
this.x = x;
this.y = y;
this.z = z;
this.state = state;
}
}
}
и на счёт этого можно ли удалять чанки и имеет ли смысл делать это на постоянной основе т.к.+ На этапе генерации (не путать с популяцией) можно в чанк-праймер ставить блоки очень быстро, возможно тебе подойдет этот вариант
Это обычными модами не исправить - добро пожаловать в переписывание mojang-кода с помощью asm-a или как-то ещеОстаётся лишь вопрос установки. - об этом я уже говорил ранее: сам майн устанавливает блоки достаточно медленно;
Phosphor +- исправляет этоПрограмма собственно в первую очередь нужна чтобы сообщить машине, что она должна делать, а не человеку ... Так что покрыть документацией для себя будущего - и ладноЕдинственный минус - читать массив человеку не очень удобно.
В этом случае подойдет ChunkPrimer (писал выше). Так же в твоем случае можно 1 раз создать чанк-шаблон - и потом замещать копией этого чанка уже существующий чанк в миремне нужно очищать область 16 на 16 чанков и заново расставлять структуры
ExtendedBlockStorage ebs = world.getChunkFromBlockCoords(pos).getBlockStorageArray()[pos.getY() >> 4];
if (ebs != Chunk.NULL_BLOCK_STORAGE) ebs.set(pos.getX() & 15, pos.getY() & 15, pos.getZ() & 15, state);
Оно так же не подходит для чанков, которые уже были отправлены клиенту, тк оно обходит трекер измененийПоэтому я юзаю данный метод лишь для замены однотипных блоков.