summaryrefslogtreecommitdiff
path: root/src/main/java/lance5057/tDefense/util/TDModelLoader.java
blob: 5ecdacf32291e53db95fc50e7052449adc083a76 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
package lance5057.tDefense.util;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import javax.annotation.Nonnull;

import org.apache.commons.io.FilenameUtils;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import gnu.trove.map.hash.TIntObjectHashMap;
import lance5057.tDefense.core.tools.bases.ArmorCore;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.ICustomModelLoader;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.common.model.TRSRTransformation;
import slimeknights.tconstruct.library.TinkerRegistry;
import slimeknights.tconstruct.library.client.CustomTextureCreator;
import slimeknights.tconstruct.library.client.model.MaterialModel;
import slimeknights.tconstruct.library.client.model.MaterialModelLoader;
import slimeknights.tconstruct.library.client.model.ModelHelper;
import slimeknights.tconstruct.library.client.model.ModifierModel;
import slimeknights.tconstruct.library.client.model.ModifierModelLoader;
import slimeknights.tconstruct.library.client.model.ToolModel;
import slimeknights.tconstruct.library.client.model.format.AmmoPosition;
import slimeknights.tconstruct.library.client.model.format.ToolModelOverride;
import slimeknights.tconstruct.library.tools.IToolPart;

public class TDModelLoader implements ICustomModelLoader {

  public static String EXTENSION = ".td";

  // used to create only actually needed textures in the texturegenerator instead of ALL materials for all parts
  private static final Map<ResourceLocation, ArmorCore> modelItemMap = Maps.newHashMap();

  public static void addPartMapping(ResourceLocation resourceLocation, ArmorCore tool) {
    modelItemMap.put(resourceLocation, tool);
  }

  @Override
  public boolean accepts(ResourceLocation modelLocation) {
    return modelLocation.getResourcePath().endsWith(EXTENSION); // tinkertoolmodel extension. Foo.tcon.json
  }

