Skip to content
This repository was archived by the owner on Jun 3, 2024. It is now read-only.

Commit ec08e71

Browse files
authored
IModelData support (#189)
* Add IModelData * Make IModelData a separate package tesselateSmooth & tesselateFlat * Fix MixinBlockRenderManager * Impl MixinChunkRenderer * Code clean up * Fix license * Patch ChunkRenderTask, IModelData supplier done * Impl IForgeBakedModel.getParticleTexture and isAmbientOcclusion * Finalize IModelData and IForgeBakedModel for 1.14.4 * Add comments and fix a naming problem
1 parent 20ee0db commit ec08e71

30 files changed

+1476
-27
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
archivesBaseName = "patchwork-extensions-bakedmodel"
2+
version = getSubprojectVersion(project, "0.1.0")
3+
4+
dependencies {
5+
implementation project(path: ':patchwork-api-base', configuration: 'dev')
6+
implementation project(path: ':patchwork-extensions-blockentity', configuration: 'dev')
7+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2020, 2019-2020
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package net.minecraftforge.client.extensions;
21+
22+
import java.util.List;
23+
import java.util.Random;
24+
25+
import javax.annotation.Nonnull;
26+
import javax.annotation.Nullable;
27+
28+
import net.minecraftforge.client.model.data.IModelData;
29+
30+
import net.minecraft.block.BlockState;
31+
import net.minecraft.client.render.model.BakedModel;
32+
import net.minecraft.client.render.model.BakedQuad;
33+
import net.minecraft.client.texture.Sprite;
34+
import net.minecraft.util.math.BlockPos;
35+
import net.minecraft.util.math.Direction;
36+
import net.minecraft.world.BlockRenderView;
37+
38+
/**
39+
* Forge makes every BakeModel including vanilla BakedModels extend this interface.
40+
* The handlePerspective and doesHandlePerspectives callback will be supported in a separated package.
41+
*/
42+
public interface IForgeBakedModel {
43+
default BakedModel getBakedModel() {
44+
return (BakedModel) this;
45+
}
46+
47+
@Nonnull
48+
default List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand, @Nonnull IModelData extraData) {
49+
return getBakedModel().getQuads(state, side, rand);
50+
}
51+
52+
default boolean isAmbientOcclusion(BlockState state) {
53+
return getBakedModel().useAmbientOcclusion();
54+
}
55+
56+
@Nonnull
57+
default IModelData getModelData(@Nonnull BlockRenderView world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull IModelData tileData) {
58+
return tileData;
59+
}
60+
61+
default Sprite getParticleTexture(@Nonnull IModelData data) {
62+
return getBakedModel().getSprite();
63+
}
64+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2020, 2019-2020
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package net.minecraftforge.client.model;
21+
22+
import java.lang.ref.WeakReference;
23+
import java.util.Collections;
24+
import java.util.HashSet;
25+
import java.util.Map;
26+
import java.util.Set;
27+
import java.util.concurrent.ConcurrentHashMap;
28+
29+
import javax.annotation.Nullable;
30+
31+
import com.google.common.base.Preconditions;
32+
import net.minecraftforge.client.model.data.IModelData;
33+
34+
import net.minecraft.block.entity.BlockEntity;
35+
import net.minecraft.client.MinecraftClient;
36+
import net.minecraft.client.world.ClientWorld;
37+
import net.minecraft.util.math.BlockPos;
38+
import net.minecraft.util.math.ChunkPos;
39+
import net.minecraft.world.World;
40+
import net.minecraft.world.chunk.WorldChunk;
41+
42+
import net.fabricmc.api.ClientModInitializer;
43+
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientChunkEvents;
44+
45+
import net.patchworkmc.impl.extensions.bakedmodel.ForgeModelDataProvider;
46+
47+
public class ModelDataManager implements ClientModInitializer {
48+
private static WeakReference<World> currentWorld = new WeakReference<>(null);
49+
50+
private static final Map<ChunkPos, Set<BlockPos>> needModelDataRefresh = new ConcurrentHashMap<>();
51+
52+
private static final Map<ChunkPos, Map<BlockPos, IModelData>> modelDataCache = new ConcurrentHashMap<>();
53+
54+
private static void cleanCaches(World world) {
55+
Preconditions.checkNotNull(world, "World must not be null");
56+
Preconditions.checkArgument(world == MinecraftClient.getInstance().world,
57+
"Cannot use model data for a world other than the current client world");
58+
if (world != currentWorld.get()) {
59+
currentWorld = new WeakReference<>(world);
60+
needModelDataRefresh.clear();
61+
modelDataCache.clear();
62+
}
63+
}
64+
65+
public static void requestModelDataRefresh(BlockEntity te) {
66+
Preconditions.checkNotNull(te, "Tile entity must not be null");
67+
World world = te.getWorld();
68+
69+
cleanCaches(world);
70+
needModelDataRefresh
71+
.computeIfAbsent(new ChunkPos(te.getPos()), $ -> Collections.synchronizedSet(new HashSet<>()))
72+
.add(te.getPos());
73+
}
74+
75+
private static void refreshModelData(World world, ChunkPos chunk) {
76+
cleanCaches(world);
77+
Set<BlockPos> needUpdate = needModelDataRefresh.remove(chunk);
78+
79+
if (needUpdate != null) {
80+
Map<BlockPos, IModelData> data = modelDataCache.computeIfAbsent(chunk, $ -> new ConcurrentHashMap<>());
81+
82+
for (BlockPos pos : needUpdate) {
83+
BlockEntity toUpdate = world.getBlockEntity(pos);
84+
85+
if (toUpdate != null && !toUpdate.isRemoved()) {
86+
data.put(pos, ((ForgeModelDataProvider) toUpdate).getModelData());
87+
} else {
88+
data.remove(pos);
89+
}
90+
}
91+
}
92+
}
93+
94+
@Override
95+
public void onInitializeClient() {
96+
ClientChunkEvents.CHUNK_UNLOAD.register(ModelDataManager::onClientChunkUnload);
97+
}
98+
99+
/**
100+
* In Forge, this method handles ChunkEvent.Unload event on the FORGE bus(MinecraftForge.EVENT_BUS).
101+
*/
102+
public static void onClientChunkUnload(ClientWorld world, WorldChunk chunk) {
103+
ChunkPos chunkPos = chunk.getPos();
104+
needModelDataRefresh.remove(chunkPos);
105+
modelDataCache.remove(chunkPos);
106+
}
107+
108+
public static @Nullable IModelData getModelData(World world, BlockPos pos) {
109+
return getModelData(world, new ChunkPos(pos)).get(pos);
110+
}
111+
112+
public static Map<BlockPos, IModelData> getModelData(World world, ChunkPos pos) {
113+
Preconditions.checkArgument(world.isClient, "Cannot request model data for server world");
114+
refreshModelData(world, pos);
115+
return modelDataCache.getOrDefault(pos, Collections.emptyMap());
116+
}
117+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2020, 2019-2020
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package net.minecraftforge.client.model.data;
21+
22+
public enum EmptyModelData implements IModelData {
23+
INSTANCE;
24+
25+
@Override
26+
public boolean hasProperty(ModelProperty<?> prop) {
27+
return false;
28+
}
29+
30+
@Override
31+
public <T> T getData(ModelProperty<T> prop) {
32+
return null;
33+
}
34+
35+
@Override
36+
public <T> T setData(ModelProperty<T> prop, T data) {
37+
return null;
38+
}
39+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2020, 2019-2020
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package net.minecraftforge.client.model.data;
21+
22+
import java.util.List;
23+
import java.util.Random;
24+
25+
import javax.annotation.Nonnull;
26+
import javax.annotation.Nullable;
27+
28+
import net.minecraftforge.client.extensions.IForgeBakedModel;
29+
30+
import net.minecraft.block.BlockState;
31+
import net.minecraft.client.render.model.BakedModel;
32+
import net.minecraft.client.render.model.BakedQuad;
33+
import net.minecraft.util.math.Direction;
34+
35+
/**
36+
* Convenience interface with default implementation of {@link IBakedModel#getQuads(net.minecraft.block.state.IBlockState, net.minecraft.util.EnumFacing, java.util.Random)}.
37+
*/
38+
public interface IDynamicBakedModel extends BakedModel, IForgeBakedModel {
39+
@Override
40+
default @Nonnull List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand) {
41+
return getQuads(state, side, rand, EmptyModelData.INSTANCE);
42+
}
43+
44+
// Force this to be overriden otherwise this introduces a default cycle between
45+
// the two overloads.
46+
@Override
47+
@Nonnull
48+
List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand, @Nonnull IModelData extraData);
49+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2020, 2019-2020
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package net.minecraftforge.client.model.data;
21+
22+
import javax.annotation.Nullable;
23+
24+
public interface IModelData {
25+
/**
26+
* Check if this data has a property, even if the value is {@code null}. Can be
27+
* used by code that intends to fill in data for a render pipeline, such as the
28+
* forge animation system.
29+
*
30+
* <p>IMPORTANT: {@link #getData(ModelProperty)} <em>can</em> return {@code null}
31+
* even if this method returns {@code true}.
32+
*
33+
* @param prop The property to check for inclusion in this model data
34+
* @return {@code true} if this data has the given property, even if no value is
35+
* present
36+
*/
37+
boolean hasProperty(ModelProperty<?> prop);
38+
39+
@Nullable
40+
<T> T getData(ModelProperty<T> prop);
41+
42+
@Nullable
43+
<T> T setData(ModelProperty<T> prop, T data);
44+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2020, 2019-2020
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package net.minecraftforge.client.model.data;
21+
22+
import java.util.IdentityHashMap;
23+
import java.util.Map;
24+
25+
import com.google.common.base.Preconditions;
26+
27+
public class ModelDataMap implements IModelData {
28+
private final Map<ModelProperty<?>, Object> backingMap;
29+
30+
private ModelDataMap(Map<ModelProperty<?>, Object> map) {
31+
this.backingMap = new IdentityHashMap<>(map);
32+
}
33+
34+
protected ModelDataMap() {
35+
this.backingMap = new IdentityHashMap<>();
36+
}
37+
38+
@Override
39+
public boolean hasProperty(ModelProperty<?> prop) {
40+
return backingMap.containsKey(prop);
41+
}
42+
43+
@SuppressWarnings("unchecked")
44+
@Override
45+
public <T> T getData(ModelProperty<T> prop) {
46+
return (T) backingMap.get(prop);
47+
}
48+
49+
@SuppressWarnings("unchecked")
50+
@Override
51+
public <T> T setData(ModelProperty<T> prop, T data) {
52+
Preconditions.checkArgument(prop.test(data), "Value is invalid for this property");
53+
return (T) backingMap.put(prop, data);
54+
}
55+
56+
public static class Builder {
57+
private final Map<ModelProperty<?>, Object> defaults = new IdentityHashMap<>();
58+
59+
public Builder withProperty(ModelProperty<?> prop) {
60+
return withInitial(prop, null);
61+
}
62+
63+
public <T> Builder withInitial(ModelProperty<T> prop, T data) {
64+
this.defaults.put(prop, data);
65+
return this;
66+
}
67+
68+
public ModelDataMap build() {
69+
return new ModelDataMap(defaults);
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)