Merge remote-tracking branch 'origin/master'

This commit is contained in:
modmuss50 2018-12-28 22:00:45 +00:00
commit 8c5c87466f
13 changed files with 687 additions and 3 deletions

View file

@ -26,7 +26,7 @@ targetCompatibility = 1.8
archivesBaseName = "fabric"
def baseVersion = "0.1.2"
def baseVersion = "0.1.3"
def mcVersion = "18w50a"
def ENV = System.getenv()
@ -38,7 +38,7 @@ minecraft {
dependencies {
minecraft "com.mojang:minecraft:$mcVersion"
mappings "net.fabricmc:yarn:$mcVersion.59"
mappings "net.fabricmc:yarn:$mcVersion.64"
modCompile "net.fabricmc:fabric-loader:0.3.0.74"
}

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2016, 2017, 2018 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.api.client.model;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.resource.ResourceManager;
import java.util.function.Consumer;
@FunctionalInterface
public interface ModelAppender {
void appendAll(ResourceManager manager, Consumer<ModelIdentifier> out);
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2016, 2017, 2018 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.api.client.model;
import net.fabricmc.fabric.impl.client.model.ModelLoadingRegistryImpl;
import net.minecraft.resource.ResourceManager;
import java.util.function.Function;
public interface ModelLoadingRegistry {
ModelLoadingRegistry INSTANCE = ModelLoadingRegistryImpl.INSTANCE;
/**
* Register a model appender, which can request loading additional models.
*
* @param appender
*/
void registerAppender(ModelAppender appender);
/**
* Register a ModelResourceProvider supplier.
*
* @param providerSupplier The ModelResourceProvider supplier, instantiated with every ModelLoader.
*/
void registerResourceProvider(Function<ResourceManager, ModelResourceProvider> providerSupplier);
/**
* Register a ModelVariantProvider supplier.
*
* @param providerSupplier The ModelVariantProvider supplier, instantiated with every ModelLoader.
*/
void registerVariantProvider(Function<ResourceManager, ModelVariantProvider> providerSupplier);
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2016, 2017, 2018 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.api.client.model;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.util.Identifier;
/**
* The model loading context used during model providing.
*/
public interface ModelProviderContext {
/**
* Load a model using a {@link Identifier}, {@link ModelIdentifier}, ...
*
* Please note that the game engine keeps track of circular model loading calls on its own.
*
* @param id The model identifier.
* @return The UnbakedModel. Can return a missing model if it's not present!
*/
UnbakedModel loadModel(Identifier id);
}

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2016, 2017, 2018 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.api.client.model;
public class ModelProviderException extends Exception {
public ModelProviderException(String s) {
super(s);
}
public ModelProviderException(String s, Throwable t) {
super(s, t);
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2016, 2017, 2018 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.api.client.model;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.util.Identifier;
/**
* Interface for model resource providers.
*
* Model resource providers hook the loading of model *files* from the resource tree;
* that is, in vanilla, it handles going from "minecraft:block/stone" to a
* "assets/minecraft/models/block/stone.json" file.
*
* This is where you want to add your own custom model formats.
*
* As providers are instantiated with a new provider, it is safe
* (and recommended!) to cache information inside a loader.
*
* Keep in mind that only *one* ModelResourceProvider may respond to a given model
* at any time. If you're writing, say, an OBJ loader, this means you could
* easily conflict with another OBJ loader unless you take some precautions,
* for example:
*
* a) Only load files with a mod-suffixed name, such as .architect.obj,
* b) Only load files from an explicit list of namespaces, registered elsewhere.
*/
@FunctionalInterface
public interface ModelResourceProvider {
/**
* @param resourceId The resource identifier to be loaded.
* @return The loaded UnbakedModel, or null if this ModelResourceProvider doesn't handle a specific Identifier
* (or if there was no error!).
*/
/* @Nullable */ UnbakedModel loadModelResource(Identifier resourceId, ModelProviderContext context) throws ModelProviderException;
}

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2016, 2017, 2018 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.api.client.model;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.util.Identifier;
/**
* Interface for model variant providers.
*
* Model variant providers hook the resolution of ModelIdentifiers. In vanilla, this is
* the part where a "minecraft:stone#normal" identifier triggers the loading of a
* "minecraft:models/stone" model ({@link ModelResourceProvider} handles the later step).
*
* The most common use of this is to cooperate with a {@link ModelAppender}, but it can
* also allow you to add your own block- or item-state formats. To trigger the loading
* of another model, use the passed {@link ModelProviderContext}.
*
* As every model loading is instantiated with a new provider, it is safe
* (and recommended!) to cache information.
*
* Keep in mind that only *one* ModelVariantProvider may respond to a given model
* at any time.
*/
@FunctionalInterface
public interface ModelVariantProvider {
/**
* @param modelId The model identifier, complete with variant.
* @return The loaded UnbakedModel, or null if this ModelVariantProvider doesn't handle a specific Identifier
* (or if there was no error!).
*/
/* @Nullable */ UnbakedModel loadModelVariant(ModelIdentifier modelId, ModelProviderContext context) throws ModelProviderException;
}

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2016, 2017, 2018 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.impl.client.model;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.util.Identifier;
public interface ModelLoaderHooks {
public void fabric_addModel(ModelIdentifier id);
public UnbakedModel fabric_loadModel(Identifier id);
}

View file

@ -0,0 +1,187 @@
/*
* Copyright (c) 2016, 2017, 2018 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.impl.client.model;
import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.client.model.*;
import net.fabricmc.loader.launch.common.FabricLauncherBase;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
public class ModelLoadingRegistryImpl implements ModelLoadingRegistry {
private static final boolean DEBUG_MODEL_LOADING = FabricLauncherBase.getLauncher().isDevelopment()
|| Boolean.valueOf(System.getProperty("fabric.debugModelLoading", "false"));
@FunctionalInterface
private static interface CustomModelItf<T> {
UnbakedModel load(T obj) throws ModelProviderException;
}
public static class LoaderInstance implements ModelProviderContext {
private final Logger logger;
private final ResourceManager manager;
private final List<ModelVariantProvider> modelVariantProviders;
private final List<ModelResourceProvider> modelResourceProviders;
private final List<ModelAppender> modelAppenders;
private ModelLoader loader;
private LoaderInstance(ModelLoadingRegistryImpl i, ModelLoader loader, ResourceManager manager) {
this.logger = ModelLoadingRegistryImpl.LOGGER;
this.loader = loader;
this.manager = manager;
this.modelVariantProviders = i.variantProviderSuppliers.stream().map((s) -> s.apply(manager)).collect(Collectors.toList());
this.modelResourceProviders = i.resourceProviderSuppliers.stream().map((s) -> s.apply(manager)).collect(Collectors.toList());
this.modelAppenders = i.appenders;
}
@Override
public UnbakedModel loadModel(Identifier id) {
if (loader == null) {
throw new RuntimeException("Called loadModel too late!");
}
return ((ModelLoaderHooks) loader).fabric_loadModel(id);
}
public void onModelPopulation(Consumer<ModelIdentifier> addModel) {
for (ModelAppender appender : modelAppenders) {
appender.appendAll(manager, addModel);
}
}
private <T> UnbakedModel loadCustomModel(CustomModelItf<T> function, Collection<T> loaders, String debugName) {
if (!DEBUG_MODEL_LOADING) {
for (T provider : loaders) {
try {
UnbakedModel model = function.load(provider);
if (model != null) {
return model;
}
} catch (ModelProviderException e) {
logger.error(e);
return null;
}
}
return null;
}
UnbakedModel modelLoaded = null;
T providerUsed = null;
List<T> providersApplied = null;
for (T provider : loaders) {
try {
UnbakedModel model = function.load(provider);
if (model != null) {
if (providersApplied != null) {
providersApplied.add(provider);
} else if (providerUsed != null) {
providersApplied = Lists.newArrayList(providerUsed, provider);
} else {
modelLoaded = model;
providerUsed = provider;
}
}
} catch (ModelProviderException e) {
logger.error(e);
return null;
}
}
if (providersApplied != null) {
StringBuilder builder = new StringBuilder("Conflict - multiple " + debugName + "s claimed the same unbaked model:");
for (T loader : providersApplied) {
builder.append("\n\t - ").append(loader.getClass().getName());
}
logger.error(builder.toString());
return null;
} else {
return modelLoaded;
}
}
/* @Nullable */
public UnbakedModel loadModelFromResource(Identifier resourceId) {
return loadCustomModel((r) -> r.loadModelResource(resourceId, this), modelResourceProviders, "resource provider");
}
/* @Nullable */
public UnbakedModel loadModelFromVariant(Identifier variantId) {
if (!(variantId instanceof ModelIdentifier)) {
return loadModelFromResource(variantId);
} else {
ModelIdentifier modelId = (ModelIdentifier) variantId;
UnbakedModel model = loadCustomModel((r) -> r.loadModelVariant((ModelIdentifier) variantId, this), modelVariantProviders, "resource provider");
if (model != null) {
return model;
}
// Replicating the special-case from ModelLoader as loadModelFromJson is insufficiently patchable
if (Objects.equals(modelId.getVariant(), "inventory")) {
Identifier resourceId = new Identifier(modelId.getNamespace(), "item/" + modelId.getPath());
model = loadModelFromResource(resourceId);
if (model != null) {
return model;
}
}
return null;
}
}
public void finish() {
loader = null;
}
}
private static final Logger LOGGER = LogManager.getLogger();
public static final ModelLoadingRegistryImpl INSTANCE = new ModelLoadingRegistryImpl();
private final List<Function<ResourceManager, ModelVariantProvider>> variantProviderSuppliers = new ArrayList<>();
private final List<Function<ResourceManager, ModelResourceProvider>> resourceProviderSuppliers = new ArrayList<>();
private final List<ModelAppender> appenders = new ArrayList<>();
@Override
public void registerAppender(ModelAppender appender) {
appenders.add(appender);
}
@Override
public void registerResourceProvider(Function<ResourceManager, ModelResourceProvider> providerSupplier) {
resourceProviderSuppliers.add(providerSupplier);
}
@Override
public void registerVariantProvider(Function<ResourceManager, ModelVariantProvider> providerSupplier) {
variantProviderSuppliers.add(providerSupplier);
}
public static LoaderInstance begin(ModelLoader loader, ResourceManager manager) {
return new LoaderInstance(INSTANCE, loader, manager);
}
}

View file

@ -0,0 +1,106 @@
/*
* Copyright (c) 2016, 2017, 2018 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.mixin.client.model;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import net.fabricmc.fabric.impl.client.model.ModelLoaderHooks;
import net.fabricmc.fabric.impl.client.model.ModelLoadingRegistryImpl;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map;
import java.util.Set;
@Mixin(ModelLoader.class)
public class MixinModelLoader implements ModelLoaderHooks {
// this is the first one
@Shadow
public static ModelIdentifier MISSING;
@Shadow
private ResourceManager resourceContainer;
@Shadow
private Set<Identifier> field_5390;
@Shadow
private Map<Identifier, UnbakedModel> unbakedModels;
private ModelLoadingRegistryImpl.LoaderInstance fabric_mlrLoaderInstance;
@Shadow
private void addModel(ModelIdentifier id) {
}
@Shadow
private void putModel(Identifier id, UnbakedModel unbakedModel) {
}
@Shadow
private void loadModel(Identifier id) {
}
@Inject(at = @At("HEAD"), method = "loadModel", cancellable = true)
private void loadModelHook(Identifier id, CallbackInfo ci) {
UnbakedModel customModel = fabric_mlrLoaderInstance.loadModelFromVariant(id);
if (customModel != null) {
putModel(id, customModel);
ci.cancel();
}
}
@Inject(at = @At("HEAD"), method = "addModel")
private void addModelHook(ModelIdentifier id, CallbackInfo info) {
if (id == MISSING) {
//noinspection RedundantCast
ModelLoaderHooks hooks = (ModelLoaderHooks) (Object) this;
fabric_mlrLoaderInstance = ModelLoadingRegistryImpl.begin((ModelLoader) (Object) this, resourceContainer);
fabric_mlrLoaderInstance.onModelPopulation(hooks::fabric_addModel);
}
}
@Inject(at = @At("RETURN"), method = "<init>")
private void initFinishedHook(CallbackInfo info) {
//noinspection ConstantConditions
fabric_mlrLoaderInstance.finish();
}
@Override
public void fabric_addModel(ModelIdentifier id) {
addModel(id);
}
@Override
public UnbakedModel fabric_loadModel(Identifier id) {
if (!field_5390.add(id)) {
throw new IllegalStateException("Circular reference while loading " + id);
}
loadModel(id);
field_5390.remove(id);
return unbakedModels.get(id);
}
}

View file

@ -1,7 +1,7 @@
{
"id": "fabric",
"name": "Fabric API",
"version": "0.1.2",
"version": "0.1.3",
"side": "universal",
"description": "Core API module providing key hooks and intercompatibility features.",
"license": "Apache-2.0",

View file

@ -7,6 +7,7 @@
"bugfix.MixinBiomeColors",
"client.itemgroup.MixinItemGroup",
"client.itemgroup.MixinCreativePlayerInventoryGui",
"client.model.MixinModelLoader",
"client.render.MixinBlockColorMap",
"client.render.MixinBlockEntityRenderManager",
"client.render.MixinEntityRenderManager",

View file

@ -0,0 +1,126 @@
/*
* Copyright (c) 2016, 2017, 2018 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.model;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
import net.fabricmc.fabric.events.client.ClientTickEvent;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.model.*;
import net.minecraft.client.render.model.json.ModelItemPropertyOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import java.util.*;
import java.util.function.Function;
public class ModelModClient implements ClientModInitializer {
private static BakedModel bakedModel;
@Override
public void onInitializeClient() {
ModelLoadingRegistry.INSTANCE.registerAppender((manager, out) -> {
System.out.println("--- ModelAppender called! ---");
out.accept(new ModelIdentifier("fabric:model#custom"));
});
ModelLoadingRegistry.INSTANCE.registerVariantProvider(manager -> ((modelId, context) -> {
if (modelId.getVariant().equals("custom") && modelId.getNamespace().equals("fabric")) {
System.out.println("--- ModelVariantProvider called! ---");
return context.loadModel(new Identifier("fabric:custom"));
} else {
return null;
}
}));
ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> ((id, context) -> {
if (id.toString().equals("fabric:custom")) {
return context.loadModel(new Identifier("fabric:custom2"));
} else if (id.toString().equals("fabric:custom2")) {
System.out.println("--- ModelResourceProvider called! ---");
return new UnbakedModel() {
@Override
public Collection<Identifier> getModelDependencies() {
return Collections.emptyList();
}
@Override
public Collection<Identifier> getTextureDependencies(Function<Identifier, UnbakedModel> var1, Set<String> var2) {
return Collections.emptyList();
}
@Override
public BakedModel bake(ModelLoader var1, Function<Identifier, Sprite> var2, ModelRotationContainer var3) {
System.out.println("--- Model baked! ---");
return bakedModel = new BakedModel() {
@Override
public List<BakedQuad> getQuads(BlockState var1, Direction var2, Random var3) {
return Collections.emptyList();
}
@Override
public boolean useAmbientOcclusion() {
return false;
}
@Override
public boolean hasDepthInGui() {
return false;
}
@Override
public boolean isBuiltin() {
return false;
}
@Override
public Sprite getSprite() {
return MinecraftClient.getInstance().getSpriteAtlas().getSprite("missingno");
}
@Override
public ModelTransformation getTransformations() {
return ModelTransformation.ORIGIN;
}
@Override
public ModelItemPropertyOverrideList getItemPropertyOverrides() {
return ModelItemPropertyOverrideList.ORIGIN;
}
};
}
};
} else {
return null;
}
}));
ClientTickEvent.CLIENT.register((client) -> {
if (client.getBakedModelManager().getModel(new ModelIdentifier("fabric:model#custom"))
== bakedModel && bakedModel != null) {
System.out.println("--- MODEL LOADED! ---");
} else {
System.out.println("--- MODEL NOT LOADED! ---");
}
});
}
}