Идея Ограничение блоков на чанк

iLapMbDev

Активный участник
Баллы
61
Имя в Minecraft
JaceTwice
Существует ли плагин, который ставит ограничение определенных блоков на чанк? Допустим, чтобы в одном чанке нельзя было ставить больше 6 солнечных панелей и т.п. Если есть, то подскажите название, а лучше поделитесь ссылочкой. Если нет, то кто смог бы написать, бесплатно или за денежное вознаграждение. Спасибо. Если что, выдел подобный плагин на wim.su, на старом Industrial.
 
Ради интереса сочинил на эту тему процедуру. Проверено - работает. Только не уверен, что нет более простого и элегантного способа это сделать. Интересует мнение специалистов.

@EventHandler
public void onSetBlock(BlockPlaceEvent event){
Player p = event.getPlayer();
Material limited = Material.GOLD_BLOCK; //лимитируемый блок
Block set = event.getBlockPlaced();
if(set.getType() != limited){ return; }
int maxnumber = 10; // лимит количества таких блоков на чанк
int number = 0;
Chunk checkchunk = set.getLocation().getChunk();
for (x = 0; x < 16; ){
for (y = 0; y < 128; ){
for (z = 0; z < 16; ){
Material check = checkchunk.getBlock(x, y, z).getType();
if(check.equals(limited)){number++;}
//log.info(x + " " + y + " " + z + " : " + check.toString());
z++;
}
y++;
}
x++;
}
if(number > maxnumber){event.setCancelled(true);p.sendMessage("Limit of this block exceed.");}
}
 
Последнее редактирование:
Ради интереса сочинил на эту тему процедуру. Проверено - работает. Только не уверен, что нет более простого и элегантного способа это сделать. Интересует мнение специалистов.

@EventHandler
public void onSetBlock(BlockPlaceEvent event){
Player p = event.getPlayer();
Material limited = Material.GOLD_BLOCK; //лимитируемый блок
Block set = event.getBlockPlaced();
if(set.getType() != limited){ return; }
int maxnumber = 10; // лимит количества таких блоков на чанк
int number = 0;
Chunk checkchunk = set.getLocation().getChunk();
for (x = 0; x < 16; ){
for (y = 0; y < 128; ){
for (z = 0; z < 16; ){
Material check = checkchunk.getBlock(x, y, z).getType();
if(check.equals(limited)){number++;}
//log.info(x + " " + y + " " + z + " : " + check.toString());
z++;
}
y++;
}
x++;
}
if(number > maxnumber){event.setCancelled(true);p.sendMessage("Limit of this block exceed.");}
}
Можешь оформить в полноценный рабочий плагин, желательно с конфигом (туда вносить блоки, и было бы не плохо ID)? Я заплачу.
 
Ради интереса сочинил на эту тему процедуру. Проверено - работает. Только не уверен, что нет более простого и элегантного способа это сделать. Интересует мнение специалистов.

@EventHandler
public void onSetBlock(BlockPlaceEvent event){
Player p = event.getPlayer();
Material limited = Material.GOLD_BLOCK; //лимитируемый блок
Block set = event.getBlockPlaced();
if(set.getType() != limited){ return; }
int maxnumber = 10; // лимит количества таких блоков на чанк
int number = 0;
Chunk checkchunk = set.getLocation().getChunk();
for (x = 0; x < 16; ){
for (y = 0; y < 128; ){
for (z = 0; z < 16; ){
Material check = checkchunk.getBlock(x, y, z).getType();
if(check.equals(limited)){number++;}
//log.info(x + " " + y + " " + z + " : " + check.toString());
z++;
}
y++;
}
x++;
}
if(number > maxnumber){event.setCancelled(true);p.sendMessage("Limit of this block exceed.");}
}
1. Высота чанка - 256
2. Перебор 65536 (16x16x256) блоков при установке каждой пОнели неплохо нагрузит сервер.
 
1. Высота чанка - 256
2. Перебор 65536 (16x16x256) блоков при установке каждой пОнели неплохо нагрузит сервер.
Согласен. Хотя перебор идет только при установке именно конкретного блока (конечно же, можно сделать не один, а набор блоков и лимитов). Ну, в общем, я попробовал на тестовом - вроде мгновенно считает. Не будут же они пытаться ставить эти блоки ежесекундно? Ну, возможно, в начале чуток переберут, а потом, "обжегшись" десяток раз, уже не будут постоянно пытаться поставить много блоков. И "нагрузка" будет достигать некоего пика лишь тогда, когда новички будут "учиться" местным особенностям.

Тем не менее, я не спорю. Потому ранее спросил у аудитории, нет ли более изящного способа подсчитать количество определенных блоков в чанке.

