Created
May 13, 2021 22:15
-
-
Save Haven-King/b6a9fd709803d2f5d50b096f73d29b44 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.aether.client.model; | |
import com.mojang.datafixers.util.Pair; | |
import net.fabricmc.fabric.api.renderer.v1.Renderer; | |
import net.fabricmc.fabric.api.renderer.v1.RendererAccess; | |
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; | |
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder; | |
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; | |
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; | |
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; | |
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; | |
import net.minecraft.block.BlockState; | |
import net.minecraft.client.render.model.*; | |
import net.minecraft.client.render.model.json.ModelOverrideList; | |
import net.minecraft.client.render.model.json.ModelTransformation; | |
import net.minecraft.client.texture.Sprite; | |
import net.minecraft.client.util.SpriteIdentifier; | |
import net.minecraft.item.ItemStack; | |
import net.minecraft.util.Identifier; | |
import net.minecraft.util.math.BlockPos; | |
import net.minecraft.util.math.Direction; | |
import net.minecraft.util.math.MathHelper; | |
import net.minecraft.util.math.Vec3i; | |
import net.minecraft.world.BlockRenderView; | |
import org.jetbrains.annotations.Nullable; | |
import java.util.*; | |
import java.util.function.Consumer; | |
import java.util.function.Function; | |
import java.util.function.Supplier; | |
public class ExtendedTilingBlockModel implements BakedModel, FabricBakedModel, UnbakedModel { | |
private static final Direction[] DIRECTIONS = Direction.values(); | |
private final List<SpriteIdentifier> spriteIdentifiers; | |
private final Map<Direction, Mesh[]> meshes = new EnumMap<>(Direction.class); | |
private final int width, height; | |
private Sprite sprite; | |
private final SpriteIdentifier spriteId; | |
private ExtendedTilingBlockModel(SpriteIdentifier spriteId, int width, int height, List<SpriteIdentifier> spriteIdentifiers) { | |
this.width = width; | |
this.height = height; | |
this.spriteIdentifiers = spriteIdentifiers; | |
this.spriteId = spriteId; | |
} | |
@Override | |
public boolean isVanillaAdapter() { | |
return false; | |
} | |
@Override | |
public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) { | |
int x = pos.getX(), y = pos.getY(), z = pos.getZ(); | |
Consumer<Mesh> consumer = context.meshConsumer(); | |
for (Direction direction : DIRECTIONS) { | |
consumer.accept(this.meshes.get(direction)[this.indexOf(direction, x, y, z)]); | |
} | |
} | |
@Override | |
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) { | |
} | |
@Override | |
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction face, Random random) { | |
return Collections.emptyList(); | |
} | |
@Override | |
public boolean useAmbientOcclusion() { | |
return true; | |
} | |
@Override | |
public boolean hasDepth() { | |
return false; | |
} | |
@Override | |
public boolean isSideLit() { | |
return false; | |
} | |
@Override | |
public boolean isBuiltin() { | |
return false; | |
} | |
@Override | |
public Sprite getSprite() { | |
return this.sprite; | |
} | |
@Override | |
public ModelTransformation getTransformation() { | |
return ModelTransformation.NONE; | |
} | |
@Override | |
public ModelOverrideList getOverrides() { | |
return ModelOverrideList.EMPTY; | |
} | |
@Override | |
public Collection<Identifier> getModelDependencies() { | |
return Collections.emptyList(); | |
} | |
@Override | |
public Collection<SpriteIdentifier> getTextureDependencies(Function<Identifier, UnbakedModel> unbakedModelGetter, Set<Pair<String, String>> unresolvedTextureReferences) { | |
return this.spriteIdentifiers; | |
} | |
@Nullable | |
@Override | |
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) { | |
Renderer renderer = RendererAccess.INSTANCE.getRenderer(); | |
if (renderer != null) { | |
this.sprite = textureGetter.apply(this.spriteId); | |
MeshBuilder builder = renderer.meshBuilder(); | |
QuadEmitter emitter = builder.getEmitter(); | |
for (Direction direction : DIRECTIONS) { | |
Mesh[] meshes = new Mesh[this.width * this.height]; | |
for (int i = 0; i < this.width * this.height; ++i) { | |
emitter.square(direction, 0, 0, 1, 1, 0); | |
emitter.spriteBake(0, textureGetter.apply(this.spriteIdentifiers.get(i)), MutableQuadView.BAKE_LOCK_UV); | |
emitter.spriteColor(0, -1, -1, -1, -1); | |
emitter.emit(); | |
meshes[i] = builder.build(); | |
} | |
this.meshes.put(direction, meshes); | |
} | |
} | |
return this; | |
} | |
private int indexOf(Direction direction, int x, int y, int z) { | |
Direction.Axis axis = direction.getAxis(); | |
Vec3i vec3i = direction.getVector(); | |
int mod = axis.choose(vec3i.getX(), vec3i.getY(), vec3i.getZ()); | |
switch (axis) { | |
case X: | |
return MathHelper.floorMod(z * -mod + x, this.width) + (this.height - MathHelper.floorMod(y + x, this.height) - 1) * this.width; | |
case Y: | |
return MathHelper.floorMod(x + y, this.width) + (this.height - MathHelper.floorMod(z * -mod + y, this.height) - 1) * this.width; | |
case Z: | |
return MathHelper.floorMod(x * mod + z, this.width) + (this.height - MathHelper.floorMod(y + z, this.height) - 1) * this.width; | |
} | |
return 0; | |
} | |
public static final class Builder { | |
private final SpriteIdentifier spriteId; | |
private int width, height; | |
private final List<SpriteIdentifier> spriteIdentifiers = new ArrayList<>(); | |
public Builder(SpriteIdentifier spriteId) { | |
this.spriteId = spriteId; | |
} | |
public Builder row(SpriteIdentifier... spriteIdentifiers) { | |
if (spriteIdentifiers.length > 0) { | |
if (this.width > 0 && spriteIdentifiers.length != this.width) { | |
throw new RuntimeException("Row is not of correct size! Expected " + this.width + " found " + spriteIdentifiers.length + "."); | |
} | |
if (this.width == 0) this.width = spriteIdentifiers.length; | |
++this.height; | |
this.spriteIdentifiers.addAll(Arrays.asList(spriteIdentifiers)); | |
} | |
return this; | |
} | |
public Builder of(SpriteIdentifier base, int startingIndex, int width, int height) { | |
this.width = width; | |
this.height = height; | |
for (int i = startingIndex; i < startingIndex + width * height; ++i) { | |
this.spriteIdentifiers.add(new SpriteIdentifier(base.getAtlasId(), new Identifier(base.getTextureId().toString() + i))); | |
} | |
return this; | |
} | |
public ExtendedTilingBlockModel build() { | |
return new ExtendedTilingBlockModel(this.spriteId, this.width, this.height, this.spriteIdentifiers); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment