Слой текстуры предмета от NBT

Версия Minecraft
1.18.1
API
Forge
515
58
150
Какими способами можно предметам НЕ из своего мода добавить второй слой в зависимости от нбт булев-тега? С моделями и рендером на новых версиях максимально незнаком. В инете читал про Baked модели, но не особо понял что да как мне нужно. Может кто поподробнее рассказать? Или привести пример каких нибудь модов где это реализовано. Пожалуйста, не тинкерс констракт, закопаюсь в слоях абстракции..
 
Последнее редактирование:
Решение
Самое простое - увеличить все квады по оси Z на маленькое, но достаточное значение и сдвинуть вполовину этого по той же оси.
Проще всего это сделать при помощи Endothermic:
Java:
List<BakedQuad> quads = ...;
List<BakedQuad> fixedQuads = quads.stream()
    .map(LazyUnpackedQuad::apply)
    .map(q->q.scale(1, 1, 1.0015))
    .map(q->q.translate(0, 0, -0.0015/2))
    .map(LazyUnpackedQuad::toBakedQuad)
    .collect(toList());
515
58
150
Тема актуальна. За 2 недели более-менее разобрался, набросал вроде как оптимизированный код (раз клиент не умирает в агонии от прогрузки моделей - думаю норм)
Только осталась одна большая проблема, с которой я никак не могу разобраться. Брал реализацию наложенного слоя из мода SaltyMod, и столкнулся с такой проблемой отображения второго слоя: знает кто-нибудь как решить? может через Transformation что-то сделать? квады самого предмета добавлял, беря напрямую BakedModel::getQuads у дефолтной модели из ModelBakeEvent
Java:
  @SubscribeEvent
  public static void modelBakeEvent(ModelBakeEvent event) {
    for (Item item : ATMIntegrations.VALID_ITEMS) {
      ModelResourceLocation itemLocation = ForgeModelBakery.getInventoryVariant(ForgeRegistries.ITEMS.getKey(item).toString());
      BakedModel existingModel = event.getModelRegistry().get(itemLocation);
      if (existingModel != null) {
        /**здеся**/ATMItemModel model = new ATMItemModel(existingModel);
        event.getModelRegistry().put(itemLocation, model);
      } else {
        ATMIntegrations.LOGGER.error(itemLocation + " model is missing!");
      }
    }
  }
Java:
 public ATMItemModel(BakedModel model) {
    this.parentModel = model;
    /**здеся**/addQuads(model.getQuads(null, null, null));
  }

  public void addQuads(List<BakedQuad> collection) {
    ImmutableList.Builder builder = ImmutableList.builder();
    builder.addAll(quads);
    builder.addAll(collection);
    quads = builder.build();
  }
квады с этой текстурой добавляю в модель тут:
Java:
public class ATMItemOverrides extends ItemOverrides {
  public static final Int2ObjectMap<BakedModel> MODELS_CACHE = new Int2ObjectOpenHashMap<>();
  public static final Minecraft mc = Minecraft.getInstance();

  @Override
  public BakedModel resolve(BakedModel originalBakedModel, ItemStack stack, ClientLevel level, LivingEntity entity, int p_173469_) {
    int hash = calcHash(stack);
    if (!MODELS_CACHE.containsKey(hash)) {
      ATMItemModel newModel = new ATMItemModel(originalBakedModel);
      if (ATMTagContainer.isAmethyst(stack))
        /**здеся**/newModel.addQuads(ItemLayerModel.getQuadsForSprite(1, mc.getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(ATMModClientEvents.SPRITES_MAP.get("sword")), Transformation.identity()));
      return MODELS_CACHE.put(hash, newModel);
    }
    return MODELS_CACHE.getOrDefault(hash, originalBakedModel);
  }

  public static int calcHash(ItemStack stack) {
    return (stack.getItem().getRegistryName().toString() + ATMTagContainer.isAmethyst(stack)).hashCode();
  }
}
 
Последнее редактирование:
515
58
150
Это потом отладить всё можно. На трёхмерные модели я не планирую свою модель вешать, насчёт другого разрешения - не знаю, увидим. позже можем скрины скину)
 
7,050
319
1,477
Проблема в мерцании?
 
515
58
150
Да. В нём. Голову ломаю долго, нет идей как исправить. еще строить квады из базовой текстуры пробовал, ситуация не сильно меняется, всё равно есть мерцание на верхней грани модели
 
7,050
319
1,477
Самое простое - увеличить все квады по оси Z на маленькое, но достаточное значение и сдвинуть вполовину этого по той же оси.
Проще всего это сделать при помощи Endothermic:
Java:
List<BakedQuad> quads = ...;
List<BakedQuad> fixedQuads = quads.stream()
    .map(LazyUnpackedQuad::apply)
    .map(q->q.scale(1, 1, 1.0015))
    .map(q->q.translate(0, 0, -0.0015/2))
    .map(LazyUnpackedQuad::toBakedQuad)
    .collect(toList());
 
515
58
150
Спасибо, попробую как буду за компом. Только у меня еще мысля появилась сделать это не через прямой сдвиг квадов, а через Transformation последним аргументом в ItemLayerModel::getQuadsForSprite
 
515
58
150
Большое спасибо @hohserg! Работает без всяких проблем.
Java:
float delta = 0.0015f;
Transformation transformation = TransformationHelper.toTransformation(new ItemTransformation(new Vector3f(), new Vector3f(-delta / 2, -delta / 2, -delta / 2), new Vector3f(1 + delta, 1 + delta, 1 + delta)));
 
515
58
150
UP! @hohserg, не знаешь случаем, как можно исправить проблему, что модель до первого отображения не успевает сбилдиться и отображается отсутствующей текстурой? Вообще не представляю, как это исправить можно. Насколько помню, такая проблема появилась после внедрении мемоизации в код.
Java:
  @Override
  @SuppressWarnings("deprecation")
  public BakedModel resolve(BakedModel originalBakedModel, ItemStack stack, ClientLevel level, LivingEntity entity, int p_173469_) {
    BakedModel overrideModel = overrides.resolve(originalBakedModel, stack, level, entity, p_173469_);
    if (originalBakedModel != overrideModel)
      return overrideModel;
    int hash = calcHash(stack);
    if (!MODELS_CACHE.containsKey(hash)) {
      ATMItemModel newBakedModel = new ATMItemModel(originalBakedModel);
      if (ATMTagContainer.isAmethyst(stack)) {
        float delta = 0.0015f;
        newBakedModel.addQuads(ItemLayerModel.getQuadsForSprite(1, atlas.apply(resolveSprite(stack.getItem())), TransformationHelper.toTransformation(new ItemTransform(new Vector3f(), new Vector3f(-delta / 2, -delta / 2, -delta / 2), new Vector3f(1 + delta, 1 + delta, 1 + delta)))));
      }
      return MODELS_CACHE.put(hash, newBakedModel);
    }
    return MODELS_CACHE.getOrDefault(hash, originalBakedModel);
  }
}
 
7,050
319
1,477
Выдели чистую функцию и мемоизируй ее, так будет проще отлаживать и понимать че происходит: читые функции, что мемоизирвоанные, что нет, всегда работают одинаково с одинаковыми аргументами, поэтому мемоизация для них просто оптимизация ценой памяти.

if (originalBakedModel != overrideModel)
return overrideModel;
Предполагаю, что этот кейс срабатывает
 
515
58
150
Предполагаю, что этот кейс срабатывает
не. проверял. он не влияет.
так будет проще отлаживать и понимать че происходит
если честно, мне даже неясно что тут дебажить можно), просто по какой-то причине модель то ли не успевает занестись в кэш до первой отрисовки, то ли что
 
515
58
150
есть только одна идея - где нибудь на стадии FMLClientSetupEvent заранее заносить все модели, и уже сразу в игре их использовать. говнокод или не? (херню сморозил, я там просто-напросто не получу нормальные объекты моделей из которых изначальные квады копирую)
 
Последнее редактирование:
515
58
150
решение оказалось элементарнейшее. MODELS_CACHE.put возвращает null, но модель в кэш добавлял, в итоге модель не прорисовывалась, если попадала под кейс !MODELS_CACHE.containsKey(hash). сделал так
Java:
if (!MODELS_CACHE.containsKey(hash)) {
      BakedModel model = getModel(originalBakedModel, stack);
      MODELS_CACHE.put(hash, model);
      return model;
    }
и все работает.
вывод: возвращать Map#put - плохая затея :\
спасибо @hohserg за совет по поводу мемоизации 🥰
 
Последнее редактирование:
515
58
150
UP! Знает кто, из-за чего может быть слишком яркий foil-эффект от зачарования на предмете? Такая проблема только на предметах, модели которых я реплейснул своей.
 
7,050
319
1,477
Прикол может быть из-за того, что у тебя на одном месте несколько квадов одинаковых или почти одинаковых
 
515
58
150
не знаю. вроде не должно быть. как смогу - продебажу созданием единичного набора квадов каждый тик, чтоб они точно не складывались
 
515
58
150
У моей модели в классе есть коллекция с квадами, которую я возвращаю в getQuads, а заполняю я эту коллекцию в конструкторе модели, добавляя в неё все элементы из коллекции от getQuads родительской модели. Код есть во втором сообщении темы, я его изменил без использования иммутабельного листа, но суть та же самая
 
7,050
319
1,477
Если от двух моделей добавляешь, или дважды одно и то же, то в обном месте могут быть два квада
 
Сверху