  @Override
  public IModel loadModel(ResourceLocation modelLocation) {
    try {
      // Modelblock is used since our format is compatible to the vanilla format
      // and we don't have to write our own json deserializer
      // it also provides us with the textures
      Map<String, String> textures = ModelHelper.loadTexturesFromJson(modelLocation);
      ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transforms = ModelHelper.loadTransformFromJson(modelLocation);
      ImmutableList<ToolModelOverride> overrides = ModelHelper.loadToolModelOverridesFromJson(modelLocation);
      AmmoPosition ammoPosition = ModelHelper.loadAmmoPositionFromJson(modelLocation);
      Float[] rotations = ModelHelper.loadLayerRotations(modelLocation);

      if(rotations.length > 0 && textures.size() != rotations.length) {
        TinkerRegistry.log.error("Toolmodel {} has invalid layerrotation entry: Size should be {} but is {}; Skipping rotations.", modelLocation, textures.size(), rotations.length);
        rotations = new Float[0];
      }

      ImmutableList.Builder<ResourceLocation> defaultTextureListBuilder = ImmutableList.builder();
      List<MaterialModel> parts = Lists.newArrayList();
      List<MaterialModel> brokenParts = Lists.newArrayList();

      ArmorCore ArmorCore = modelItemMap.get(MaterialModelLoader.getReducedPath(modelLocation));

      for(Map.Entry<String, String> entry : textures.entrySet()) {
        String name = entry.getKey();
        try {
          int i;
          List<MaterialModel> listToAdd;

          if(name.startsWith("layer")) {
            i = Integer.valueOf(name.substring(5));
            listToAdd = parts;
          }
          else if(name.startsWith("broken")) {
            i = Integer.valueOf(name.substring(6));
            listToAdd = brokenParts;
          }
          // invalid entry, ignore
          else {
            TinkerRegistry.log.warn("Toolmodel {} has invalid texture entry {}; Skipping layer.", modelLocation, name);
            continue;
          }

          ResourceLocation location = new ResourceLocation(entry.getValue());
          MaterialModel partModel = new MaterialModel(ImmutableList.of(location));
          while(listToAdd.size() <= i) {
            listToAdd.add(null);
          }
          listToAdd.set(i, partModel);

          defaultTextureListBuilder.add(location);
          registerCustomTextures(i, location, ArmorCore);
        } catch(NumberFormatException e) {
          TinkerRegistry.log.error("Toolmodel {} has invalid texture entry {}; Skipping layer.", modelLocation, name);
        }
      }

      // create overrides
      for(ToolModelOverride override : overrides) {
        for(Map.Entry<String, String> entry : override.textures.entrySet()) {
          String name = entry.getKey();
          try {
            int i;
            TIntObjectHashMap<MaterialModel> mapToAdd;

            if(name.startsWith("layer")) {
              i = Integer.valueOf(name.substring(5));
              mapToAdd = override.partModelReplacement;
            }
            else if(name.startsWith("broken")) {
              i = Integer.valueOf(name.substring(6));
              mapToAdd = override.brokenPartModelReplacement;
            }
            // invalid entry, ignore
            else {
              TinkerRegistry.log.warn("Toolmodel {} has invalid texture override entry {}; Skipping layer.", modelLocation, name);
              continue;
            }

            ResourceLocation location = new ResourceLocation(entry.getValue());
            MaterialModel partModel = new MaterialModel(ImmutableList.of(location));
            mapToAdd.put(i, partModel);

            registerCustomTextures(i, location, ArmorCore);
          } catch(NumberFormatException e) {
            TinkerRegistry.log.error("Toolmodel {} has invalid texture entry {}; Skipping layer.", modelLocation, name);
          }
        }
      }

      // remove models/item/ and .tcon
      String toolName = FilenameUtils.removeExtension(modelLocation.getResourcePath().substring(12));
      IModel mods;
      ModifierModel modifiers = null;
      try {
        mods = ModelLoaderRegistry.getModel(ModifierModelLoader.getLocationForToolModifiers(modelLocation.getResourceDomain(), toolName));

        if(mods == null || !(mods instanceof ModifierModel)) {
          TinkerRegistry.log.trace(
              "Toolmodel {} does not have any modifiers associated with it. Be sure that the Tools internal name, the Toolmodels filename and the name used inside the Modifier Model Definition match!",
              modelLocation);
        }
        else {
          modifiers = (ModifierModel) mods;

          for(ToolModelOverride toolModelOverride : overrides) {
            if(toolModelOverride.modifierSuffix != null) {
              String modifierName = toolName + toolModelOverride.modifierSuffix;
              IModel extraModel = ModelLoaderRegistry.getModel(ModifierModelLoader.getLocationForToolModifiers(modelLocation.getResourceDomain(), modifierName));
              if(extraModel instanceof ModifierModel) {
                ModifierModel overriddenModifierModel = new ModifierModel();
                // fill in non-overridden modifiers
                for(Map.Entry<String, String> entry : modifiers.getModels().entrySet()) {
                  overriddenModifierModel.addModelForModifier(entry.getKey(), entry.getValue());
                }
                // overwrite overridden modifiers
                for(Map.Entry<String, String> entry : ((ModifierModel) extraModel).getModels().entrySet()) {
                  overriddenModifierModel.addModelForModifier(entry.getKey(), entry.getValue());
                }
                toolModelOverride.overrideModifierModel = overriddenModifierModel;
              }
            }
          }
        }
      } catch(Exception e) {
        TinkerRegistry.log.error(e);
        modifiers = null;
      }

      return new ToolModel(defaultTextureListBuilder.build(), parts, brokenParts, rotations, modifiers, transforms, overrides, ammoPosition);
    } catch(IOException e) {
      TinkerRegistry.log.error("Could not load multimodel {}", modelLocation.toString());
    }
    return ModelLoaderRegistry.getMissingModel();
  }

  private void registerCustomTextures(int i, ResourceLocation resourceLocation, ArmorCore ArmorCore) {
    if(ArmorCore == null) {
      CustomTextureCreator.registerTexture(resourceLocation);
    }
    else {
      for(IToolPart part : ArmorCore.getRequiredComponents().get(i).getPossibleParts()) {
        CustomTextureCreator.registerTextureForPart(resourceLocation, part);
      }
    }
  }

  @Override
  public void onResourceManagerReload(@Nonnull IResourceManager resourceManager) {

  }
}