Skip to content

Commit

Permalink
feat: Mark Five Model
Browse files Browse the repository at this point in the history
chore: ClientSuit now holds model, texture
chore: Suit now holds its own SuitSet
  • Loading branch information
Duzos committed Aug 26, 2024
1 parent f95454c commit aaf288b
Show file tree
Hide file tree
Showing 11 changed files with 498 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class ArmorFeatureRendererMixin {
private void timeless$getArmorTexture(ArmorItem item, boolean secondLayer, @Nullable String overlay, CallbackInfoReturnable<Identifier> cir) {
if (!(item instanceof SuitItem suit)) return;

if (!suit.getSuit().toClient().hasRenderer()) return;
if (!suit.getSuit().toClient().hasModel()) return;

cir.setReturnValue(new Identifier(Timeless.MOD_ID, "textures/empty.png"));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package mc.duzo.timeless.mixin.client;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.LivingEntityRenderer;
import net.minecraft.client.render.entity.PlayerEntityRenderer;
import net.minecraft.client.render.entity.model.PlayerEntityModel;

import mc.duzo.timeless.suit.client.render.SuitFeature;

@Mixin(PlayerEntityRenderer.class)
public abstract class PlayerEntityRendererMixin extends LivingEntityRenderer<AbstractClientPlayerEntity, PlayerEntityModel<AbstractClientPlayerEntity>> {
public PlayerEntityRendererMixin(EntityRendererFactory.Context ctx, PlayerEntityModel<AbstractClientPlayerEntity> model, float shadowRadius) {
super(ctx, model, shadowRadius);
}

@Inject(method = "<init>", at = @At("TAIL"))
private void timeless$PlayerEntityRenderer(EntityRendererFactory.Context ctx, boolean slim, CallbackInfo ci) {
PlayerEntityRenderer renderer = (PlayerEntityRenderer) (Object) this;

this.addFeature(new SuitFeature<>(renderer, ctx.getModelLoader()));
}

@Inject(method = "setModelPose", at = @At("TAIL"))
private void timeless$playerRender(AbstractClientPlayerEntity player, CallbackInfo ci) {
boolean current = this.getModel().body.visible;
if (!(current)) return;
if (!SuitFeature.shouldRender(player)) return;

this.getModel().setVisible(false);

MinecraftClient client = MinecraftClient.getInstance();
if (player.equals(client.player) && !client.gameRenderer.getCamera().isThirdPerson()) {
this.getModel().setVisible(true);
}
}
}
3 changes: 3 additions & 0 deletions src/main/java/mc/duzo/timeless/suit/Suit.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
import mc.duzo.timeless.registry.Identifiable;
import mc.duzo.timeless.suit.client.ClientSuit;
import mc.duzo.timeless.suit.client.ClientSuitRegistry;
import mc.duzo.timeless.suit.set.SuitSet;

public abstract class Suit implements Identifiable {
public abstract boolean isBinding();
public abstract SuitSet getSet();

@Environment(EnvType.CLIENT)
public ClientSuit toClient() {
ClientSuit found = ClientSuitRegistry.REGISTRY.get(this.id());
Expand Down
18 changes: 17 additions & 1 deletion src/main/java/mc/duzo/timeless/suit/client/ClientSuit.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package mc.duzo.timeless.suit.client;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;

import net.minecraft.util.Identifier;

import mc.duzo.timeless.registry.Identifiable;
import mc.duzo.timeless.suit.Suit;
import mc.duzo.timeless.suit.SuitRegistry;
import mc.duzo.timeless.suit.client.render.SuitModel;

@Environment(EnvType.CLIENT)
public abstract class ClientSuit implements Identifiable {
private final Suit parent;
protected ClientSuit(Suit suit) {
Expand All @@ -24,5 +29,16 @@ public Identifier id() {
return this.toServer().id();
}

public abstract boolean hasRenderer();
/**
* @return whether this suit has a custom model and will use the timeless renderer
*/
public boolean hasModel() {
return this.model() != null;
}
public SuitModel model() {
return null;
}
public Identifier texture() {
return new Identifier(this.id().getNamespace(), "textures/suit/" + this.id().getPath() + ".png");
}
}
60 changes: 60 additions & 0 deletions src/main/java/mc/duzo/timeless/suit/client/render/SuitFeature.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package mc.duzo.timeless.suit.client.render;

import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.feature.FeatureRenderer;
import net.minecraft.client.render.entity.feature.FeatureRendererContext;
import net.minecraft.client.render.entity.model.BipedEntityModel;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.render.entity.model.EntityModelLoader;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;

import mc.duzo.timeless.suit.Suit;
import mc.duzo.timeless.suit.item.SuitItem;
import mc.duzo.timeless.suit.set.SuitSet;

public class SuitFeature<T extends LivingEntity, M extends EntityModel<T>>
extends FeatureRenderer<T, M> {

public SuitFeature(FeatureRendererContext<T, M> context, EntityModelLoader loader) {
super(context);
}

@Override
public void render(MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, T livingEntity, float f, float g, float h, float j, float k, float l) {
Suit suit = findSuit(livingEntity);
if (suit == null) return;

SuitSet set = suit.getSet();
if (!(set.isWearing(livingEntity))) return; // todo this check every frame is bad

VertexConsumer consumer = vertexConsumerProvider.getBuffer(RenderLayer.getEntityTranslucent(suit.toClient().texture()));
SuitModel model = suit.toClient().model();

BipedEntityModel<?> context = (BipedEntityModel<?>) this.getContextModel();

model.copyFrom(context);
model.setAngles(livingEntity, f, g, j, k, l);

model.render(livingEntity, j, matrixStack, consumer, i, 1, 1, 1, 1);
}

private static Suit findSuit(LivingEntity entity) {
ItemStack chest = entity.getEquippedStack(EquipmentSlot.CHEST);
if (!(chest.getItem() instanceof SuitItem item)) return null;

return item.getSuit();
}

public static boolean shouldRender(LivingEntity livingEntity) {
Suit suit = findSuit(livingEntity);
if (suit == null) return false;

SuitSet set = suit.getSet();
return set.isWearing(livingEntity); // todo this check every frame is bad
}
}
58 changes: 58 additions & 0 deletions src/main/java/mc/duzo/timeless/suit/client/render/SuitModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package mc.duzo.timeless.suit.client.render;

import java.util.Optional;

import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.entity.model.BipedEntityModel;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Identifier;

import mc.duzo.timeless.suit.client.ClientSuit;

public abstract class SuitModel extends EntityModel<LivingEntity> {
/**
* This will be called to render the model, perform all adjustments here and render the model using the proper method.
*/
public abstract void render(LivingEntity entity, float tickDelta, MatrixStack matrices, VertexConsumer vertexConsumers, int light, float r, float g, float b, float alpha);

@Override
public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) {
this.getPart().render(matrices, vertices, light, overlay, red, green, blue, alpha);
}

public Identifier texture() {
return this.getSuit().texture();
}
public Optional<Identifier> emission() {
return Optional.empty();
}
public abstract ClientSuit getSuit();

/**
* @return The root model part
*/
public abstract ModelPart getPart();

/**
* @return the name of the root model part
*/
protected String getPartName() {
return "root";
}
public Optional<ModelPart> getChild(String name) {
if (name.equals(this.getPartName())) {
return Optional.of(this.getPart());
}
return this.getPart().traverse().filter(part -> part.hasChild(name)).findFirst().map(part -> part.getChild(name));
}
protected void resetTransforms() {
this.getPart().resetTransform();
this.getPart().traverse().forEach(ModelPart::resetTransform);
}
public void copyFrom(BipedEntityModel<?> model) {

}
}
11 changes: 0 additions & 11 deletions src/main/java/mc/duzo/timeless/suit/ironman/IronManSuit.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import mc.duzo.timeless.Timeless;
import mc.duzo.timeless.suit.Suit;
import mc.duzo.timeless.suit.client.ClientSuit;

public abstract class IronManSuit extends Suit {
private final Identifier id;
Expand Down Expand Up @@ -33,14 +32,4 @@ public boolean isBinding() {
public Identifier id() {
return this.id;
}

@Override
protected ClientSuit createClient() {
return new ClientSuit(this) {
@Override
public boolean hasRenderer() {
return true;
}
};
}
}
22 changes: 22 additions & 0 deletions src/main/java/mc/duzo/timeless/suit/ironman/mk5/MarkFiveSuit.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,31 @@
package mc.duzo.timeless.suit.ironman.mk5;

import mc.duzo.timeless.suit.client.ClientSuit;
import mc.duzo.timeless.suit.client.render.SuitModel;
import mc.duzo.timeless.suit.ironman.IronManSuit;
import mc.duzo.timeless.suit.ironman.mk5.client.MarkFiveModel;
import mc.duzo.timeless.suit.set.SetRegistry;
import mc.duzo.timeless.suit.set.SuitSet;

public class MarkFiveSuit extends IronManSuit {
public MarkFiveSuit() {
super("mk_five");
}

@Override
public SuitSet getSet() {
return SetRegistry.MARK_FIVE;
}

@Override
protected ClientSuit createClient() {
SuitModel model = new MarkFiveModel();

return new ClientSuit(this) {
@Override
public SuitModel model() {
return model;
}
};
}
}
Loading

0 comments on commit aaf288b

Please sign in to comment.