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

Версия Minecraft
1.18.1
API
Forge
627
72
178
Какими способами можно предметам НЕ из своего мода добавить второй слой в зависимости от нбт булев-тега? С моделями и рендером на новых версиях максимально незнаком. В инете читал про 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());
627
72
178
Тема актуальна. За 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();
  }
}
 
Последнее редактирование:
7,099
324
1,510
Проблема в мерцании?
 
7,099
324
1,510
Самое простое - увеличить все квады по оси 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());
 
627
72
178
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,099
324
1,510
Выдели чистую функцию и мемоизируй ее, так будет проще отлаживать и понимать че происходит: читые функции, что мемоизирвоанные, что нет, всегда работают одинаково с одинаковыми аргументами, поэтому мемоизация для них просто оптимизация ценой памяти.

if (originalBakedModel != overrideModel)
return overrideModel;
Предполагаю, что этот кейс срабатывает
 
627
72
178
Предполагаю, что этот кейс срабатывает
не. проверял. он не влияет.
так будет проще отлаживать и понимать че происходит
если честно, мне даже неясно что тут дебажить можно), просто по какой-то причине модель то ли не успевает занестись в кэш до первой отрисовки, то ли что
 
627
72
178
есть только одна идея - где нибудь на стадии FMLClientSetupEvent заранее заносить все модели, и уже сразу в игре их использовать. говнокод или не? (херню сморозил, я там просто-напросто не получу нормальные объекты моделей из которых изначальные квады копирую)
 
Последнее редактирование:
627
72
178
решение оказалось элементарнейшее. 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 за совет по поводу мемоизации 🥰
 
Последнее редактирование:
7,099
324
1,510
Прикол может быть из-за того, что у тебя на одном месте несколько квадов одинаковых или почти одинаковых
 
627
72
178
У моей модели в классе есть коллекция с квадами, которую я возвращаю в getQuads, а заполняю я эту коллекцию в конструкторе модели, добавляя в неё все элементы из коллекции от getQuads родительской модели. Код есть во втором сообщении темы, я его изменил без использования иммутабельного листа, но суть та же самая
 
7,099
324
1,510
Если от двух моделей добавляешь, или дважды одно и то же, то в обном месте могут быть два квада
 
Сверху