Разгрузить процесс можно, если слушать еще и ломание блоков. То есть, при достижении лимита блоков чанк вносить в некий список забаненных и в дальнейшем просто проверять, не входит ли чанк в этот список. А уже из этого списка убирать чанк тогда, когда сломан один лимитированный блок и в чанке их стало меньше максимума. Однако, спорный вопрос: что сильнее нагрузит сервер - дополнительный "слушатель" на ломание блоков или все-таки перебор всего чанка каждый раз, когда установлен блок определенного типа.

P.S. И, кстати, у меня в коде высота чанка равна 128. Цифру я взял, руководствуясь этим: http://jd.bukkit.org/rb/doxygen/d6/d90/interfaceorg_1_1bukkit_1_1Chunk.html
И, кстати, зря я так поступил. 🙂 Проверил, изменил.

Что ж, это натолкнуло меня на мысль, что в настройках неплохо бы указывать пределы отслеживания. Кому придет в голову ставить блоки выше 200, например? Ну и нефиг тогда проверять, правильно?

Надо сказать, что автор наверняка неточно выразил свою мысль и на самом деле речь не о чанке, а о некотором объеме. В таком случае можно проверять не чанк, а просто некий куб пространства вокруг блока, с заданным "радиусом".
 
Последнее редактирование:
"в одном чанке нельзя было ставить больше 6 солнечных панелей"
а нельзя это просто контролировать при установке блоков ?.. просто считать/хранить в базе их и запрещать в случае чего ... будет время реализую покажу, но пока не вижу применения этому плагину
 
"в одном чанке нельзя было ставить больше 6 солнечных панелей"
а нельзя это просто контролировать при установке блоков ?.. просто считать/хранить в базе их и запрещать в случае чего ... будет время реализую покажу, но пока не вижу применения этому плагину
Проблема в том, что при подсчете будет не хилая нагрузочка.
 
Проблема в том, что при подсчете будет не хилая нагрузочка.
с какого перепугу ?

вы меня не поняли !

реализуется так (под рукой эклипса нет поэтому могу насчет методов классов/интерфейсов баккита ошибаться):
public HashMap<Chunk,HashMap<Block,int>> КоличестваБлоковВЧанках;
затем в методе события
onBlockPlace(event){
ВЧанке = КоличестваБлоковВЧанках.Get(event.getPlayer().getLocation().getChunk());
int i = ВЧанке.Get(event.getBlock());
i++;
if(i>6)p.SendMessage("ЭЭЭЭ низя больше 6 блоков "+event.getBlock().GetName());
ВЧанке.Set(event.getBlock(),i);

}

никаких циклов !
все делается за одну итерацию
ненужно пересчитывать весь чанк , зачем ? в задаче этого не упоминалось !
единственное что эту структуру придется сериализовать, сохранять и загружать при перезапуске сервера
причем такая структура будет небольшой (декартово произведение блоков на "тронутые" чанки) если ориентироваться в ограничениях на один блок то еще проще и меньше
единственно что я б всетаки учел еще блокировку данных и использовал синхронизацию на случай если в одном чанке работают одновременно 10 человек и все одновременно поставят этот блок , но проблема решаема заменой HashMap на LinkedHashMap
 
Последнее редактирование:
с какого перепугу ?

вы меня не поняли !

реализуется так (под рукой эклипса нет поэтому могу насчет методов классов/интерфейсов баккита ошибаться):
public HashMap<Chunk,HashMap<Block,int>> КоличестваБлоковВЧанках;
затем в методе события
onBlockPlace(event){
ВЧанке = КоличестваБлоковВЧанках.Get(event.getPlayer().getLocation().getChunk());
int i = ВЧанке.Get(event.getBlock());
i++;
if(i>6)p.SendMessage("ЭЭЭЭ низя больше 6 блоков "+event.getBlock().GetName());
ВЧанке.Set(event.getBlock(),i);

}

никаких циклов !
все делается за одну итерацию
ненужно пересчитывать весь чанк , зачем ? в задаче этого не упоминалось !
единственное что эту структуру придется сериализовать, сохранять и загружать при перезапуске сервера
причем такая структура будет небольшой (декартово произведение блоков на "тронутые" чанки) если ориентироваться в ограничениях на один блок то еще проще и меньше
единственно что я б всетаки учел еще блокировку данных и использовал синхронизацию на случай если в одном чанке работают одновременно 10 человек и все одновременно поставят этот блок , но проблема решаема заменой HashMap на LinkedHashMap
Этот метод вызывает у меня сомнения насчет оптимальности использования ОЗУ. Но этот алгоритм можно использовать только при старте сервера, когда еще никто не ставил эти блоки.
 
Этот метод вызывает у меня сомнения насчет оптимальности использования ОЗУ. Но этот алгоритм можно использовать только при старте сервера, когда еще никто не ставил эти блоки.

Java сама по себе вызывает сомнение насчёт оптимальности использования ОЗУ, поэтому не нужно про это писать. Мегабайтом больше/Мегабайтом меньше - ничего не поменяется.

Всё что нужно для реализации данной проблемы - постепенно обходить чанки в различных тиках и вести подсчёт количества нужных блоков. Как только чанк будет считаться "расчитанным", то на таком чанке производим контроль изменения блоков: установка, ломание, взрывание. Никаких больших сложностей здесь нет, всё же здесь нужно - это правильная логика.

p.s. для всех объектов bukkit'а лучше делать различные врапперы, а не пользоваться оригинальными объектами. Т.е. очень сомнительно пользоваться оригинальными Chunk/Block/Location, в особенности если нет понимания полной работы Контейнеров, хешфункции, equals, и нет уверенности, что адрес всегда будет один и тот же.
Это единственное, в чём я увидел сомнение. Проще ChunkWrapper свой сделать, который будет иметь пару полей и переопределённые методы, чтобы можно было equals сделать с Chunk.
 
Этот метод вызывает у меня сомнения насчет оптимальности использования ОЗУ. Но этот алгоритм можно использовать только при старте сервера, когда еще никто не ставил эти блоки.
насчет памяти скажу: сколько по вашему чанков "открывают" игроки всего? давайте прикинем, что игроки открыли мир 5000х5000 это будет всего 97656 чанков, если уж так беспокоиться за память то применить простой массив типа
public int i[97656];
и в коде из координат чанка высчитывать позицию в массиве с инкрементом в этом случае JVM использует всего 97656*sizeof(int)4 = 390624 байта или 381 килобайт озу... это много ? а если массив байт то вообще 96 килобайт ...
по поводу использования лишь на свежих серверах , можно написать отдельную обработочку на любом языке которая "пробежит" за ночь по всем чанкам карты (вне сервера просто операция над файлами) и создаст базу заполнения (снимок сервера). либо и вправду постепенно обходить все чанки в параллельном потоке но это нагрузка на серв

Java сама по себе вызывает сомнение насчёт оптимальности использования ОЗУ, поэтому не нужно про это писать. Мегабайтом больше/Мегабайтом меньше - ничего не поменяется.

Всё что нужно для реализации данной проблемы - постепенно обходить чанки в различных тиках и вести подсчёт количества нужных блоков. Как только чанк будет считаться "расчитанным", то на таком чанке производим контроль изменения блоков: установка, ломание, взрывание. Никаких больших сложностей здесь нет, всё же здесь нужно - это правильная логика.

p.s. для всех объектов bukkit'а лучше делать различные врапперы, а не пользоваться оригинальными объектами. Т.е. очень сомнительно пользоваться оригинальными Chunk/Block/Location, в особенности если нет понимания полной работы Контейнеров, хешфункции, equals, и нет уверенности, что адрес всегда будет один и тот же.
Это единственное, в чём я увидел сомнение. Проще ChunkWrapper свой сделать, который будет иметь пару полей и переопределённые методы, чтобы можно было equals сделать с Chunk.

по поводу враперов я всеж не понял зачем, но звучит умно ) пожалуй возьму на заметку, тем более я новичек как в джаве так и в бакките , ранее на шарпе на плюсах писал 🙂
правда пока не до конца понял зачем. Может из за того что неизвестно как реализована equals у класса в бакките?
 
Java сама по себе вызывает сомнение насчёт оптимальности использования ОЗУ, поэтому не нужно про это писать. Мегабайтом больше/Мегабайтом меньше - ничего не поменяется.

Всё что нужно для реализации данной проблемы - постепенно обходить чанки в различных тиках и вести подсчёт количества нужных блоков. Как только чанк будет считаться "расчитанным", то на таком чанке производим контроль изменения блоков: установка, ломание, взрывание. Никаких больших сложностей здесь нет, всё же здесь нужно - это правильная логика.

p.s. для всех объектов bukkit'а лучше делать различные врапперы, а не пользоваться оригинальными объектами. Т.е. очень сомнительно пользоваться оригинальными Chunk/Block/Location, в особенности если нет понимания полной работы Контейнеров, хешфункции, equals, и нет уверенности, что адрес всегда будет один и тот же.
Это единственное, в чём я увидел сомнение. Проще ChunkWrapper свой сделать, который будет иметь пару полей и переопределённые методы, чтобы можно было equals сделать с Chunk.
Таки у Location есть equals, так что можно использовать его. А чанка точно нет, у блока вроде был.
Проблема в контроле эвентами в том что ТС хочет на котёл, а там половину вещей эвентами не покрывается.
 
Таки у Location есть equals, так что можно использовать его. А чанка точно нет, у блока вроде был.
Проблема в контроле эвентами в том что ТС хочет на котёл, а там половину вещей эвентами не покрывается.
Location отваливается в случае перезгрузки мира.
 
Назад
Верх