Лучшая структура данных для хранения 2048 тегов предметов Minecraft?

В контексте, я работаю над модом Minecraft (1.21, то есть Java 21), цель которого:

  1. Используйте компонент данных max_stack_size для управления очевидным максимальным размером стека по умолчанию для элементов простым способом настройки. Чтобы элементы отображались по умолчанию с максимальным размером стека N, просто добавьте элемент в max_stack_size_N.json, а логика тега элемента сделает все остальное.
  2. Разорвите жестко запрограммированное ограничение 99 на максимальный размер стека на куски и замените его чем-то более удобным.

Я достиг этих двух целей для N=2ˣ, индивидуально определив, назначив прослушиватель и проверив каждый тег на каждую степень двойки.


public class ModTags{
public static final TagKey<Item> IS_STACK_SIZE_1 = createTag("stack_size_1" );
public static final TagKey<Item> IS_STACK_SIZE_2 = createTag("stack_size_2" );  
public static final TagKey<Item> IS_STACK_SIZE_2 = createTag("stack_size_4" );  
[...]
public static final TagKey<Item> IS_STACK_SIZE_2048 = createTag("stack_size_2048");

[...]
addReloadListener("stack_size_1"   );
addReloadListener("stack_size_2"   );
addReloadListener("stack_size_4"   );
[...]
addReloadListener("stack_size_2048");
}}
@Mixin(ItemStack.class)
public abstract class ItemStack_SizeMixin implements ComponentHolder, FabricItemStack {
[...]
@Inject(method = "getMaxCount", at = @At("HEAD"))
    private void updateMaxStackSizeWithTag(CallbackInfoReturnable<Integer> cir){
        ItemStack thisAsStack = (ItemStack)(Object) this;
        
        if      ( thisAsStack.isIn(ModTags.Items.IS_STACK_SIZE_2048)) ChangeStackSize(thisAsStack, 2048 );
        else if ( thisAsStack.isIn(ModTags.Items.IS_STACK_SIZE_1024)) ChangeStackSize(thisAsStack, 1024 );
[...]
}
}

Стратегия, которая, как я знал, не будет масштабироваться, когда я ее выберу, но наивность которой позволит легко кодировать остальную логику мода, проверьте. Я надеялся, что за то время, которое мне понадобится, чтобы удовлетворительно исправить все остальное, я накопим ноу-хау, чтобы заменить это лучшей системой. Что ж, насколько я могу судить, это время пришло.

А у меня точно не так: мой вопрос,

Как лучше всего систематически определять, хранить и проверять теги предметов Minecraft 2048? Ради людей, которые действительно хотят, чтобы max_stack_size был равен 372?

Я уже пробовал реализовать его как ArrayList, и это постоянно вызывало stackOverflows. Кроме того, у меня просто нет знаний Java, чтобы иметь представление.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
84
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, первое, что вам следует задуматься: «Действительно ли мне нужно, чтобы люди могли выбирать размер стека 1837?». Какую выгоду получит игрок, выбрав такое произвольное число? То, что вы можете, не означает, что вы должны.

Игроки привыкли к стекам из 1, 16 и 64, поэтому, по своей наивности, я бы сказал: придерживайтесь степеней двойки, этого более чем достаточно. Мало того, это облегчает вашу жизнь, а также жизнь игрока, давая ему меньше бремени выбора. (Я рискую и говорю, что игроков вообще не волнует разный размер стека. Они, вероятно, все равно выбирают максимально возможный размер...)

При этом, имея дело с повторным созданием и чтением объектов, рекомендуется использовать циклы и, возможно, карту, на которой вы можете легко хранить объекты одного и того же типа.

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

Я не в курсе моддинга Minecraft, но думаю, что большая часть кода состоит из static переменных и методов. Кроме того, я не уверен на 100 %, как работает thisAsStack.isIn, но попытаюсь дать вам отправную точку, как обобщить ваш код и сделать его масштабируемым. Итак, в итоге я бы предложил следующее:

public class ModTags {
    /**
     * Allows for stack sizes up to 2^11 = 2048
     */
    private static final Integer MAX_POWER_OF_TWO = 11;
    public static final Map<Integer, TagKey<Item>> STACK_SIZES;

    static {
        Map<Integer, Object> tmpMap = new HashMap<>();
        for(int i = 0; i <= MAX_POWER_OF_TWO; i++) {
            int stackSize = 1 << i;
            String tagName = "stack_size_" + i;
            tmpMap.put(stackSize, createTag(tagName));
            addReloadListener(tagName);
        }
        STACK_SIZES = Collections.unmodifiableMap(tmpMap);
    }
    ...
}

и ваш класс полезности:

...
private void updateMaxStackSizeWithTag(CallbackInfoReturnable<Integer> cir){
    ItemStack thisAsStack = (ItemStack)(Object) this;
    ModTags.STACK_SIZES.entrySet().stream()
        .filter(entry -> thisAsStack.isIn(entry.getValue()))
        .findFirst()
        .map(Map.Entry::getKey)
        .ifPresentOrElse(stackSize -> ChangeStackSize(thisAsStack, stackSize), () -> /* Handle not found here */);
}
            

Благодаря этому у вас есть общий способ добавления размеров стека со степенью двойки и выполнения всей регистрации и обновления в несколько строк. Больше не нужно создавать сотни подобных констант.

Опять же, поскольку я не уверен на 100%, как все работает в вашем коде, я надеюсь, что смогу дать вам хотя бы основу для работы.

Вы правы: игрокам определенно не нужен 1837, а степень двойки будет наиболее интересной. Но причина, по которой мне нужны все цифры, заключается в том, чтобы дать возможность шутникам, не требующим особых усилий, сложить все до 69, 132, 420 или чего-то еще в своем пакете данных для личного использования, оставив меня в стороне. По моему мнению, было бы лучше иметь номера в наличии и никогда не нуждаться в них, чем когда-либо иметь дело с запросами на добавление номера.

AnDrew the Awesome 14.07.2024 16:08

Еще спасибо. Думаю, я понимаю весь этот код и обязательно попытаюсь его использовать. Я полон надежд и отчитаюсь, когда получу что-то, что скомпилируется. Еще раз спасибо.

AnDrew the Awesome 14.07.2024 16:10

Сразу понял, что жалуется. Это конечно не корректно, но это ни сюда, ни сюда по поводу заданного мной вопроса. И на то, что я спросил, это определенно идеальный ответ. Спасибо.

AnDrew the Awesome 14.07.2024 16:24

Другие вопросы по теме