mirror of
https://github.com/MineLittlePony/MineLittlePony.git
synced 2025-03-14 15:40:06 +01:00
Compare commits
4 commits
4.13.0-bet
...
1.20.2
Author | SHA1 | Date | |
---|---|---|---|
|
57754d8dec | ||
|
ec8f92e151 | ||
|
e21ce62631 | ||
|
c78cf32bd4 |
240 changed files with 4354 additions and 5387 deletions
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -1,38 +0,0 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG]"
|
||||
labels: bug
|
||||
assignees: Sollace
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Steps to reproduce**
|
||||
Help us figure out what you did to get this issue
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Version Information:**
|
||||
- Minecraft Version: [e.g. 1.20.5]
|
||||
- Mine Little Pony Version:
|
||||
|
||||
**Mod Loader:**
|
||||
- [ ] Fabric
|
||||
- [ ] Quilt
|
||||
- [ ] Neoforge (with connector)
|
||||
|
||||
**Client/Server Logs**
|
||||
If applicable, add log files by uploading them as attachments or put them below.
|
||||
|
||||
<details>
|
||||
```
|
||||
**Paste logs here**
|
||||
```
|
||||
</details>
|
26
.github/ISSUE_TEMPLATE/feature_request.md
vendored
26
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
@ -1,26 +0,0 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: Sollace
|
||||
|
||||
---
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Version Information:**
|
||||
- Minecraft Version: [e.g. 1.20.5]
|
||||
- Mine Little Pony Version:
|
||||
|
||||
**Mod Loader:**
|
||||
- [ ] Fabric
|
||||
- [ ] Quilt
|
||||
- [ ] Neoforge (with connector)
|
2
.github/workflows/gradle-build.yml
vendored
2
.github/workflows/gradle-build.yml
vendored
|
@ -12,7 +12,7 @@ jobs:
|
|||
- name: Set up JDK
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 21
|
||||
java-version: 17
|
||||
- name: Build Gradle
|
||||
uses: eskatos/gradle-command-action@v1
|
||||
with:
|
||||
|
|
2
.github/workflows/gradle-check.yml
vendored
2
.github/workflows/gradle-check.yml
vendored
|
@ -12,7 +12,7 @@ jobs:
|
|||
- name: Set up JDK
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 21
|
||||
java-version: 17
|
||||
- name: Build Gradle
|
||||
uses: eskatos/gradle-command-action@v1
|
||||
with:
|
||||
|
|
2
.github/workflows/gradle-publish.yml
vendored
2
.github/workflows/gradle-publish.yml
vendored
|
@ -16,7 +16,7 @@ jobs:
|
|||
- name: Set up JDK
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 21
|
||||
java-version: 17
|
||||
- name: Publish Maven Jar
|
||||
env:
|
||||
ACCESS_KEY: ${{ secrets.ACCESS_KEY }}
|
||||
|
|
8
.gitmodules
vendored
8
.gitmodules
vendored
|
@ -2,11 +2,3 @@
|
|||
path = skins
|
||||
url = https://github.com/MineLittlePony/Community-Skin-Pack.git
|
||||
branch = master
|
||||
[submodule "plugins/ShowMeYourPonies"]
|
||||
path = plugins/ShowMeYourPonies
|
||||
url = https://github.com/MineLittlePony/ShowMeYourPonies.git
|
||||
branch = 1.20.5
|
||||
[submodule "plugins/Sockies"]
|
||||
path = plugins/Sockies
|
||||
url = https://github.com/MineLittlePony/Sockies.git
|
||||
branch = 1.21
|
||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 12 KiB |
17
build.gradle
17
build.gradle
|
@ -4,7 +4,7 @@ buildscript {
|
|||
}
|
||||
}
|
||||
plugins {
|
||||
id 'fabric-loom' version '1.7-SNAPSHOT'
|
||||
id 'fabric-loom' version '1.5-SNAPSHOT'
|
||||
id 'maven-publish'
|
||||
id 'com.modrinth.minotaur' version '2.+'
|
||||
id 'org.ajoberstar.reckon' version '0.13.1'
|
||||
|
@ -13,13 +13,13 @@ apply plugin: 'io.github.dexman545.outlet'
|
|||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
languageVersion = JavaLanguageVersion.of(17)
|
||||
}
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
outlet.allowSnapshotsForProject = false
|
||||
outlet.mcVersionRange = ">=${project.minecraft_version}"
|
||||
outlet.mcVersionRange = project.minecraft_version_range
|
||||
|
||||
group = project.group
|
||||
description = project.displayname
|
||||
|
@ -47,8 +47,6 @@ dependencies {
|
|||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
||||
modApi "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||
|
||||
modImplementation "com.ptsmods:devlogin:3.4.1"
|
||||
|
||||
modApi fabricApi.module("fabric-api-base", project.fabric_version)
|
||||
modApi fabricApi.module("fabric-lifecycle-events-v1", project.fabric_version)
|
||||
modApi fabricApi.module("fabric-resource-loader-v0", project.fabric_version)
|
||||
|
@ -125,10 +123,9 @@ modrinth {
|
|||
gameVersions.add ver
|
||||
}
|
||||
dependencies {
|
||||
required.project 'P7dR8mSH' // Fabric API
|
||||
required.project '9aNz8Zqn' // Kirin
|
||||
optional.project 'FzE9gshV' // HD Skins
|
||||
optional.project 'h9pJxJR9' // Big Pony
|
||||
required.project 'P7dR8mSH'
|
||||
optional.project 'FzE9gshV'
|
||||
optional.project 'h9pJxJR9'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,4 +174,4 @@ publishing {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@ org.gradle.daemon=false
|
|||
|
||||
# Fabric Properties
|
||||
# check these on https://fabricmc.net/develop
|
||||
minecraft_version=1.21.4
|
||||
yarn_mappings=1.21.4+build.2
|
||||
loader_version=0.16.9
|
||||
fabric_version=0.111.0+1.21.4
|
||||
minecraft_version=1.20.2
|
||||
yarn_mappings=1.20.2+build.4
|
||||
loader_version=0.15.1
|
||||
fabric_version=0.91.1+1.20.2
|
||||
|
||||
# Mod Properties
|
||||
group=com.minelittlepony
|
||||
|
@ -15,12 +15,12 @@ org.gradle.daemon=false
|
|||
description=Mine Little Pony turns players and mobs into ponies. Press F9 ingame to access settings.
|
||||
|
||||
# Publishing
|
||||
minecraft_version_range=>=1.21.3 <1.21.4
|
||||
minecraft_version_range=>=1.20.2
|
||||
modrinth_loader_type=fabric
|
||||
modrinth_project_id=JBjInUXM
|
||||
|
||||
# Dependencies
|
||||
modmenu_version=13.0.0-beta.1
|
||||
kirin_version=1.20.3+1.21.4
|
||||
hd_skins_version=6.14.2+1.21.4
|
||||
mson_version=1.11.1+1.21.4
|
||||
modmenu_version=8.0.0
|
||||
kirin_version=1.16.1+1.20.2
|
||||
hd_skins_version=6.12.4+1.20.2
|
||||
mson_version=1.9.3+1.20.2
|
||||
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 1ae97d064e7579d94a93f2784473dc7ce0e1e670
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 31e72eab1b764506c55f00881e05aca513ea7074
|
|
@ -1,16 +1,13 @@
|
|||
package com.minelittlepony.api.config;
|
||||
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.minelittlepony.api.pony.meta.*;
|
||||
import com.minelittlepony.common.client.gui.VisibilityMode;
|
||||
import com.minelittlepony.common.util.GamePaths;
|
||||
import com.minelittlepony.common.util.settings.*;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* Storage container for MineLP client settings.
|
||||
|
@ -57,6 +54,11 @@ public class PonyConfig extends Config {
|
|||
.addComment("Helps to prevent entities from vanishing when they're in long stacks");
|
||||
public final Setting<Boolean> horsieMode = value("settings", "horsieMode", false)
|
||||
.addComment("Enables the alternative horsey models from the April Fools 2023 update");
|
||||
public final Setting<Boolean> mixedHumanSkins = value("settings", "dualSkinMode", false)
|
||||
.addComment("(Experimental) Use priority to decide between displaying the HDSkins' texture, or vanilla mojang server skin")
|
||||
.addComment("(Experimental) eg. On pony level = HUMANS")
|
||||
.addComment("(Experimental) Any time both skins resolve to the same race (eg. on pony-level HUMANS, or if both are ponies)")
|
||||
.addComment("(Experimental) the skin with the highest priority will be chosen.");;
|
||||
|
||||
public final Setting<SizePreset> sizeOverride = value("debug", "sizeOverride", SizePreset.UNSET)
|
||||
.addComment("Overrides pony sizes")
|
||||
|
@ -83,13 +85,8 @@ public class PonyConfig extends Config {
|
|||
.addComment("ON - always show")
|
||||
.addComment("OFF - never show");
|
||||
|
||||
public final Setting<HashSet<Identifier>> forwardHoldingItems = value("customisation", "forwardHoldingItems", HashSet::new, Identifier.class)
|
||||
.addComment("Contains a list of item ids that should preserve orientation")
|
||||
.addComment("when held in a unicorn's magical aura in first person");
|
||||
|
||||
public PonyConfig(Path path) {
|
||||
super(new HeirarchicalJsonConfigAdapter(new GsonBuilder()
|
||||
.registerTypeAdapter(Identifier.class, new ToStringAdapter<>(Identifier::toString, Identifier::of))), path);
|
||||
super(HEIRARCHICAL_JSON_ADAPTER, path);
|
||||
instance = this;
|
||||
}
|
||||
|
||||
|
@ -135,12 +132,12 @@ public class PonyConfig extends Config {
|
|||
*/
|
||||
public static Race getEffectiveRace(Race race) {
|
||||
|
||||
Race override = getInstance().raceOverride.get();
|
||||
Race override = instance.raceOverride.get();
|
||||
if (override != Race.HUMAN) {
|
||||
return override;
|
||||
}
|
||||
|
||||
if (getInstance().ponyLevel.get() == PonyLevel.HUMANS) {
|
||||
if (instance.ponyLevel.get() == PonyLevel.HUMANS) {
|
||||
return Race.HUMAN;
|
||||
}
|
||||
|
||||
|
@ -148,7 +145,7 @@ public class PonyConfig extends Config {
|
|||
}
|
||||
|
||||
public static Size getEffectiveSize(Size size) {
|
||||
SizePreset sz = getInstance().sizeOverride.get();
|
||||
SizePreset sz = instance.sizeOverride.get();
|
||||
|
||||
if (sz != SizePreset.UNSET) {
|
||||
return sz;
|
||||
|
|
63
src/main/java/com/minelittlepony/api/events/Channel.java
Normal file
63
src/main/java/com/minelittlepony/api/events/Channel.java
Normal file
|
@ -0,0 +1,63 @@
|
|||
package com.minelittlepony.api.events;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientLoginConnectionEvents;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.minelittlepony.api.pony.PonyData;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class Channel {
|
||||
private static final Identifier CLIENT_PONY_DATA = new Identifier("minelittlepony", "pony_data");
|
||||
private static final Identifier REQUEST_PONY_DATA = new Identifier("minelittlepony", "request_pony_data");
|
||||
private static final Logger LOGGER = LogManager.getLogger("MineLittlePony:Networking");
|
||||
|
||||
private static boolean registered;
|
||||
|
||||
public static void bootstrap() {
|
||||
ClientLoginConnectionEvents.INIT.register((handler, client) -> {
|
||||
registered = false;
|
||||
});
|
||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||
LOGGER.info("Sending consent packet to " + handler.getPlayer().getName().getString());
|
||||
|
||||
sender.sendPacket(REQUEST_PONY_DATA, PacketByteBufs.empty());
|
||||
});
|
||||
|
||||
ClientPlayNetworking.registerGlobalReceiver(REQUEST_PONY_DATA, (client, handler, ignored, sender) -> {
|
||||
registered = true;
|
||||
LOGGER.info("Server has just consented");
|
||||
});
|
||||
ServerPlayNetworking.registerGlobalReceiver(CLIENT_PONY_DATA, (server, player, ignore, buffer, ignore2) -> {
|
||||
PonyData packet = MsgPonyData.read(buffer);
|
||||
server.execute(() -> {
|
||||
PonyDataCallback.EVENT.invoker().onPonyDataAvailable(player, packet, EnvType.SERVER);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean isRegistered() {
|
||||
return registered;
|
||||
}
|
||||
|
||||
public static boolean broadcastPonyData(PonyData packet) {
|
||||
if (!isRegistered()) {
|
||||
return false;
|
||||
}
|
||||
if (FabricLoader.getInstance().getEnvironmentType() != EnvType.CLIENT) {
|
||||
throw new RuntimeException("Client packet send called by the server");
|
||||
}
|
||||
|
||||
ClientPlayNetworking.send(CLIENT_PONY_DATA, MsgPonyData.write(packet, PacketByteBufs.create()));
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package com.minelittlepony.api.events;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientLoginConnectionEvents;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.minelittlepony.api.pony.PonyData;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class ClientChannel {
|
||||
private static final Logger LOGGER = LogManager.getLogger("MineLittlePony:Networking");
|
||||
|
||||
private static boolean registered;
|
||||
|
||||
public static void bootstrap() {
|
||||
ClientLoginConnectionEvents.INIT.register((handler, client) -> {
|
||||
registered = false;
|
||||
});
|
||||
|
||||
ClientPlayNetworking.registerGlobalReceiver(CommonChannel.PonyDataRequest.ID, (packet, context) -> {
|
||||
registered = true;
|
||||
LOGGER.info("Server has just consented");
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean isRegistered() {
|
||||
return registered;
|
||||
}
|
||||
|
||||
public static boolean broadcastPonyData(PonyData packet) {
|
||||
if (!isRegistered()) {
|
||||
return false;
|
||||
}
|
||||
if (FabricLoader.getInstance().getEnvironmentType() != EnvType.CLIENT) {
|
||||
throw new RuntimeException("Client packet send called by the server");
|
||||
}
|
||||
|
||||
ClientPlayNetworking.send(new CommonChannel.PonyDataPayload(packet));
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
package com.minelittlepony.api.events;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.fabric.api.networking.v1.*;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
import net.minecraft.network.packet.CustomPayload;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.minelittlepony.api.pony.PonyData;
|
||||
|
||||
public class CommonChannel {
|
||||
private static final Logger LOGGER = LogManager.getLogger("MineLittlePony:Networking");
|
||||
|
||||
public static void bootstrap() {
|
||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||
LOGGER.info("Sending consent packet to " + handler.getPlayer().getName().getString());
|
||||
sender.sendPacket(PonyDataRequest.INSTANCE);
|
||||
});
|
||||
|
||||
PayloadTypeRegistry.playS2C().register(PonyDataRequest.ID, PonyDataRequest.CODEC);
|
||||
PayloadTypeRegistry.playS2C().register(PonyDataPayload.ID, PonyDataPayload.CODEC);
|
||||
PayloadTypeRegistry.playC2S().register(PonyDataPayload.ID, PonyDataPayload.CODEC);
|
||||
|
||||
ServerPlayNetworking.registerGlobalReceiver(PonyDataPayload.ID, (packet, context) -> {
|
||||
context.player().server.execute(() -> {
|
||||
PonyDataCallback.EVENT.invoker().onPonyDataAvailable(context.player(), packet.data(), EnvType.SERVER);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
record PonyDataPayload(PonyData data) implements CustomPayload {
|
||||
public static final Id<PonyDataPayload> ID = new Id<>(Identifier.of("minelittlepony", "pony_data"));
|
||||
public static final PacketCodec<PacketByteBuf, PonyDataPayload> CODEC = CustomPayload.codecOf(
|
||||
(p, buffer) -> MsgPonyData.write(p.data(), buffer),
|
||||
buffer -> new PonyDataPayload(MsgPonyData.read(buffer))
|
||||
);
|
||||
|
||||
@Override
|
||||
public Id<PonyDataPayload> getId() {
|
||||
return ID;
|
||||
}
|
||||
}
|
||||
|
||||
record PonyDataRequest() implements CustomPayload {
|
||||
public static final PonyDataRequest INSTANCE = new PonyDataRequest();
|
||||
public static final Id<PonyDataRequest> ID = new Id<>(Identifier.of("minelittlepony", "request_pony_data"));
|
||||
public static final PacketCodec<PacketByteBuf, PonyDataRequest> CODEC = PacketCodec.unit(INSTANCE);
|
||||
|
||||
@Override
|
||||
public Id<? extends CustomPayload> getId() {
|
||||
return ID;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,22 +2,18 @@ package com.minelittlepony.api.events;
|
|||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
import net.minecraft.entity.Entity;
|
||||
|
||||
import com.minelittlepony.api.model.PonyModel;
|
||||
import com.minelittlepony.api.model.ModelAttributes;
|
||||
|
||||
/**
|
||||
* Event triggered when a pony model's state is being evaluated.
|
||||
* <p>
|
||||
* Subscribers have the option to read the pony model's attributes or modify them if neccessary to
|
||||
* allow for custom animations.
|
||||
*/
|
||||
public interface PonyModelPrepareCallback {
|
||||
|
||||
Event<PonyModelPrepareCallback> EVENT = EventFactory.createArrayBacked(PonyModelPrepareCallback.class, listeners -> (entity, model, mode) -> {
|
||||
for (PonyModelPrepareCallback event : listeners) {
|
||||
event.onPonyModelPrepared(entity, model, mode);
|
||||
}
|
||||
});
|
||||
|
||||
void onPonyModelPrepared(ModelAttributes attributes, PonyModel<?> model, ModelAttributes.Mode mode);
|
||||
void onPonyModelPrepared(Entity entity, PonyModel<?> model, ModelAttributes.Mode mode);
|
||||
}
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
package com.minelittlepony.api.events;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.api.pony.Pony;
|
||||
|
||||
/**
|
||||
* Event for mods that want to replace the skin being used by a pony.
|
||||
*/
|
||||
public interface PonySkinResolver {
|
||||
Event<PonySkinResolver> EVENT = EventFactory.createArrayBacked(PonySkinResolver.class, listeners -> (entity, pony, result) -> {
|
||||
for (PonySkinResolver event : listeners) {
|
||||
result = event.onPonySkinResolving(entity, pony, result);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
|
||||
@Nullable
|
||||
Identifier onPonySkinResolving(Entity entity, PonyLookup ponyLookup, @Nullable Identifier previousResult);
|
||||
|
||||
interface PonyLookup {
|
||||
Pony getPony(Identifier skin);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.minelittlepony.api.model;
|
||||
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
|
||||
public interface HornedPonyModel<T extends LivingEntity> extends PonyModel<T> {
|
||||
/**
|
||||
* Returns true if this model is being applied to a race that can use magic.
|
||||
*/
|
||||
default boolean hasMagic() {
|
||||
return getRace().hasHorn() && getAttributes().metadata.glowColor() != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this model is currently using magic (horn is lit).
|
||||
*/
|
||||
boolean isCasting();
|
||||
}
|
|
@ -30,25 +30,26 @@ public final class MobPosingHelper {
|
|||
arm.roll = cos;
|
||||
}
|
||||
|
||||
public static void rotateUndeadArms(PonyModel.AttributedHolder attributes, PonyModel<?> model, float limbAngle, float ticks) {
|
||||
if (islookAngleRight(limbAngle)) {
|
||||
ModelPart rightArm = model.getForeLeg(Arm.RIGHT);
|
||||
rotateArmHolding(rightArm, 1, attributes.getSwingAmount(), ticks);
|
||||
if (attributes.getAttributes().isSitting) {
|
||||
public static void rotateUndeadArms(PonyModel<?> model, float move, float ticks) {
|
||||
ModelPart leftArm = model.getForeLeg(Arm.LEFT);
|
||||
ModelPart rightArm = model.getForeLeg(Arm.RIGHT);
|
||||
|
||||
if (islookAngleRight(move)) {
|
||||
rotateArmHolding(rightArm, 1, model.getSwingAmount(), ticks);
|
||||
if (model.getAttributes().isSitting) {
|
||||
rightArm.pitch += 0.6F;
|
||||
}
|
||||
PartUtil.shift(rightArm, 0.5F, 1.5F, 3);
|
||||
} else {
|
||||
ModelPart leftArm = model.getForeLeg(Arm.LEFT);
|
||||
rotateArmHolding(leftArm, -1, attributes.getSwingAmount(), ticks);
|
||||
if (attributes.getAttributes().isSitting) {
|
||||
rotateArmHolding(leftArm, -1, model.getSwingAmount(), ticks);
|
||||
if (model.getAttributes().isSitting) {
|
||||
leftArm.pitch += 0.6F;
|
||||
}
|
||||
PartUtil.shift(leftArm, -0.5F, 1.5F, 3);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean islookAngleRight(float limbAngle) {
|
||||
return MathHelper.sin(limbAngle / 20) < 0;
|
||||
public static boolean islookAngleRight(float move) {
|
||||
return MathHelper.sin(move / 20) < 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.minelittlepony.api.model;
|
|||
|
||||
import com.minelittlepony.api.config.PonyConfig;
|
||||
import com.minelittlepony.api.pony.*;
|
||||
import com.minelittlepony.api.pony.meta.*;
|
||||
import com.minelittlepony.common.util.animation.Interpolator;
|
||||
import com.minelittlepony.util.MathUtil;
|
||||
|
||||
|
@ -62,7 +61,7 @@ public class ModelAttributes {
|
|||
*/
|
||||
public boolean isLeftHanded;
|
||||
/**
|
||||
* True if the model is riding on the back of another pony.
|
||||
* True if the model is sitting as in boats.
|
||||
*/
|
||||
public boolean isRidingInteractive;
|
||||
/**
|
||||
|
@ -74,11 +73,6 @@ public class ModelAttributes {
|
|||
*/
|
||||
public boolean isHorsey;
|
||||
|
||||
/**
|
||||
* Flag indicating whether the pony is a player
|
||||
*/
|
||||
public boolean isPlayer;
|
||||
|
||||
/**
|
||||
* Vertical pitch whilst flying.
|
||||
*/
|
||||
|
@ -111,11 +105,6 @@ public class ModelAttributes {
|
|||
*/
|
||||
public float wingAngle;
|
||||
|
||||
/**
|
||||
* Flag to indicate whether the wings are open or shut
|
||||
*/
|
||||
public boolean wingsSpread;
|
||||
|
||||
/**
|
||||
* Contains a list of additional skins available for rendering.
|
||||
*/
|
||||
|
@ -126,11 +115,8 @@ public class ModelAttributes {
|
|||
*/
|
||||
public PonyData metadata = PonyData.NULL;
|
||||
|
||||
public Size size = SizePreset.NORMAL;
|
||||
|
||||
public Arm mainArm;
|
||||
public Hand activeHand;
|
||||
@Deprecated
|
||||
public ItemStack heldStack = ItemStack.EMPTY;
|
||||
public int itemUseTime;
|
||||
|
||||
|
@ -144,12 +130,11 @@ public class ModelAttributes {
|
|||
isGoingFast = (isFlying && model instanceof WingedPonyModel) || isGliding;
|
||||
isGoingFast &= zMotion > 0.4F;
|
||||
isGoingFast |= entity.isUsingRiptide();
|
||||
isGoingFast |= entity.isGliding();
|
||||
isGoingFast |= entity.isFallFlying();
|
||||
|
||||
motionLerp = MathUtil.clampLimit(zMotion * 30, 1);
|
||||
|
||||
wingAngle = calcWingRotationFactor(ticks);
|
||||
wingsSpread = (isSwimming || isFlying || isCrouching) && (PonyConfig.getInstance().flappyElytras.get() || !isGliding);
|
||||
}
|
||||
|
||||
private float calcWingRotationFactor(float ticks) {
|
||||
|
@ -163,21 +148,18 @@ public class ModelAttributes {
|
|||
}
|
||||
|
||||
public void updateLivingState(LivingEntity entity, Pony pony, Mode mode) {
|
||||
metadata = pony.metadata();
|
||||
size = entity.isBaby() ? SizePreset.FOAL : pony.size();
|
||||
isPlayer = entity instanceof PlayerEntity;
|
||||
visualHeight = entity.getHeight() + 0.125F;
|
||||
isSitting = PonyPosture.isSitting(entity);
|
||||
isSleeping = entity.isAlive() && entity.isSleeping();;
|
||||
isLyingDown = isSleeping;
|
||||
if (isPlayer) {
|
||||
if (entity instanceof PlayerEntity) {
|
||||
boolean moving = entity.getVelocity().multiply(1, 0, 1).length() == 0 && entity.isSneaking();
|
||||
isLyingDown |= getMainInterpolator().interpolate("lyingDown", moving ? 10 : 0, 200) >= 9;
|
||||
}
|
||||
|
||||
isCrouching = !isLyingDown && !isSitting && mode == Mode.THIRD_PERSON && PonyPosture.isCrouching(pony, entity);
|
||||
isFlying = !isLyingDown && mode == Mode.THIRD_PERSON && PonyPosture.isFlying(entity);
|
||||
isGliding = entity.isGliding();
|
||||
isGliding = entity.isFallFlying();
|
||||
isSwimming = mode == Mode.THIRD_PERSON && PonyPosture.isSwimming(entity);
|
||||
isSwimmingRotated = isSwimming;
|
||||
isRiptide = entity.isUsingRiptide();
|
||||
|
@ -187,7 +169,7 @@ public class ModelAttributes {
|
|||
}
|
||||
isLeftHanded = entity.getMainArm() == Arm.LEFT;
|
||||
isHorsey = PonyConfig.getInstance().horsieMode.get();
|
||||
featureSkins = SkinsProxy.getInstance().getAvailableSkins(entity);
|
||||
featureSkins = SkinsProxy.instance.getAvailableSkins(entity);
|
||||
mainArm = entity.getMainArm();
|
||||
activeHand = entity.getActiveHand();
|
||||
itemUseTime = entity.getItemUseTimeLeft();
|
||||
|
@ -197,31 +179,12 @@ public class ModelAttributes {
|
|||
return Interpolator.linear(interpolatorId);
|
||||
}
|
||||
|
||||
public UUID getEntityId() {
|
||||
return interpolatorId;
|
||||
}
|
||||
|
||||
public boolean shouldLiftArm(ArmPose pose, ArmPose complement, float sigma) {
|
||||
return pose != ArmPose.EMPTY
|
||||
&& (pose != complement || sigma == (isLeftHanded ? 1 : -1))
|
||||
&& (complement != ArmPose.BLOCK && complement != ArmPose.CROSSBOW_HOLD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if this model is wearing the given piece of gear.
|
||||
*/
|
||||
public boolean isWearing(Wearable wearable) {
|
||||
return isEmbedded(wearable) || featureSkins.contains(wearable.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the chosen piece of gear is sourcing its texture from the main skin.
|
||||
* i.e. Used to change wing rendering when using saddlebags.
|
||||
*/
|
||||
public boolean isEmbedded(Wearable wearable) {
|
||||
return metadata.gear().matches(wearable);
|
||||
}
|
||||
|
||||
public enum Mode {
|
||||
FIRST_PERSON,
|
||||
THIRD_PERSON,
|
||||
|
|
|
@ -2,10 +2,13 @@ package com.minelittlepony.api.model;
|
|||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.entity.model.ModelWithArms;
|
||||
import net.minecraft.client.render.entity.model.BipedEntityModel.ArmPose;
|
||||
import net.minecraft.util.Arm;
|
||||
|
||||
public interface ModelWithHooves extends ModelWithArms {
|
||||
ModelPart getForeLeg(Arm side);
|
||||
|
||||
ModelPart getHindLeg(Arm side);
|
||||
|
||||
ArmPose getArmPoseForSide(Arm side);
|
||||
}
|
||||
|
|
|
@ -1,42 +1,57 @@
|
|||
package com.minelittlepony.api.model;
|
||||
|
||||
import net.minecraft.client.render.entity.equipment.EquipmentModel;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.ArmorItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Util;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.client.model.AbstractPonyModel;
|
||||
import com.minelittlepony.api.pony.PonyData;
|
||||
import com.minelittlepony.client.model.PlayerModelKey;
|
||||
import com.minelittlepony.client.model.armour.*;
|
||||
import com.minelittlepony.mson.api.ModelKey;
|
||||
import com.minelittlepony.mson.api.MsonModel;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Container class for the various models and their associated piece of armour.
|
||||
*/
|
||||
public record Models<M extends PonyModel<?>> (
|
||||
Function<ModelKey<AbstractPonyModel<?>>, AbstractPonyModel<?>> armor,
|
||||
M body
|
||||
) {
|
||||
public class Models<T extends LivingEntity, M extends PonyModel<?>> {
|
||||
@Nullable
|
||||
private final MsonModel.Factory<PonyArmourModel<T>> armorFactory;
|
||||
private final Map<ModelKey<PonyArmourModel<?>>, PonyArmourModel<T>> armor = new HashMap<>();
|
||||
|
||||
public Models(PlayerModelKey<? super M> playerModelKey, boolean slimArms, @Nullable Consumer<M> initializer) {
|
||||
this(Util.memoize(key -> key.createModel(playerModelKey.armorFactory())), playerModelKey.getKey(slimArms).createModel());
|
||||
private final M body;
|
||||
|
||||
public Models(PlayerModelKey<T, ? super M> playerModelKey, boolean slimArms, @Nullable Consumer<M> initializer) {
|
||||
this.armorFactory = playerModelKey.armorFactory();
|
||||
this.body = playerModelKey.getKey(slimArms).createModel();
|
||||
if (initializer != null) {
|
||||
initializer.accept(body);
|
||||
initializer.accept(this.body);
|
||||
}
|
||||
}
|
||||
|
||||
public Models(ModelKey<M> key) {
|
||||
this(Util.memoize(k -> k.createModel()), key.createModel());
|
||||
this.armorFactory = null;
|
||||
this.body = key.createModel();
|
||||
}
|
||||
|
||||
public Optional<AbstractPonyModel<?>> getArmourModel(ItemStack stack, EquipmentModel.LayerType layerType, ArmourVariant variant) {
|
||||
return ArmorModelRegistry.getModelKey(stack.getItem(), layerType)
|
||||
.or(() -> variant.getDefaultModel(layerType))
|
||||
.map(armor);
|
||||
public M body() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public Optional<PonyArmourModel<T>> getArmourModel(ItemStack stack, ArmourLayer layer, ArmourVariant variant) {
|
||||
return ArmorModelRegistry.getModelKey(stack.getItem(), layer).or(() -> variant.getDefaultModel(layer).filter(l -> stack.getItem() instanceof ArmorItem))
|
||||
.map(key -> armor.computeIfAbsent(key, k -> {
|
||||
return armorFactory == null ? k.createModel() : k.createModel(armorFactory);
|
||||
}));
|
||||
}
|
||||
|
||||
public Models<T, M> applyMetadata(PonyData meta) {
|
||||
body.setMetadata(meta);
|
||||
armor.values().forEach(a -> a.setMetadata(meta));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,30 +2,84 @@ package com.minelittlepony.api.model;
|
|||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.entity.model.*;
|
||||
import net.minecraft.client.render.entity.state.EntityRenderState;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
import com.minelittlepony.api.pony.meta.Race;
|
||||
import com.minelittlepony.api.config.PonyConfig;
|
||||
import com.minelittlepony.api.pony.Pony;
|
||||
import com.minelittlepony.api.pony.PonyData;
|
||||
import com.minelittlepony.api.pony.meta.*;
|
||||
import com.minelittlepony.mson.api.MsonModel;
|
||||
|
||||
public interface PonyModel<T extends EntityRenderState & PonyModel.AttributedHolder> extends MsonModel, ModelWithHooves, ModelWithHead {
|
||||
public interface PonyModel<T extends LivingEntity> extends MsonModel, ModelWithHooves, ModelWithHat, ModelWithHead {
|
||||
|
||||
void copyAttributes(BipedEntityModel<T> other);
|
||||
|
||||
void updateLivingState(T entity, Pony pony, ModelAttributes.Mode mode);
|
||||
|
||||
ModelPart getBodyPart(BodyPart part);
|
||||
|
||||
/**
|
||||
* Applies a transform particular to a certain body part.
|
||||
*/
|
||||
void transform(T state, BodyPart part, MatrixStack stack);
|
||||
void transform(BodyPart part, MatrixStack stack);
|
||||
|
||||
default float getWobbleAmplitude(T state) {
|
||||
return 1;
|
||||
/**
|
||||
* Gets the transitive properties of this model.
|
||||
*/
|
||||
ModelAttributes getAttributes();
|
||||
|
||||
/**
|
||||
* Sets the pony metadata object associated with this model.
|
||||
*/
|
||||
void setMetadata(PonyData meta);
|
||||
|
||||
/**
|
||||
* Gets the active scaling profile used to lay out this model's parts.
|
||||
*/
|
||||
default Size getSize() {
|
||||
return PonyConfig.getEffectiveSize(getAttributes().metadata.size());
|
||||
}
|
||||
|
||||
public interface AttributedHolder {
|
||||
ModelAttributes getAttributes();
|
||||
|
||||
Race getRace();
|
||||
|
||||
float getSwingAmount();
|
||||
default Race getRace() {
|
||||
return PonyConfig.getEffectiveRace(getAttributes().metadata.race());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current leg swing amount.
|
||||
*/
|
||||
float getSwingAmount();
|
||||
|
||||
/**
|
||||
* Gets the step wobble used for various hair bits and animations.
|
||||
*/
|
||||
default float getWobbleAmount() {
|
||||
if (getSwingAmount() <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return MathHelper.sin(MathHelper.sqrt(getSwingAmount()) * MathHelper.PI * 2) * 0.04F;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the y-offset applied to entities riding this one.
|
||||
*/
|
||||
float getRiderYOffset();
|
||||
|
||||
/**
|
||||
* Tests if this model is wearing the given piece of gear.
|
||||
*/
|
||||
default boolean isWearing(Wearable wearable) {
|
||||
return isEmbedded(wearable) || getAttributes().featureSkins.contains(wearable.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the chosen piece of gear is sourcing its texture from the main skin.
|
||||
* i.e. Used to change wing rendering when using saddlebags.
|
||||
*/
|
||||
default boolean isEmbedded(Wearable wearable) {
|
||||
return getAttributes().metadata.gear().matches(wearable);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
117
src/main/java/com/minelittlepony/api/model/PonyModelMixin.java
Normal file
117
src/main/java/com/minelittlepony/api/model/PonyModelMixin.java
Normal file
|
@ -0,0 +1,117 @@
|
|||
package com.minelittlepony.api.model;
|
||||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||
import net.minecraft.client.render.entity.model.ModelWithArms;
|
||||
import net.minecraft.client.render.entity.model.BipedEntityModel.ArmPose;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.util.Arm;
|
||||
|
||||
import com.minelittlepony.api.pony.Pony;
|
||||
import com.minelittlepony.api.pony.PonyData;
|
||||
import com.minelittlepony.api.pony.meta.Size;
|
||||
import com.minelittlepony.mson.api.ModelView;
|
||||
import com.minelittlepony.mson.api.model.BoxBuilder.RenderLayerSetter;
|
||||
|
||||
public interface PonyModelMixin<T extends LivingEntity, M extends PonyModel<T>> extends PonyModel<T> {
|
||||
M mixin();
|
||||
|
||||
@Override
|
||||
default void init(ModelView context) {
|
||||
mixin().init(context);
|
||||
if (mixin() instanceof RenderLayerSetter && this instanceof RenderLayerSetter) {
|
||||
((RenderLayerSetter)this).setRenderLayerFactory(((RenderLayerSetter)mixin()).getRenderLayerFactory());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
default void updateLivingState(T entity, Pony pony, ModelAttributes.Mode mode) {
|
||||
mixin().updateLivingState(entity, pony, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
default void copyAttributes(BipedEntityModel<T> other) {
|
||||
mixin().copyAttributes(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
default void transform(BodyPart part, MatrixStack stack) {
|
||||
mixin().transform(part, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
default ModelAttributes getAttributes() {
|
||||
return mixin().getAttributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
default Size getSize() {
|
||||
return mixin().getSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
default void setMetadata(PonyData meta) {
|
||||
mixin().setMetadata(meta);
|
||||
}
|
||||
|
||||
@Override
|
||||
default float getSwingAmount() {
|
||||
return mixin().getSwingAmount();
|
||||
}
|
||||
|
||||
@Override
|
||||
default float getWobbleAmount() {
|
||||
return mixin().getWobbleAmount();
|
||||
}
|
||||
|
||||
@Override
|
||||
default float getRiderYOffset() {
|
||||
return mixin().getRiderYOffset();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
default ModelPart getForeLeg(Arm side) {
|
||||
return mixin().getForeLeg(side);
|
||||
}
|
||||
|
||||
@Override
|
||||
default ModelPart getHindLeg(Arm side) {
|
||||
return mixin().getHindLeg(side);
|
||||
}
|
||||
|
||||
@Override
|
||||
default ArmPose getArmPoseForSide(Arm side) {
|
||||
return mixin().getArmPoseForSide(side);
|
||||
}
|
||||
|
||||
@Override
|
||||
default void setArmAngle(Arm arm, MatrixStack stack) {
|
||||
if (mixin() instanceof ModelWithArms) {
|
||||
((ModelWithArms)mixin()).setArmAngle(arm, stack);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
default ModelPart getHead() {
|
||||
return mixin().getHead();
|
||||
}
|
||||
|
||||
@Override
|
||||
default ModelPart getBodyPart(BodyPart part) {
|
||||
return mixin().getBodyPart(part);
|
||||
}
|
||||
|
||||
@Override
|
||||
default void setHatVisible(boolean hatVisible) {
|
||||
mixin().setHatVisible(hatVisible);
|
||||
}
|
||||
|
||||
interface Caster<T extends LivingEntity, M extends PonyModel<T> & HornedPonyModel<T>, ArmModel> extends PonyModelMixin<T, M>, HornedPonyModel<T> {
|
||||
@Override
|
||||
default boolean isCasting() {
|
||||
return mixin().isCasting();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package com.minelittlepony.api.model;
|
||||
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public interface PreviewModel {
|
||||
Identifier getForm();
|
||||
boolean forceSeapony();
|
||||
|
||||
boolean forceNirik();
|
||||
}
|
||||
|
|
|
@ -1,38 +1,25 @@
|
|||
package com.minelittlepony.api.model;
|
||||
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.entity.state.EntityRenderState;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
import com.minelittlepony.mson.util.RenderList;
|
||||
public interface SubModel {
|
||||
/**
|
||||
* Sets the model's various rotation angles.
|
||||
*/
|
||||
default void setPartAngles(ModelAttributes attributes, float limbAngle, float limbSpeed, float bodySwing, float animationProgress) {
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface SubModel<T extends EntityRenderState> extends RenderList {
|
||||
static <T extends EntityRenderState> RenderList toRenderList(Supplier<SubModel<? super T>> part) {
|
||||
return (stack, vertices, overlay, light, color) -> part.get().renderPart(stack, vertices, overlay, light, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders this model component.
|
||||
*/
|
||||
void renderPart(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color);
|
||||
|
||||
@Override
|
||||
default void accept(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color) {
|
||||
renderPart(stack, vertices, overlay, light, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the model's various rotation angles.
|
||||
*/
|
||||
default void setPartAngles(T state, float wobbleAmount) {
|
||||
}
|
||||
void renderPart(MatrixStack stack, VertexConsumer vertices, int overlay, int light, float red, float green, float blue, float alpha, ModelAttributes attributes);
|
||||
|
||||
/**
|
||||
* Sets whether this part should be rendered.
|
||||
*/
|
||||
default void setVisible(boolean visible, T state) {
|
||||
default void setVisible(boolean visible, ModelAttributes attributes) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +1,42 @@
|
|||
package com.minelittlepony.api.model;
|
||||
|
||||
import net.minecraft.client.render.entity.state.BipedEntityRenderState;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
|
||||
import com.minelittlepony.api.config.PonyConfig;
|
||||
import com.minelittlepony.api.pony.meta.Wearable;
|
||||
import com.minelittlepony.util.MathUtil;
|
||||
|
||||
public interface WingedPonyModel<T extends BipedEntityRenderState & PonyModel.AttributedHolder> extends PonyModel<T> {
|
||||
public interface WingedPonyModel<T extends LivingEntity> extends PonyModel<T> {
|
||||
public static final float WINGS_HALF_SPREAD_ANGLE = MathUtil.Angles._270_DEG;
|
||||
public static final float WINGS_FULL_SPREAD_ANGLE = MathUtil.Angles._270_DEG + 0.4F;
|
||||
public static final float WINGS_RAISED_ANGLE = 4;
|
||||
|
||||
/**
|
||||
* Gets the wings of this pegasus/flying creature
|
||||
*/
|
||||
SubModel<T> getWings();
|
||||
|
||||
/**
|
||||
* Returns true if the wings are spread.
|
||||
*/
|
||||
default boolean wingsAreOpen(T state) {
|
||||
return state.getAttributes().wingsSpread;
|
||||
default boolean wingsAreOpen() {
|
||||
return (getAttributes().isSwimming || getAttributes().isFlying || getAttributes().isCrouching)
|
||||
&& (PonyConfig.getInstance().flappyElytras.get() || !getAttributes().isGliding);
|
||||
}
|
||||
|
||||
default boolean isBurdened() {
|
||||
return isWearing(Wearable.SADDLE_BAGS_BOTH)
|
||||
|| isWearing(Wearable.SADDLE_BAGS_LEFT)
|
||||
|| isWearing(Wearable.SADDLE_BAGS_RIGHT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the wings of this pegasus/flying creature
|
||||
*/
|
||||
SubModel getWings();
|
||||
|
||||
/**
|
||||
* Determines angle used to animate wing flaps whilst flying/swimming.
|
||||
*
|
||||
* @param ticks Partial render ticks
|
||||
*/
|
||||
default float getWingRotationFactor(T state) {
|
||||
return state.getAttributes().wingAngle;
|
||||
default float getWingRotationFactor(float ticks) {
|
||||
return getAttributes().wingAngle;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,20 +6,36 @@ import net.minecraft.client.render.RenderLayer;
|
|||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class AbstractGearModel extends Model implements Gear {
|
||||
|
||||
private final List<ModelPart> parts = new ArrayList<>();
|
||||
|
||||
private final float stackingHeight;
|
||||
|
||||
public AbstractGearModel(ModelPart root, float stackingHeight) {
|
||||
super(root, RenderLayer::getEntitySolid);
|
||||
public AbstractGearModel(float stackingHeight) {
|
||||
super(RenderLayer::getEntitySolid);
|
||||
this.stackingHeight = stackingHeight;
|
||||
}
|
||||
|
||||
public AbstractGearModel addPart(ModelPart t) {
|
||||
parts.add(t);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color, UUID interpolatorId) {
|
||||
render(stack, vertices, overlay, light, color);
|
||||
public void render(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha, UUID interpolatorId) {
|
||||
render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack stack, VertexConsumer renderContext, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
|
||||
parts.forEach(part -> {
|
||||
part.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,9 +2,9 @@ package com.minelittlepony.api.model.gear;
|
|||
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.entity.state.BipedEntityRenderState;
|
||||
import net.minecraft.client.render.entity.state.EntityRenderState;
|
||||
import net.minecraft.client.render.entity.model.EntityModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import com.minelittlepony.api.model.*;
|
||||
|
@ -37,7 +37,7 @@ public interface Gear {
|
|||
*
|
||||
* @return True to render this wearable
|
||||
*/
|
||||
boolean canRender(PonyModel<?> model, EntityRenderState entity);
|
||||
boolean canRender(PonyModel<?> model, Entity entity);
|
||||
|
||||
/**
|
||||
* Gets the body location that this wearable appears on.
|
||||
|
@ -62,21 +62,21 @@ public interface Gear {
|
|||
*
|
||||
* If you need to use the player's own skin, use {@link IRenderContext#getDefaultTexture(entity, wearable)}
|
||||
*/
|
||||
<S extends EntityRenderState> Identifier getTexture(S entity, Context<S, ?> context);
|
||||
<T extends Entity> Identifier getTexture(T entity, Context<T, ?> context);
|
||||
|
||||
/**
|
||||
* Gets the layer used to render this piece of gear.
|
||||
*/
|
||||
default <S extends EntityRenderState> RenderLayer getLayer(S entity, Context<S, ?> context) {
|
||||
default <T extends Entity> RenderLayer getLayer(T entity, Context<T, ?> context) {
|
||||
return RenderLayer.getEntityTranslucent(getTexture(entity, context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies body transformations for this wearable
|
||||
*/
|
||||
default <S extends EntityRenderState & PonyModel.AttributedHolder> void transform(S state, PonyModel<S> model, MatrixStack matrices) {
|
||||
default <M extends EntityModel<?> & PonyModel<?>> void transform(M model, MatrixStack matrices) {
|
||||
BodyPart part = getGearLocation();
|
||||
model.transform(state, part, matrices);
|
||||
model.transform(part, matrices);
|
||||
model.getBodyPart(part).rotate(matrices);
|
||||
}
|
||||
|
||||
|
@ -85,14 +85,14 @@ public interface Gear {
|
|||
*
|
||||
* See {@link AbstractPonyMode.setRotationAndAngle} for an explanation of the various parameters.
|
||||
*/
|
||||
default <S extends BipedEntityRenderState & PonyModel.AttributedHolder> void pose(PonyModel<S> model, S state, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) {
|
||||
default void pose(PonyModel<?> model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders this model component.
|
||||
*/
|
||||
void render(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color, UUID interpolatorId);
|
||||
void render(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha, UUID interpolatorId);
|
||||
|
||||
/**
|
||||
* A render context for instance of IGear.
|
||||
|
@ -100,7 +100,7 @@ public interface Gear {
|
|||
* @param <T> The type of entity being rendered.
|
||||
* @param <M> The type of the entity's primary model.
|
||||
*/
|
||||
public interface Context<S extends EntityRenderState, M extends PonyModel<?>> {
|
||||
public interface Context<T extends Entity, M extends PonyModel<?>> {
|
||||
/**
|
||||
* The empty context.
|
||||
*/
|
||||
|
@ -109,7 +109,7 @@ public interface Gear {
|
|||
/**
|
||||
* Checks whether the given wearable and gear are able to render for this specific entity and its renderer.
|
||||
*/
|
||||
default boolean shouldRender(M model, S entity, Wearable wearable, Gear gear) {
|
||||
default boolean shouldRender(M model, T entity, Wearable wearable, Gear gear) {
|
||||
return gear.canRender(model, entity);
|
||||
}
|
||||
|
||||
|
@ -118,6 +118,6 @@ public interface Gear {
|
|||
*
|
||||
* May be the entity's own texture or a specific texture allocated for that wearable.
|
||||
*/
|
||||
Identifier getDefaultTexture(S entity, Wearable wearable);
|
||||
Identifier getDefaultTexture(T entity, Wearable wearable);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
package com.minelittlepony.api.model.gear;
|
||||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.entity.state.EntityRenderState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import com.minelittlepony.api.model.BodyPart;
|
||||
import com.minelittlepony.api.model.PonyModel;
|
||||
import com.minelittlepony.api.pony.meta.Wearable;
|
||||
import com.minelittlepony.client.render.entity.state.PonyRenderState;
|
||||
|
||||
public class WearableGear extends AbstractGearModel {
|
||||
|
||||
protected final Wearable wearable;
|
||||
protected final BodyPart location;
|
||||
|
||||
public WearableGear(ModelPart root, Wearable wearable, BodyPart location, float stackingHeight) {
|
||||
super(root, stackingHeight);
|
||||
public WearableGear(Wearable wearable, BodyPart location, float stackingHeight) {
|
||||
super(stackingHeight);
|
||||
this.wearable = wearable;
|
||||
this.location = location;
|
||||
}
|
||||
|
@ -26,12 +24,12 @@ public class WearableGear extends AbstractGearModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canRender(PonyModel<?> model, EntityRenderState entity) {
|
||||
return entity instanceof PonyRenderState state && state.isWearing(wearable);
|
||||
public boolean canRender(PonyModel<?> model, Entity entity) {
|
||||
return model.isWearing(wearable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends EntityRenderState> Identifier getTexture(S entity, Context<S, ?> context) {
|
||||
public <T extends Entity> Identifier getTexture(T entity, Context<T, ?> context) {
|
||||
return context.getDefaultTexture(entity, wearable);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,35 +1,32 @@
|
|||
package com.minelittlepony.api.pony;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.util.DefaultSkinHelper;
|
||||
import net.minecraft.client.util.SkinTextures;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Util;
|
||||
|
||||
import com.minelittlepony.api.pony.meta.Race;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public final class DefaultPonySkinHelper {
|
||||
public static final Identifier STEVE = Pony.id("textures/entity/player/wide/steve_pony.png");
|
||||
public static final Identifier STEVE = new Identifier("minelittlepony", "textures/entity/player/wide/steve_pony.png");
|
||||
|
||||
public static final Identifier SEAPONY_SKIN_TYPE_ID = Pony.id("seapony");
|
||||
public static final Identifier NIRIK_SKIN_TYPE_ID = Pony.id("nirik");
|
||||
public static final Identifier SEAPONY_SKIN_TYPE_ID = new Identifier("minelp", "seapony");
|
||||
public static final Identifier NIRIK_SKIN_TYPE_ID = new Identifier("minelp", "nirik");
|
||||
|
||||
private static final Function<SkinTextures, SkinTextures> SKINS = Util.memoize(original -> new SkinTextures(
|
||||
Pony.id(original.texture().getPath().replace(".png", "_pony.png")),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
original.model(),
|
||||
false
|
||||
));
|
||||
private static final Map<SkinTextures, SkinTextures> SKINS = new HashMap<>();
|
||||
|
||||
public static SkinTextures getTextures(SkinTextures original) {
|
||||
return SKINS.apply(original);
|
||||
return SKINS.computeIfAbsent(original, o -> {
|
||||
return new SkinTextures(
|
||||
new Identifier("minelittlepony", original.texture().getPath().replace(".png", "_pony.png")),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
original.model(),
|
||||
false
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
public static String getModelType(UUID id) {
|
||||
|
|
|
@ -26,13 +26,6 @@ public record Pony (
|
|||
return PonyManager.Instance.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an identifier for the Mine Little Pony namespace
|
||||
*/
|
||||
public static Identifier id(String name) {
|
||||
return Identifier.of("minelittlepony", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the metadata associated with this pony's model texture.
|
||||
*/
|
||||
|
|
|
@ -6,8 +6,6 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import com.google.common.collect.ComparisonChain;
|
||||
import com.minelittlepony.api.pony.meta.*;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
@ -72,20 +70,6 @@ public record PonyData (
|
|||
private static final Function<Race, PonyData> OF_RACE = Util.memoize(race -> new PonyData(race, TailLength.FULL, TailShape.STRAIGHT, Gender.MARE, SizePreset.NORMAL, DEFAULT_MAGIC_COLOR, true, 0, Wearable.EMPTY_FLAGS));
|
||||
public static final PonyData NULL = OF_RACE.apply(Race.HUMAN);
|
||||
|
||||
public static final Codec<PonyData> CODEC = RecordCodecBuilder.create(i -> {
|
||||
return i.group(
|
||||
Race.CODEC.fieldOf("race").forGetter(PonyData::race),
|
||||
TailLength.CODEC.fieldOf("tailLength").forGetter(PonyData::tailLength),
|
||||
TailShape.CODEC.fieldOf("tailShape").forGetter(PonyData::tailShape),
|
||||
Gender.CODEC.fieldOf("gender").forGetter(PonyData::gender),
|
||||
SizePreset.CODEC.xmap(s -> (Size)s, s -> (SizePreset)s).fieldOf("size").forGetter(PonyData::size),
|
||||
Codec.INT.fieldOf("glowColor").forGetter(PonyData::glowColor),
|
||||
Codec.BOOL.optionalFieldOf("noSkin", false).forGetter(PonyData::noSkin),
|
||||
Codec.INT.optionalFieldOf("priority", 0).forGetter(PonyData::priority),
|
||||
Wearable.FLAGS_CODEC.fieldOf("gear").forGetter(PonyData::gear)
|
||||
).apply(i, PonyData::new);
|
||||
});
|
||||
|
||||
public static PonyData emptyOf(Race race) {
|
||||
return OF_RACE.apply(race);
|
||||
}
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
package com.minelittlepony.api.pony;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.render.entity.EntityRendererFactory;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.client.render.entity.PlayerPonyRenderer;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* The different forms a pony can take.
|
||||
* <p>
|
||||
* The default is land, which is your typical pony with four legs.
|
||||
* Other options are water (seaponies that go shoop-de-doo)
|
||||
* And Niriks (the burning form of kirins)
|
||||
*/
|
||||
@Environment(EnvType.CLIENT)
|
||||
public record PonyForm(Identifier id, Predicate<PlayerEntity> shouldApply, RendererFactory<?> factory) {
|
||||
public static final Identifier DEFAULT = Pony.id("land");
|
||||
public static final Identifier SEAPONY = Pony.id("seapony");
|
||||
public static final Identifier NIRIK = Pony.id("nirik");
|
||||
|
||||
public static final List<Identifier> VALUES = new ArrayList<>();
|
||||
public static final Map<Identifier, PonyForm> REGISTRY = new HashMap<>();
|
||||
|
||||
public static void register(Identifier id, Predicate<PlayerEntity> shouldApply, RendererFactory<?> factory) {
|
||||
VALUES.add(0, id);
|
||||
REGISTRY.put(id, new PonyForm(id, shouldApply, factory));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PonyForm of(PlayerEntity player) {
|
||||
for (Identifier id : VALUES) {
|
||||
PonyForm form = REGISTRY.get(id);
|
||||
if (form != null && form.shouldApply().test(player)) {
|
||||
return form;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public interface RendererFactory<T extends PlayerPonyRenderer> {
|
||||
T create(EntityRendererFactory.Context context, boolean slimArms);
|
||||
}
|
||||
}
|
|
@ -7,8 +7,6 @@ import net.minecraft.util.Identifier;
|
|||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.server.ServerPonyManager;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -73,6 +71,6 @@ public interface PonyManager {
|
|||
interface ForcedPony {}
|
||||
|
||||
final class Instance {
|
||||
public static PonyManager instance = new ServerPonyManager();
|
||||
public static PonyManager instance;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import java.util.Optional;
|
|||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.StairsBlock;
|
||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.registry.tag.FluidTags;
|
||||
|
@ -32,7 +33,7 @@ public final class PonyPosture {
|
|||
Vec3d motion = entity.getVelocity();
|
||||
double zMotion = Math.sqrt(motion.x * motion.x + motion.z * motion.z);
|
||||
|
||||
return (isFlying(entity) && pony.race().hasWings()) || entity.isGliding() & zMotion > 0.4F;
|
||||
return (isFlying(entity) && pony.race().hasWings()) || entity.isFallFlying() & zMotion > 0.4F;
|
||||
}
|
||||
|
||||
public static boolean isFlying(LivingEntity entity) {
|
||||
|
@ -85,24 +86,39 @@ public final class PonyPosture {
|
|||
return isSitting(entity) && getMountPony(entity).map(Pony::race).orElse(Race.HUMAN) != Race.HUMAN;
|
||||
}
|
||||
|
||||
public static boolean isSeaponyModifier(LivingEntity entity) {
|
||||
if (entity instanceof PreviewModel preview) {
|
||||
return preview.forceSeapony();
|
||||
}
|
||||
return hasSeaponyForm(entity) && isPartiallySubmerged(entity);
|
||||
}
|
||||
|
||||
public static boolean hasSeaponyForm(LivingEntity entity) {
|
||||
if (entity instanceof PreviewModel preview) {
|
||||
return preview.getForm() == PonyForm.SEAPONY;
|
||||
return preview.forceSeapony();
|
||||
}
|
||||
return Pony.getManager().getPony(entity).filter(pony -> {
|
||||
return (pony.race() == Race.SEAPONY
|
||||
|| (entity instanceof PlayerEntity player && SkinsProxy.getInstance().getSkin(DefaultPonySkinHelper.SEAPONY_SKIN_TYPE_ID, player).isPresent())
|
||||
|| (entity instanceof AbstractClientPlayerEntity player && SkinsProxy.instance.getSkin(DefaultPonySkinHelper.SEAPONY_SKIN_TYPE_ID, player).isPresent())
|
||||
);
|
||||
}).isPresent();
|
||||
}
|
||||
|
||||
public static boolean isNirikModifier(LivingEntity entity) {
|
||||
if (entity instanceof PreviewModel preview) {
|
||||
return preview.forceNirik();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static boolean hasNirikForm(LivingEntity entity) {
|
||||
if (entity instanceof PreviewModel preview) {
|
||||
return preview.getForm() == PonyForm.NIRIK;
|
||||
return preview.forceNirik();
|
||||
}
|
||||
return Pony.getManager().getPony(entity).filter(pony -> {
|
||||
return (pony.race() == Race.KIRIN
|
||||
&& (entity instanceof PlayerEntity player && SkinsProxy.getInstance().getSkin(DefaultPonySkinHelper.NIRIK_SKIN_TYPE_ID, player).isPresent())
|
||||
&& (entity instanceof AbstractClientPlayerEntity player && SkinsProxy.instance.getSkin(DefaultPonySkinHelper.NIRIK_SKIN_TYPE_ID, player).isPresent())
|
||||
);
|
||||
}).isPresent();
|
||||
}
|
||||
|
|
|
@ -1,60 +1,28 @@
|
|||
package com.minelittlepony.api.pony;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.google.common.cache.*;
|
||||
import com.minelittlepony.server.MineLittlePonyServer;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.minecraft.MinecraftProfileTextures;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||
import net.minecraft.client.texture.PlayerSkinProvider;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
/**
|
||||
* Proxy handler for getting player skin data from HDSkins
|
||||
*/
|
||||
public class SkinsProxy {
|
||||
public static SkinsProxy INSTANCE = new SkinsProxy();
|
||||
private static final SkinsProxy DEFAULT = INSTANCE;
|
||||
public static SkinsProxy instance = new SkinsProxy();
|
||||
|
||||
private final LoadingCache<GameProfile, GameProfile> profileCache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(30, TimeUnit.SECONDS)
|
||||
.build(CacheLoader.from(profile -> {
|
||||
var result = MineLittlePonyServer.getServer().getSessionService().fetchProfile(profile.getId(), false);
|
||||
return result == null ? profile : result.profile();
|
||||
}));
|
||||
|
||||
public static SkinsProxy getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
protected SkinsProxy() {
|
||||
if (INSTANCE == DEFAULT) {
|
||||
INSTANCE = this;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Identifier getSkinTexture(GameProfile profile) {
|
||||
MinecraftServer server = MineLittlePonyServer.getServer();
|
||||
if (server != null) {
|
||||
profile = profileCache.getUnchecked(profile);
|
||||
|
||||
MinecraftProfileTextures textures = server.getSessionService().getTextures(profile);
|
||||
|
||||
if (textures != MinecraftProfileTextures.EMPTY) {
|
||||
return Identifier.of(textures.skin().getUrl());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
PlayerSkinProvider skins = MinecraftClient.getInstance().getSkinProvider();
|
||||
return skins.getSkinTextures(profile).texture();
|
||||
}
|
||||
|
||||
public Optional<Identifier> getSkin(Identifier skinTypeId, PlayerEntity player) {
|
||||
public Optional<Identifier> getSkin(Identifier skinTypeId, AbstractClientPlayerEntity player) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,7 @@ package com.minelittlepony.api.pony.meta;
|
|||
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public record Flags<T extends Enum<T> & TValue<T>> (
|
||||
T def,
|
||||
|
@ -15,15 +10,6 @@ public record Flags<T extends Enum<T> & TValue<T>> (
|
|||
int colorCode
|
||||
) implements Comparable<Flags<T>>, TValue<T> {
|
||||
|
||||
public static <T extends Enum<T> & TValue<T>> Codec<Flags<T>> codec(T def, Codec<T> elementCodec) {
|
||||
Codec<Set<T>> setCodec = Codec.list(elementCodec).xmap(elements -> elements.stream().distinct().collect(Collectors.toUnmodifiableSet()), set -> List.copyOf(set));
|
||||
return Codec.xor(setCodec.xmap(elements -> new Flags<>(def, elements, 0), flags -> flags.values()), RecordCodecBuilder.<Flags<T>>create(i -> i.group(
|
||||
elementCodec.fieldOf("def").forGetter(Flags::def),
|
||||
setCodec.fieldOf("values").forGetter(Flags::values),
|
||||
Codec.INT.fieldOf("colorCode").forGetter(Flags::colorCode)
|
||||
).apply(i, Flags::new))).xmap(Either::unwrap, Either::left);
|
||||
}
|
||||
|
||||
public static <T extends Enum<T> & TValue<T>> Flags<T> of(T def) {
|
||||
return new Flags<>(def, Set.<T>of(), 0);
|
||||
}
|
||||
|
@ -41,7 +27,7 @@ public record Flags<T extends Enum<T> & TValue<T>> (
|
|||
for (int i = 0; i < length; i++) {
|
||||
values.add(all[buffer.readInt()]);
|
||||
}
|
||||
return of(def, buffer.readInt(), values);
|
||||
return new Flags<>(def, values, buffer.readInt());
|
||||
}
|
||||
|
||||
public void write(PacketByteBuf buffer) {
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
package com.minelittlepony.api.pony.meta;
|
||||
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
|
||||
public enum Gender implements TValue<Gender> {
|
||||
MARE(0),
|
||||
STALLION(0xffffff),
|
||||
ABOMONATION(0x888888);
|
||||
|
||||
public static final Codec<Gender> CODEC = StringIdentifiable.createCodec(Gender::values);
|
||||
|
||||
private int triggerValue;
|
||||
|
||||
Gender(int pixel) {
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
package com.minelittlepony.api.pony.meta;
|
||||
|
||||
import net.minecraft.util.math.ColorHelper;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.Raster;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
|
||||
public interface Mats {
|
||||
static TriggerPixel.Mat createMat(MinecraftProfileTexture texture) throws IOException {
|
||||
return createMat(URI.create(texture.getUrl()).toURL());
|
||||
}
|
||||
|
||||
static TriggerPixel.Mat createMat(URL url) throws IOException {
|
||||
try {
|
||||
@Nullable
|
||||
BufferedImage image = ImageIO.read(url);
|
||||
if (image == null) {
|
||||
throw new IOException("Unable to read image from url " + url);
|
||||
}
|
||||
Raster raster = image.getData();
|
||||
return (x, y) -> {
|
||||
if (x < 0 || y < 0 || x > raster.getWidth() || y > raster.getHeight()) {
|
||||
return 0;
|
||||
}
|
||||
int[] color = raster.getPixel(x, y, new int[] {0, 0, 0, 0});
|
||||
return ColorHelper.getArgb(color[3], color[0], color[1], color[2]);
|
||||
};
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IOException("Could not create mat from image", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,5 @@
|
|||
package com.minelittlepony.api.pony.meta;
|
||||
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
|
||||
public enum Race implements TValue<Race> {
|
||||
HUMAN (0x000000, false, false),
|
||||
EARTH (0xf9b131, false, false),
|
||||
|
@ -19,8 +15,6 @@ public enum Race implements TValue<Race> {
|
|||
BATPONY (0xeeeeee, true, false),
|
||||
SEAPONY (0x3655dd, false, true);
|
||||
|
||||
public static final Codec<Race> CODEC = StringIdentifiable.createCodec(Race::values);
|
||||
|
||||
private final boolean wings;
|
||||
private final boolean horn;
|
||||
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package com.minelittlepony.api.pony.meta;
|
||||
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
|
||||
import com.minelittlepony.api.config.PonyConfig;
|
||||
import com.mojang.serialization.Codec;
|
||||
|
||||
/**
|
||||
* Represents the different model sizes that are possible.
|
||||
|
@ -17,14 +14,10 @@ public enum SizePreset implements Size {
|
|||
BULKY (0xce3254, 0.5f, 1, 1.05F),
|
||||
LANKY (0x3254ce, 0.45F, 0.85F, 0.9F),
|
||||
NORMAL (0x000000, 0.4f, 0.8F, 0.8F),
|
||||
STOCKY (0xb2e7dd, 0.45F, 0.8F, 0.8F),
|
||||
SQUAT (0xa3d2c7, 0.4F, 0.7F, 0.67F),
|
||||
YEARLING(0x53beff, 0.4F, 0.6F, 0.65F),
|
||||
FOAL (0xffbe53, 0.25f, 0.6F, 0.5F),
|
||||
UNSET (0x000000, 1, 1, 1);
|
||||
|
||||
public static final Codec<SizePreset> CODEC = StringIdentifiable.createCodec(SizePreset::values);
|
||||
|
||||
private final int triggerValue;
|
||||
private final float shadowSize;
|
||||
private final float scale;
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
package com.minelittlepony.api.pony.meta;
|
||||
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Interface for enums that can be parsed from an image trigger pixel value.
|
||||
*/
|
||||
public interface TValue<T> extends StringIdentifiable {
|
||||
public interface TValue<T> {
|
||||
/**
|
||||
* Gets the pixel colour matching this enum value.
|
||||
*/
|
||||
|
@ -26,11 +24,6 @@ public interface TValue<T> extends StringIdentifiable {
|
|||
*/
|
||||
String name();
|
||||
|
||||
@Override
|
||||
default String asString() {
|
||||
return name();
|
||||
}
|
||||
|
||||
default String getHexValue() {
|
||||
return toHex(colorCode());
|
||||
}
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
package com.minelittlepony.api.pony.meta;
|
||||
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
|
||||
public enum TailLength implements TValue<TailLength> {
|
||||
STUB (0x425844),
|
||||
QUARTER (0xd19fe4),
|
||||
|
@ -11,8 +7,6 @@ public enum TailLength implements TValue<TailLength> {
|
|||
THREE_QUARTERS (0x8a6b7f),
|
||||
FULL (0x000000);
|
||||
|
||||
public static final Codec<TailLength> CODEC = StringIdentifiable.createCodec(TailLength::values);
|
||||
|
||||
private int triggerValue;
|
||||
|
||||
TailLength(int pixel) {
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
package com.minelittlepony.api.pony.meta;
|
||||
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
|
||||
public enum TailShape implements TValue<TailShape> {
|
||||
STRAIGHT(0),
|
||||
BUMPY (0xfc539f),
|
||||
SWIRLY (0x3eff22),
|
||||
SPIKY (0x3308c7);
|
||||
|
||||
public static final Codec<TailShape> CODEC = StringIdentifiable.createCodec(TailShape::values);
|
||||
|
||||
private int triggerValue;
|
||||
|
||||
TailShape(int pixel) {
|
||||
|
|
|
@ -5,6 +5,8 @@ import net.minecraft.util.math.ColorHelper;
|
|||
|
||||
import org.joml.Vector2i;
|
||||
|
||||
import com.minelittlepony.common.util.Color;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
|
@ -27,9 +29,9 @@ public interface TriggerPixel<T> {
|
|||
MAX_COORDS.y = Math.max(MAX_COORDS.y, y);
|
||||
Int2ObjectOpenHashMap<T> lookup = buildLookup(options);
|
||||
return image -> {
|
||||
int color = image.getColor(x, y);
|
||||
int color = Color.abgrToArgb(image.getColor(x, y));
|
||||
|
||||
if (ColorHelper.getAlpha(color) < 255) {
|
||||
if (ColorHelper.Argb.getAlpha(color) < 255) {
|
||||
return (T)def;
|
||||
}
|
||||
return lookup.getOrDefault(color & 0x00FFFFFF, def);
|
||||
|
@ -39,7 +41,7 @@ public interface TriggerPixel<T> {
|
|||
static TriggerPixel<Integer> ofColor(int x, int y) {
|
||||
MAX_COORDS.x = Math.max(MAX_COORDS.x, x);
|
||||
MAX_COORDS.y = Math.max(MAX_COORDS.y, y);
|
||||
return image -> image.getColor(x, y);
|
||||
return image -> Color.abgrToArgb(image.getColor(x, y));
|
||||
}
|
||||
|
||||
static <T extends Enum<T> & TValue<T>> TriggerPixel<Flags<T>> ofFlags(int x, int y, Flags<T> def, T[] options) {
|
||||
|
@ -53,15 +55,15 @@ public interface TriggerPixel<T> {
|
|||
}
|
||||
};
|
||||
return image -> {
|
||||
int color = image.getColor(x, y);
|
||||
if (ColorHelper.getAlpha(color) < 255) {
|
||||
int color = Color.abgrToArgb(image.getColor(x, y));
|
||||
if (ColorHelper.Argb.getAlpha(color) < 255) {
|
||||
return def;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<T> values = EnumSet.noneOf((Class<T>)def.def().getClass());
|
||||
if (flagReader.readFlag(ColorHelper.getRed(color), values)
|
||||
| flagReader.readFlag(ColorHelper.getGreen(color), values)
|
||||
| flagReader.readFlag(ColorHelper.getBlue(color), values)) {
|
||||
if (flagReader.readFlag(ColorHelper.Argb.getRed(color), values)
|
||||
| flagReader.readFlag(ColorHelper.Argb.getGreen(color), values)
|
||||
| flagReader.readFlag(ColorHelper.Argb.getBlue(color), values)) {
|
||||
return new Flags<>(def.def(), values, color & 0x00FFFFFF);
|
||||
}
|
||||
return def;
|
||||
|
|
|
@ -1,26 +1,22 @@
|
|||
package com.minelittlepony.api.pony.meta;
|
||||
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
import net.minecraft.util.math.ColorHelper;
|
||||
|
||||
import com.minelittlepony.api.pony.Pony;
|
||||
import com.mojang.serialization.Codec;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public enum Wearable implements TValue<Wearable> {
|
||||
NONE (0x00, null),
|
||||
CROWN (0x16, Pony.id("textures/models/crown.png")),
|
||||
MUFFIN (0x32, Pony.id("textures/models/muffin.png")),
|
||||
HAT (0x64, Identifier.ofVanilla("textures/entity/witch.png")),
|
||||
ANTLERS (0x96, Pony.id("textures/models/antlers.png")),
|
||||
SADDLE_BAGS_LEFT (0xC6, Pony.id("textures/models/saddlebags.png")),
|
||||
SADDLE_BAGS_RIGHT (0xC7, Pony.id("textures/models/saddlebags.png")),
|
||||
SADDLE_BAGS_BOTH (0xC8, Pony.id("textures/models/saddlebags.png")),
|
||||
STETSON (0xFA, Pony.id("textures/models/stetson.png"));
|
||||
CROWN (0x16, new Identifier("minelittlepony", "textures/models/crown.png")),
|
||||
MUFFIN (0x32, new Identifier("minelittlepony", "textures/models/muffin.png")),
|
||||
HAT (0x64, new Identifier("textures/entity/witch.png")),
|
||||
ANTLERS (0x96, new Identifier("minelittlepony", "textures/models/antlers.png")),
|
||||
SADDLE_BAGS_LEFT (0xC6, new Identifier("minelittlepony", "textures/models/saddlebags.png")),
|
||||
SADDLE_BAGS_RIGHT (0xC7, new Identifier("minelittlepony", "textures/models/saddlebags.png")),
|
||||
SADDLE_BAGS_BOTH (0xC8, new Identifier("minelittlepony", "textures/models/saddlebags.png")),
|
||||
STETSON (0xFA, new Identifier("minelittlepony", "textures/models/stetson.png"));
|
||||
|
||||
private int triggerValue;
|
||||
|
||||
|
@ -31,12 +27,9 @@ public enum Wearable implements TValue<Wearable> {
|
|||
|
||||
public static final Flags<Wearable> EMPTY_FLAGS = Flags.of(NONE);
|
||||
|
||||
public static final Codec<Wearable> CODEC = StringIdentifiable.createCodec(Wearable::values);
|
||||
public static final Codec<Flags<Wearable>> FLAGS_CODEC = Flags.codec(NONE, CODEC);
|
||||
|
||||
Wearable(int pixel, Identifier texture) {
|
||||
triggerValue = pixel;
|
||||
id = Pony.id(name().toLowerCase(Locale.ROOT));
|
||||
id = new Identifier("minelittlepony", name().toLowerCase(Locale.ROOT));
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
|
@ -59,6 +52,6 @@ public enum Wearable implements TValue<Wearable> {
|
|||
|
||||
@Override
|
||||
public int getChannelAdjustedColorCode() {
|
||||
return triggerValue == 0 ? 0 : ColorHelper.getArgb(255, triggerValue, triggerValue, triggerValue);
|
||||
return triggerValue == 0 ? 0 : ColorHelper.Argb.getArgb(255, triggerValue, triggerValue, triggerValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
package com.minelittlepony.client;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.api.pony.SkinsProxy;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
public class ClientSkinsProxy extends SkinsProxy {
|
||||
@Nullable
|
||||
public Identifier getSkinTexture(GameProfile profile) {
|
||||
return MinecraftClient.getInstance().getSkinProvider().getSkinTextures(profile).texture();
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@ package com.minelittlepony.client;
|
|||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerPosition;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.*;
|
||||
|
||||
|
@ -21,11 +20,11 @@ public class HorseCam {
|
|||
* Restores the previous camera (unadjusted) angle for the client when the server sends an update.
|
||||
* This is to prevent issues caused by the server updating our pitch whenever the player leaves a portal.
|
||||
*/
|
||||
public static PlayerPosition transformIncomingServerCameraAngle(PlayerPosition change) {
|
||||
if (MathHelper.approximatelyEquals(change.pitch(), lastComputedPitch)) {
|
||||
return new PlayerPosition(change.position(), change.deltaMovement(), change.yaw(), lastOriginalPitch);
|
||||
public static float transformIncomingServerCameraAngle(float serverPitch) {
|
||||
if (MathHelper.approximatelyEquals(serverPitch, lastComputedPitch)) {
|
||||
return lastOriginalPitch;
|
||||
}
|
||||
return change;
|
||||
return serverPitch;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,7 +87,7 @@ public class HorseCam {
|
|||
public static float rescaleCameraPitch(double toHeight, float originalPitch) {
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
PlayerEntity player = client.player;
|
||||
client.gameRenderer.updateCrosshairTarget(client.getRenderTickCounter().getTickDelta(false));
|
||||
client.gameRenderer.updateTargetedEntity(client.getTickDelta());
|
||||
HitResult hit = client.crosshairTarget;
|
||||
|
||||
if (client.targetedEntity != null) {
|
||||
|
|
|
@ -14,8 +14,8 @@ import static com.minelittlepony.common.event.SkinFilterCallback.copy;
|
|||
*/
|
||||
class LegacySkinConverter implements SkinFilterCallback {
|
||||
@Override
|
||||
public NativeImage processImage(NativeImage image, int initialWidth, int initialHeight) {
|
||||
if (SkinFilterCallback.isLegacyAspectRatio(initialWidth, initialHeight)) {
|
||||
public void processImage(NativeImage image, boolean legacy) {
|
||||
if (legacy) {
|
||||
// ( from ) ( offset ) (size) flipX flipY
|
||||
copy(image, 58, 16, 0, 16, 2, 2, true, false); // top
|
||||
copy(image, 60, 16, 0, 16, 2, 2, true, false); // bottom
|
||||
|
@ -24,7 +24,5 @@ class LegacySkinConverter implements SkinFilterCallback {
|
|||
copy(image, 56, 18, 4, 16, 2, 14, true, false); // outside
|
||||
copy(image, 62, 18, 0, 16, 2, 14, true, false); // front
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.minelittlepony.client;
|
||||
|
||||
import com.minelittlepony.api.config.PonyConfig;
|
||||
import com.minelittlepony.api.events.ClientChannel;
|
||||
import com.minelittlepony.api.events.Channel;
|
||||
import com.minelittlepony.client.model.ModelType;
|
||||
import com.minelittlepony.client.model.armour.ArmourTextureResolver;
|
||||
import com.minelittlepony.client.render.MobRenderers;
|
||||
|
@ -9,12 +9,12 @@ import com.minelittlepony.client.render.PonyRenderDispatcher;
|
|||
import com.minelittlepony.common.client.gui.VisibilityMode;
|
||||
import com.minelittlepony.common.client.gui.element.Button;
|
||||
import com.minelittlepony.common.client.gui.sprite.TextureSprite;
|
||||
import com.minelittlepony.common.event.ClientReadyCallback;
|
||||
import com.minelittlepony.common.event.ScreenInitCallback;
|
||||
import com.minelittlepony.common.event.SkinFilterCallback;
|
||||
import com.minelittlepony.common.util.GamePaths;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||
|
@ -40,7 +40,7 @@ public class MineLittlePony implements ClientModInitializer {
|
|||
|
||||
private static MineLittlePony instance;
|
||||
|
||||
public static final Logger LOGGER = LogManager.getLogger("MineLittlePony");
|
||||
public static final Logger logger = LogManager.getLogger("MineLittlePony");
|
||||
|
||||
private PonyManagerImpl ponyManager;
|
||||
private VariatedTextureSupplier variatedTextures;
|
||||
|
@ -48,8 +48,6 @@ public class MineLittlePony implements ClientModInitializer {
|
|||
private final KeyBinding keyBinding = new KeyBinding("key.minelittlepony.settings", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_F9, "key.categories.misc");
|
||||
|
||||
private final PonyRenderDispatcher renderDispatcher = new PonyRenderDispatcher();
|
||||
private final AtomicBoolean initialized = new AtomicBoolean();
|
||||
private final AtomicBoolean configChanged = new AtomicBoolean();
|
||||
|
||||
private boolean hasHdSkins;
|
||||
private boolean hasModMenu;
|
||||
|
@ -65,10 +63,6 @@ public class MineLittlePony implements ClientModInitializer {
|
|||
return instance;
|
||||
}
|
||||
|
||||
public static Identifier id(String name) {
|
||||
return Identifier.of("minelittlepony", name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
hasHdSkins = FabricLoader.getInstance().isModLoaded("hdskins");
|
||||
|
@ -82,34 +76,27 @@ public class MineLittlePony implements ClientModInitializer {
|
|||
|
||||
ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(ponyManager);
|
||||
ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(variatedTextures);
|
||||
ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(ArmourTextureResolver.INSTANCE);
|
||||
|
||||
// convert legacy pony skins
|
||||
SkinFilterCallback.EVENT.register(new LegacySkinConverter());
|
||||
|
||||
// general events
|
||||
ClientReadyCallback.Handler.register();
|
||||
ClientTickEvents.END_CLIENT_TICK.register(this::onTick);
|
||||
ClientReadyCallback.EVENT.register(client -> {
|
||||
renderDispatcher.initialise(client.getEntityRenderDispatcher(), false);
|
||||
});
|
||||
ScreenInitCallback.EVENT.register(this::onScreenInit);
|
||||
|
||||
new ClientSkinsProxy();
|
||||
|
||||
config.load();
|
||||
config.onChangedExternally(c -> configChanged.set(true));
|
||||
|
||||
ClientChannel.bootstrap();
|
||||
Channel.bootstrap();
|
||||
ModelType.bootstrap();
|
||||
|
||||
FabricLoader.getInstance().getEntrypoints("minelittlepony", ClientModInitializer.class).forEach(ClientModInitializer::onInitializeClient);
|
||||
}
|
||||
|
||||
private void onTick(MinecraftClient client) {
|
||||
if (!initialized.getAndSet(true)) {
|
||||
renderDispatcher.initialise(client.getEntityRenderDispatcher(), false);
|
||||
}
|
||||
|
||||
if (configChanged.getAndSet(false) && client.currentScreen instanceof PonySettingsScreen screen) {
|
||||
screen.init(client, screen.width, screen.height);
|
||||
}
|
||||
|
||||
boolean inGame = client.world != null && client.player != null && client.currentScreen == null;
|
||||
boolean mainMenu = client.currentScreen instanceof TitleScreen;
|
||||
|
@ -137,7 +124,7 @@ public class MineLittlePony implements ClientModInitializer {
|
|||
button.getStyle()
|
||||
.setIcon(new TextureSprite()
|
||||
.setPosition(2, 2)
|
||||
.setTexture(id("textures/gui/pony.png"))
|
||||
.setTexture(new Identifier("minelittlepony", "textures/gui/pony.png"))
|
||||
.setTextureSize(16, 16)
|
||||
.setSize(16, 16))
|
||||
.setTooltip("minelp.options.title", 0, 10);
|
||||
|
@ -164,7 +151,7 @@ public class MineLittlePony implements ClientModInitializer {
|
|||
private static final class ClientPonyConfig extends PonyConfig {
|
||||
public ClientPonyConfig(Path path) {
|
||||
super(path);
|
||||
MobRenderers.REGISTRY.values().forEach(r -> value("entities", r.name(), true));
|
||||
MobRenderers.REGISTRY.values().forEach(r -> value("entities", r.name, true));
|
||||
disablePonifiedArmour.onChanged(t -> ArmourTextureResolver.INSTANCE.invalidate());
|
||||
}
|
||||
|
||||
|
|
50
src/main/java/com/minelittlepony/client/PonyBounds.java
Normal file
50
src/main/java/com/minelittlepony/client/PonyBounds.java
Normal file
|
@ -0,0 +1,50 @@
|
|||
package com.minelittlepony.client;
|
||||
|
||||
import com.minelittlepony.api.pony.Pony;
|
||||
import com.minelittlepony.api.pony.PonyPosture;
|
||||
import com.minelittlepony.client.transform.PonyTransformation;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class PonyBounds {
|
||||
public static Vec3d getAbsoluteRidingOffset(LivingEntity entity) {
|
||||
return PonyPosture.getMountPony(entity).map(ridingPony -> {
|
||||
LivingEntity vehicle = (LivingEntity)entity.getVehicle();
|
||||
|
||||
Vec3d offset = PonyTransformation.forSize(ridingPony.size()).getRiderOffset();
|
||||
float scale = ridingPony.metadata().size().scaleFactor();
|
||||
|
||||
return getAbsoluteRidingOffset(vehicle).add(
|
||||
0,
|
||||
offset.y - vehicle.getHeight() * 1 / scale,
|
||||
0
|
||||
);
|
||||
}).orElseGet(() -> getBaseRidingOffset(entity));
|
||||
}
|
||||
|
||||
private static Vec3d getBaseRidingOffset(LivingEntity entity) {
|
||||
float delta = MinecraftClient.getInstance().getTickDelta();
|
||||
|
||||
Entity vehicle = entity.getVehicle();
|
||||
double vehicleOffset = vehicle == null ? 0 : vehicle.getHeight();
|
||||
|
||||
return new Vec3d(
|
||||
MathHelper.lerp(delta, entity.prevX, entity.getX()),
|
||||
MathHelper.lerp(delta, entity.prevY, entity.getY()) + vehicleOffset,
|
||||
MathHelper.lerp(delta, entity.prevZ, entity.getZ())
|
||||
);
|
||||
}
|
||||
|
||||
public static Box getBoundingBox(Pony pony, LivingEntity entity) {
|
||||
final float scale = pony.size().scaleFactor() + 0.1F;
|
||||
final float width = entity.getWidth() * scale;
|
||||
final float height = entity.getHeight() * scale;
|
||||
|
||||
return new Box(-width, height, -width, width, 0, width).offset(getAbsoluteRidingOffset(entity));
|
||||
}
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
package com.minelittlepony.client;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.resource.metadata.ResourceMetadataSerializer;
|
||||
import net.minecraft.resource.metadata.ResourceMetadataReader;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.minelittlepony.api.pony.PonyData;
|
||||
import com.minelittlepony.client.util.render.NativeUtil;
|
||||
|
||||
|
@ -14,9 +15,23 @@ import java.util.function.Supplier;
|
|||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PonyDataLoader {
|
||||
public static final Supplier<Optional<PonyData>> NULL = loaded(PonyData.NULL);
|
||||
private static final ResourceMetadataSerializer<PonyData> SERIALIZER = new ResourceMetadataSerializer<PonyData>("pony", PonyData.CODEC);
|
||||
class PonyDataLoader {
|
||||
static final Supplier<Optional<PonyData>> NULL = loaded(PonyData.NULL);
|
||||
private static final ResourceMetadataReader<PonyData> SERIALIZER = new ResourceMetadataReader<PonyData>() {
|
||||
private static final Gson GSON = new GsonBuilder()
|
||||
.excludeFieldsWithoutExposeAnnotation()
|
||||
.create();
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "pony";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PonyData fromJson(JsonObject json) {
|
||||
return GSON.fromJson(json, PonyData.class);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses the given resource into a new IPonyData.
|
||||
|
@ -31,7 +46,7 @@ public class PonyDataLoader {
|
|||
try {
|
||||
return res.getMetadata().decode(SERIALIZER);
|
||||
} catch (IOException e) {
|
||||
MineLittlePony.LOGGER.warn("Unable to read {} metadata", identifier, e);
|
||||
MineLittlePony.logger.warn("Unable to read {} metadata", identifier, e);
|
||||
}
|
||||
return Optional.empty();
|
||||
}).map(PonyDataLoader::loaded).orElseGet(() -> {
|
||||
|
@ -39,7 +54,7 @@ public class PonyDataLoader {
|
|||
NativeUtil.parseImage(identifier, image -> {
|
||||
callback.accept(new PonyData(image, noSkin));
|
||||
}, e -> {
|
||||
MineLittlePony.LOGGER.fatal("Unable to read {} metadata", identifier, e);
|
||||
MineLittlePony.logger.fatal("Unable to read {} metadata", identifier, e);
|
||||
callback.accept(PonyData.NULL);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,41 +1,39 @@
|
|||
package com.minelittlepony.client;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.cache.*;
|
||||
import com.minelittlepony.api.config.PonyConfig;
|
||||
import com.minelittlepony.api.config.PonyLevel;
|
||||
import com.minelittlepony.api.events.PonySkinResolver;
|
||||
import com.minelittlepony.api.pony.*;
|
||||
import com.minelittlepony.client.render.blockentity.skull.PonySkullRenderer;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||
import net.minecraft.client.render.entity.LivingEntityRenderer;
|
||||
import net.minecraft.client.render.entity.state.LivingEntityRenderState;
|
||||
import net.minecraft.client.util.DefaultSkinHelper;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceReloadListener {
|
||||
private static final Identifier ID = MineLittlePony.id("background_ponies");
|
||||
private static final Identifier ID = new Identifier("minelittlepony", "background_ponies");
|
||||
|
||||
private final PonyConfig config;
|
||||
|
||||
private final LoadingCache<Key, Pony> poniesCache = CacheBuilder.newBuilder()
|
||||
private final LoadingCache<Identifier, Pony> defaultedPoniesCache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(30, TimeUnit.SECONDS)
|
||||
.build(CacheLoader.from(key -> new Pony(key.texture(), PonyDataLoader.parse(key.texture(), key.defaulted()))));
|
||||
private final WeakHashMap<UUID, Pony> playerPonies = new WeakHashMap<>();
|
||||
.build(CacheLoader.from(resource -> new Pony(resource, PonyDataLoader.parse(resource, true))));
|
||||
|
||||
record Key(Identifier texture, boolean defaulted) {}
|
||||
private final LoadingCache<Identifier, Pony> poniesCache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(30, TimeUnit.SECONDS)
|
||||
.build(CacheLoader.from(resource -> new Pony(resource, PonyDataLoader.parse(resource, false))));
|
||||
|
||||
public PonyManagerImpl(PonyConfig config) {
|
||||
this.config = config;
|
||||
|
@ -44,7 +42,7 @@ public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceRe
|
|||
|
||||
private Pony loadPony(Identifier resource, boolean defaulted) {
|
||||
try {
|
||||
return poniesCache.get(new Key(resource, defaulted));
|
||||
return (defaulted ? defaultedPoniesCache : poniesCache).get(resource);
|
||||
} catch (ExecutionException e) {
|
||||
return new Pony(resource, PonyDataLoader.NULL);
|
||||
}
|
||||
|
@ -52,26 +50,7 @@ public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceRe
|
|||
|
||||
@Override
|
||||
public Pony getPony(PlayerEntity player) {
|
||||
final UUID id = player instanceof ForcedPony ? null : player.getGameProfile() == null || player.getGameProfile().getId() == null ? player.getUuid() : player.getGameProfile().getId();
|
||||
|
||||
Pony pony;
|
||||
if (player instanceof ServerPlayerEntity && id != null) {
|
||||
pony = playerPonies.get(id);
|
||||
if (pony != null) {
|
||||
return pony;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Identifier skin = getSkin(player);
|
||||
if (skin != null) {
|
||||
skin = MoreObjects.firstNonNull(PonySkinResolver.EVENT.invoker().onPonySkinResolving(player, s -> getPony(s, id), skin), skin);
|
||||
}
|
||||
pony = getPony(skin, id);
|
||||
if (!(player instanceof ServerPlayerEntity) && id != null) {
|
||||
playerPonies.put(id, pony);
|
||||
}
|
||||
return pony;
|
||||
return getPony(getSkin(player), player instanceof ForcedPony ? null : player.getGameProfile() == null ? player.getUuid() : player.getGameProfile().getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -79,11 +58,7 @@ public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceRe
|
|||
if (entity instanceof PlayerEntity player) {
|
||||
return Optional.of(getPony(player));
|
||||
}
|
||||
@Nullable
|
||||
Identifier skin = getSkin(entity);
|
||||
if (skin != null) {
|
||||
skin = MoreObjects.firstNonNull(PonySkinResolver.EVENT.invoker().onPonySkinResolving(entity, s -> getPony(s, null), skin), skin);
|
||||
}
|
||||
return skin == null ? Optional.empty() : Optional.of(getPony(skin, null));
|
||||
}
|
||||
|
||||
|
@ -109,7 +84,6 @@ public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceRe
|
|||
return loadPony(DefaultSkinHelper.getSkinTextures(uuid).texture(), true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
private Identifier getSkin(LivingEntity entity) {
|
||||
if (entity instanceof PlayerEntity player) {
|
||||
|
@ -117,8 +91,8 @@ public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceRe
|
|||
return clientPlayer.getSkinTextures().texture();
|
||||
}
|
||||
} else {
|
||||
if (MineLittlePony.getInstance().getRenderDispatcher().getPonyRenderer(entity) instanceof LivingEntityRenderer renderer) {
|
||||
return renderer.getTexture((LivingEntityRenderState)renderer.getAndUpdateRenderState(entity, 1));
|
||||
if (MineLittlePony.getInstance().getRenderDispatcher().getPonyRenderer(entity) != null) {
|
||||
return MinecraftClient.getInstance().getEntityRenderDispatcher().getRenderer(entity).getTexture(entity);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,17 +101,19 @@ public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceRe
|
|||
|
||||
public void removePony(Identifier resource) {
|
||||
poniesCache.invalidate(resource);
|
||||
defaultedPoniesCache.invalidate(resource);
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
MineLittlePony.LOGGER.info("Turned {} cached ponies into cupcakes.", poniesCache.size());
|
||||
MineLittlePony.logger.info("Flushed {} cached ponies.", poniesCache.size());
|
||||
poniesCache.invalidateAll();
|
||||
defaultedPoniesCache.invalidateAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(ResourceManager manager) {
|
||||
public void reload(ResourceManager var1) {
|
||||
clearCache();
|
||||
PonySkullRenderer.INSTANCE.reload();
|
||||
PonySkullRenderer.reload();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -136,11 +136,10 @@ public class PonySettingsScreen extends GameGui {
|
|||
|
||||
if (hiddenOptions) {
|
||||
for (Setting<?> i : config.getCategory("customisation").entries()) {
|
||||
if (i.get() instanceof Boolean value) {
|
||||
content.addButton(new Toggle(LEFT, row += 20, value))
|
||||
.onChange((Setting<Boolean>)i)
|
||||
.getStyle().setText(OPTIONS_PREFIX + i.name().toLowerCase());
|
||||
}
|
||||
Button button = content
|
||||
.addButton(new Toggle(LEFT, row += 20, ((Setting<Boolean>)i).get()))
|
||||
.onChange((Setting<Boolean>)i);
|
||||
button.getStyle().setText(OPTIONS_PREFIX + i.name().toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,9 +156,9 @@ public class PonySettingsScreen extends GameGui {
|
|||
|
||||
content.addButton(new Label(RIGHT, row)).getStyle().setText(MOB_PREFIX + "title");
|
||||
for (MobRenderers i : MobRenderers.REGISTRY.values()) {
|
||||
content.addButton(new Toggle(RIGHT, row += 20, i.option()))
|
||||
.onChange(i.option())
|
||||
.getStyle().setText(MOB_PREFIX + i.name());
|
||||
content.addButton(new Toggle(RIGHT, row += 20, i.get()))
|
||||
.onChange(i::set)
|
||||
.getStyle().setText(MOB_PREFIX + i.name);
|
||||
}
|
||||
|
||||
row += 15;
|
||||
|
|
|
@ -11,9 +11,9 @@ import com.minelittlepony.util.MathUtil;
|
|||
import java.util.*;
|
||||
|
||||
public class VariatedTextureSupplier implements SimpleSynchronousResourceReloadListener {
|
||||
private static final Identifier ID = MineLittlePony.id("variated_textures");
|
||||
public static final Identifier BACKGROUND_PONIES_POOL = MineLittlePony.id("textures/entity/pony");
|
||||
public static final Identifier BACKGROUND_ZOMPONIES_POOL = MineLittlePony.id("textures/entity/zompony");
|
||||
private static final Identifier ID = new Identifier("minelittlepony", "variated_textures");
|
||||
public static final Identifier BACKGROUND_PONIES_POOL = new Identifier("minelittlepony", "textures/entity/pony");
|
||||
public static final Identifier BACKGROUND_ZOMPONIES_POOL = new Identifier("minelittlepony", "textures/entity/zompony");
|
||||
|
||||
private final Map<Identifier, SkinList> entries = new HashMap<>();
|
||||
|
||||
|
@ -75,7 +75,7 @@ public class VariatedTextureSupplier implements SimpleSynchronousResourceReloadL
|
|||
public void reloadAll(ResourceManager resourceManager) {
|
||||
textures.clear();
|
||||
textures.addAll(resourceManager.findResources(id.getPath(), path -> path.getPath().endsWith(".png")).keySet());
|
||||
MineLittlePony.LOGGER.info("Detected {} ponies installed at {}.", textures.size(), id);
|
||||
MineLittlePony.logger.info("Detected {} ponies installed at {}.", textures.size(), id);
|
||||
}
|
||||
|
||||
static boolean isUser(UUID uuid) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.minelittlepony.client.compat.hdskins;
|
||||
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import com.minelittlepony.api.model.PreviewModel;
|
||||
import com.minelittlepony.api.pony.*;
|
||||
|
@ -21,13 +20,12 @@ class DummyPony extends DummyPlayer implements PreviewModel, PonyManager.ForcedP
|
|||
}
|
||||
|
||||
@Override
|
||||
public Identifier getForm() {
|
||||
if (getTextures().getPosture().getActiveSkinType() == MineLPHDSkins.seaponySkinType) {
|
||||
return PonyForm.SEAPONY;
|
||||
}
|
||||
if (getTextures().getPosture().getActiveSkinType() == MineLPHDSkins.nirikSkinType) {
|
||||
return PonyForm.NIRIK;
|
||||
}
|
||||
return PonyForm.DEFAULT;
|
||||
public boolean forceSeapony() {
|
||||
return getTextures().getPosture().getActiveSkinType() == MineLPHDSkins.seaponySkinType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceNirik() {
|
||||
return getTextures().getPosture().getActiveSkinType() == MineLPHDSkins.nirikSkinType;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,22 +17,22 @@ import net.minecraft.util.Identifier;
|
|||
* Skin uploading GUI. Usually displayed over the main menu.
|
||||
*/
|
||||
class GuiSkinsMineLP extends GuiSkins {
|
||||
private static final Identifier[] PANORAMAS = new Identifier[] {
|
||||
MineLittlePony.id("textures/cubemap/sugarcubecorner"),
|
||||
MineLittlePony.id("textures/cubemap/quillsandsofas"),
|
||||
MineLittlePony.id("textures/cubemap/sweetappleacres")
|
||||
private static final String[] PANORAMAS = new String[] {
|
||||
"minelittlepony:textures/cubemap/sugarcubecorner",
|
||||
"minelittlepony:textures/cubemap/quillsandsofas",
|
||||
"minelittlepony:textures/cubemap/sweetappleacres"
|
||||
};
|
||||
|
||||
public GuiSkinsMineLP(Screen parent, SkinServerList servers) {
|
||||
super(parent, servers);
|
||||
chooser.addSkinChangedEventListener(type -> {
|
||||
MineLittlePony.LOGGER.debug("Invalidating old local skin, checking updated local skin");
|
||||
MineLittlePony.logger.debug("Invalidating old local skin, checking updated local skin");
|
||||
if (type == SkinType.SKIN) {
|
||||
MineLittlePony.getInstance().getManager().removePony(previewer.getLocal().getSkins().get(SkinType.SKIN).getId());
|
||||
}
|
||||
});
|
||||
uploader.addSkinLoadedEventListener((type, location, profileTexture) -> {
|
||||
MineLittlePony.LOGGER.debug("Invalidating old remote skin, checking updated remote skin");
|
||||
MineLittlePony.logger.debug("Invalidating old remote skin, checking updated remote skin");
|
||||
if (type == SkinType.SKIN) {
|
||||
MineLittlePony.getInstance().getManager().removePony(location);
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ class GuiSkinsMineLP extends GuiSkins {
|
|||
.getStyle()
|
||||
.setIcon(new TextureSprite()
|
||||
.setPosition(2, 2)
|
||||
.setTexture(MineLittlePony.id("textures/gui/pony.png"))
|
||||
.setTexture(new Identifier("minelittlepony", "textures/gui/pony.png"))
|
||||
.setTextureSize(16, 16)
|
||||
.setSize(16, 16))
|
||||
.setTooltip("minelp.options.title", 0, 10);
|
||||
|
@ -64,6 +64,8 @@ class GuiSkinsMineLP extends GuiSkins {
|
|||
|
||||
@Override
|
||||
protected Identifier getBackground() {
|
||||
return PANORAMAS[(int)Math.floor(Math.random() * PANORAMAS.length)];
|
||||
int i = (int)Math.floor(Math.random() * PANORAMAS.length);
|
||||
|
||||
return new Identifier(PANORAMAS[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,13 +6,14 @@ import com.minelittlepony.api.pony.*;
|
|||
import com.minelittlepony.api.pony.meta.Wearable;
|
||||
import com.minelittlepony.common.client.gui.ScrollContainer;
|
||||
import com.minelittlepony.common.client.gui.element.Button;
|
||||
import com.minelittlepony.hdskins.HDSkinsServer;
|
||||
import com.minelittlepony.common.event.ClientReadyCallback;
|
||||
import com.minelittlepony.hdskins.client.*;
|
||||
import com.minelittlepony.hdskins.client.gui.GuiSkins;
|
||||
import com.minelittlepony.hdskins.client.gui.player.DummyPlayer;
|
||||
import com.minelittlepony.hdskins.client.gui.player.skins.PlayerSkins.PlayerSkin;
|
||||
import com.minelittlepony.hdskins.client.profile.SkinLoader.ProvidedSkins;
|
||||
import com.minelittlepony.hdskins.profile.SkinType;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
import java.util.*;
|
||||
|
@ -24,7 +25,6 @@ import net.minecraft.client.MinecraftClient;
|
|||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
|
@ -33,52 +33,45 @@ import com.minelittlepony.client.*;
|
|||
/**
|
||||
* All the interactions with HD Skins.
|
||||
*/
|
||||
public class MineLPHDSkins extends ClientSkinsProxy implements ClientModInitializer {
|
||||
public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
|
||||
|
||||
static SkinType seaponySkinType;
|
||||
static SkinType nirikSkinType;
|
||||
|
||||
static final Map<SkinType, Wearable> WEARABLE_TYPES = new HashMap<>();
|
||||
static final Map<SkinType, Wearable> wearableTypes = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
SkinsProxy.instance = this;
|
||||
PonySettingsScreen.buttonFactory = this::renderOption;
|
||||
|
||||
seaponySkinType = SkinType.register(DefaultPonySkinHelper.SEAPONY_SKIN_TYPE_ID, Items.COD_BUCKET.getDefaultStack());
|
||||
nirikSkinType = SkinType.register(DefaultPonySkinHelper.NIRIK_SKIN_TYPE_ID, Items.LAVA_BUCKET.getDefaultStack());
|
||||
Wearable.REGISTRY.values().forEach(wearable -> {
|
||||
if (wearable != Wearable.NONE) {
|
||||
WEARABLE_TYPES.put(SkinType.register(wearable.getId(), Items.BUNDLE.getDefaultStack()), wearable);
|
||||
wearableTypes.put(SkinType.register(wearable.getId(), Items.BUNDLE.getDefaultStack()), wearable);
|
||||
}
|
||||
});
|
||||
|
||||
// Clear ponies when skins are cleared
|
||||
SkinCacheClearCallback.EVENT.register(() -> {
|
||||
MineLittlePony.getInstance().getManager().clearCache();
|
||||
ClientReadyCallback.EVENT.register(client -> {
|
||||
// Clear ponies when skins are cleared
|
||||
SkinCacheClearCallback.EVENT.register(MineLittlePony.getInstance().getManager()::clearCache);
|
||||
|
||||
// Ponify the skins GUI.
|
||||
GuiSkins.setSkinsGui(GuiSkinsMineLP::new);
|
||||
});
|
||||
|
||||
// Ponify the skins GUI.
|
||||
GuiSkins.setSkinsGui(GuiSkinsMineLP::new);
|
||||
|
||||
HDSkins.getInstance().getSkinPrioritySorter().addSelector((skinType, playerSkins) -> {
|
||||
if (skinType == SkinType.SKIN) {
|
||||
if (skinType == SkinType.SKIN && PonyConfig.getInstance().mixedHumanSkins.get()) {
|
||||
Optional<Pony> hdPony = getPony(playerSkins.hd());
|
||||
Optional<Pony> vanillaPony = getPony(playerSkins.vanilla());
|
||||
|
||||
if (hdPony.isPresent() && vanillaPony.isPresent()) {
|
||||
PonyLevel level = PonyConfig.getInstance().ponyLevel.get();
|
||||
boolean vanillaHuman = vanillaPony.get().metadata().race().isHuman();
|
||||
boolean hdHuman = hdPony.get().metadata().race().isHuman();
|
||||
if (vanillaHuman != hdHuman) {
|
||||
return (level == PonyLevel.HUMANS ? vanillaHuman : hdHuman) ? playerSkins.vanilla() : playerSkins.hd();
|
||||
}
|
||||
|
||||
if (vanillaPony.get().metadata().priority() > hdPony.get().metadata().priority()) {
|
||||
return playerSkins.vanilla();
|
||||
}
|
||||
if (hdPony.isPresent() && vanillaPony.isPresent()
|
||||
&& vanillaPony.get().metadata().priority() > hdPony.get().metadata().priority()
|
||||
&& (PonyConfig.getInstance().ponyLevel.get() == PonyLevel.HUMANS || vanillaPony.get().metadata().race().isHuman() == hdPony.get().metadata().race().isHuman())) {
|
||||
return playerSkins.vanilla();
|
||||
}
|
||||
}
|
||||
|
||||
return playerSkins.combined();
|
||||
});
|
||||
}
|
||||
|
@ -92,20 +85,15 @@ public class MineLPHDSkins extends ClientSkinsProxy implements ClientModInitiali
|
|||
private void renderOption(Screen screen, @Nullable Screen parent, int row, int RIGHT, ScrollContainer content) {
|
||||
content.addButton(new Button(RIGHT, row += 20, 150, 20))
|
||||
.onClick(button -> MinecraftClient.getInstance().setScreen(
|
||||
parent instanceof GuiSkins ? parent : GuiSkins.create(screen, HDSkinsServer.getInstance().getServers())
|
||||
parent instanceof GuiSkins ? parent : GuiSkins.create(screen, HDSkins.getInstance().getSkinServerList())
|
||||
))
|
||||
.getStyle()
|
||||
.setText("minelp.options.skins.hdskins.open");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Identifier> getSkin(Identifier skinTypeId, PlayerEntity player) {
|
||||
if (player instanceof AbstractClientPlayerEntity clientPlayer) {
|
||||
return SkinType.REGISTRY.getOptionalValue(skinTypeId).flatMap(type -> getSkin(type, clientPlayer));
|
||||
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
public Optional<Identifier> getSkin(Identifier skinTypeId, AbstractClientPlayerEntity player) {
|
||||
return SkinType.REGISTRY.getOrEmpty(skinTypeId).flatMap(type -> getSkin(type, player));
|
||||
}
|
||||
|
||||
public Set<Identifier> getAvailableSkins(Entity entity) {
|
||||
|
@ -146,17 +134,16 @@ public class MineLPHDSkins extends ClientSkinsProxy implements ClientModInitiali
|
|||
}
|
||||
}
|
||||
|
||||
return Optional.of(player)
|
||||
.flatMap(PlayerSkins::of)
|
||||
return Optional.of(player).flatMap(PlayerSkins::of)
|
||||
.map(PlayerSkins::layers)
|
||||
.map(PlayerSkinLayers::combined)
|
||||
.flatMap(skins -> skins.getSkin(type));
|
||||
.map(PlayerSkinLayers::combined).flatMap(skins -> skins.getSkin(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getSkinTexture(GameProfile profile) {
|
||||
return HDSkins.getInstance().getProfileRepository()
|
||||
.load(profile).getNow(ProvidedSkins.EMPTY)
|
||||
.load(profile)
|
||||
.getNow(ProvidedSkins.EMPTY)
|
||||
.getSkin(SkinType.SKIN)
|
||||
.orElseGet(() -> super.getSkinTexture(profile));
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ class PonifiedDualCarouselWidget extends DualCarouselWidget {
|
|||
return super.getDefaultSkin(SkinType.SKIN, modelVariant);
|
||||
}
|
||||
|
||||
Wearable wearable = MineLPHDSkins.WEARABLE_TYPES.getOrDefault(type, Wearable.NONE);
|
||||
Wearable wearable = MineLPHDSkins.wearableTypes.getOrDefault(type, Wearable.NONE);
|
||||
|
||||
if (wearable != Wearable.NONE) {
|
||||
return NativeImageFilters.GREYSCALE.load(wearable.getDefaultTexture(), wearable.getDefaultTexture(), getExclusion());
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package com.minelittlepony.client.mixin;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public interface IResizeable {
|
||||
@Accessor
|
||||
void setStandingEyeHeight(float height);
|
||||
}
|
|
@ -2,8 +2,9 @@ package com.minelittlepony.client.mixin;
|
|||
|
||||
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.CallbackInfoReturnable;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
|
||||
import com.minelittlepony.api.pony.Pony;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
|
@ -11,15 +12,18 @@ import net.minecraft.client.render.Camera;
|
|||
|
||||
@Mixin(Camera.class)
|
||||
abstract class MixinCamera {
|
||||
@ModifyReturnValue(method = "clipToSpace(F)F", at = @At("RETURN"))
|
||||
private float redirectCameraDistance(float value) {
|
||||
if (MinecraftClient.getInstance().player != null) {
|
||||
Pony pony = Pony.getManager().getPony(MinecraftClient.getInstance().player);
|
||||
@Inject(method = "clipToSpace(D)D",
|
||||
at = @At("RETURN"),
|
||||
cancellable = true)
|
||||
private void redirectCameraDistance(double initial, CallbackInfoReturnable<Double> info) {
|
||||
double value = info.getReturnValueD();
|
||||
|
||||
if (!pony.race().isHuman()) {
|
||||
value *= pony.size().eyeDistanceFactor();
|
||||
}
|
||||
Pony pony = Pony.getManager().getPony(MinecraftClient.getInstance().player);
|
||||
|
||||
if (!pony.race().isHuman()) {
|
||||
value *= pony.size().eyeDistanceFactor();
|
||||
}
|
||||
return value;
|
||||
|
||||
info.setReturnValue(value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package com.minelittlepony.client.mixin;
|
||||
|
||||
import com.minelittlepony.api.pony.Pony;
|
||||
import com.minelittlepony.client.render.EquineRenderManager;
|
||||
|
||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||
import net.minecraft.client.network.ClientPlayerEntity;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityDimensions;
|
||||
import net.minecraft.entity.EntityPose;
|
||||
|
||||
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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(ClientPlayerEntity.class)
|
||||
abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity implements EquineRenderManager.RegistrationHandler {
|
||||
public MixinClientPlayerEntity() { super(null, null); }
|
||||
|
||||
private final EquineRenderManager.SyncedPony syncedPony = new EquineRenderManager.SyncedPony();
|
||||
|
||||
@Inject(method = "startRiding(Lnet/minecraft/entity/Entity;Z)Z", at = @At("RETURN"))
|
||||
private void onStartRiding(Entity entity, boolean bl, CallbackInfoReturnable<Boolean> info) {
|
||||
calculateDimensions();
|
||||
}
|
||||
|
||||
@Inject(method = "dismountVehicle()V", at = @At("RETURN"))
|
||||
private void onStopRiding(CallbackInfo info) {
|
||||
calculateDimensions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EquineRenderManager.SyncedPony getSyncedPony() {
|
||||
return syncedPony;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getActiveEyeHeight(EntityPose pose, EntityDimensions dimensions) {
|
||||
float value = super.getActiveEyeHeight(pose, dimensions);
|
||||
|
||||
Pony pony = Pony.getManager().getPony(this);
|
||||
|
||||
if (!pony.race().isHuman()) {
|
||||
float factor = pony.size().eyeHeightFactor();
|
||||
if (factor != 1) {
|
||||
value *= factor;
|
||||
|
||||
if (hasVehicle()) {
|
||||
value += getVehicle().getHeight();
|
||||
}
|
||||
return Math.max(value, 0.1F);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package com.minelittlepony.client.mixin;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
|
||||
import com.minelittlepony.api.config.PonyConfig;
|
||||
import com.minelittlepony.api.config.PonyLevel;
|
||||
import com.minelittlepony.api.pony.DefaultPonySkinHelper;
|
||||
|
@ -11,16 +10,28 @@ import net.minecraft.util.Identifier;
|
|||
|
||||
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.CallbackInfoReturnable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Mixin(DefaultSkinHelper.class)
|
||||
abstract class MixinDefaultSkinHelper {
|
||||
@ModifyReturnValue(method = "getTexture()Lnet/minecraft/util/Identifier;", at = @At("RETURN"))
|
||||
private static Identifier replaceDefaultSteveTexture(Identifier returnValue) {
|
||||
return PonyConfig.getInstance().ponyLevel.get() == PonyLevel.PONIES ? DefaultPonySkinHelper.STEVE : returnValue;
|
||||
@Inject(method = "getTexture()Lnet/minecraft/util/Identifier;",
|
||||
at = @At("RETURN"),
|
||||
cancellable = true)
|
||||
private static void onGetTexture(CallbackInfoReturnable<Identifier> cir) {
|
||||
if (PonyConfig.getInstance().ponyLevel.get() == PonyLevel.PONIES) {
|
||||
cir.setReturnValue(DefaultPonySkinHelper.STEVE);
|
||||
}
|
||||
}
|
||||
|
||||
@ModifyReturnValue(method = "getSkinTextures(Ljava/util/UUID;)Lnet/minecraft/client/util/SkinTextures;", at = @At("RETURN"))
|
||||
private static SkinTextures onGetTexture(SkinTextures returnValue) {
|
||||
return PonyConfig.getInstance().ponyLevel.get() == PonyLevel.PONIES ? DefaultPonySkinHelper.getTextures(returnValue) : returnValue;
|
||||
@Inject(method = "getSkinTextures(Ljava/util/UUID;)Lnet/minecraft/client/util/SkinTextures;",
|
||||
at = @At("RETURN"),
|
||||
cancellable = true)
|
||||
private static void onGetTexture(UUID uuid, CallbackInfoReturnable<SkinTextures> cir) {
|
||||
if (PonyConfig.getInstance().ponyLevel.get() == PonyLevel.PONIES) {
|
||||
cir.setReturnValue(DefaultPonySkinHelper.getTextures(cir.getReturnValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package com.minelittlepony.client.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.client.render.entity.EntityRendererFactory;
|
||||
import net.minecraft.client.render.entity.EntityRenderers;
|
||||
import net.minecraft.entity.EntityType;
|
||||
|
||||
@Mixin(EntityRenderers.class)
|
||||
public interface MixinEntityRenderers {
|
||||
@Accessor("RENDERER_FACTORIES")
|
||||
public static Map<EntityType<?>, EntityRendererFactory<?>> getRendererFactories() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package com.minelittlepony.client.mixin;
|
||||
|
||||
import net.minecraft.client.render.*;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
import org.joml.Matrix4f;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
@ -13,12 +14,12 @@ import com.minelittlepony.api.model.RenderPass;
|
|||
@Mixin(GameRenderer.class)
|
||||
abstract class MixinGameRenderer {
|
||||
@Inject(method = "renderWorld", at = @At("HEAD"))
|
||||
private void beforeRenderWorld(RenderTickCounter counter, CallbackInfo info) {
|
||||
private void beforeRenderWorld(float tickDelta, long limitTime, MatrixStack matrices, CallbackInfo info) {
|
||||
RenderPass.swap(RenderPass.WORLD);
|
||||
}
|
||||
|
||||
@Inject(method = "renderWorld", at = @At("RETURN"))
|
||||
private void afterRenderWorld(RenderTickCounter counter, CallbackInfo info) {
|
||||
private void afterRenderWorld(float tickDelta, long limitTime, MatrixStack matrices, CallbackInfo info) {
|
||||
RenderPass.swap(RenderPass.GUI);
|
||||
}
|
||||
}
|
||||
|
@ -30,14 +31,7 @@ abstract class MixinWorldRenderer {
|
|||
target = "net.minecraft.client.render.VertexConsumerProvider$Immediate.drawCurrentLayer()V",
|
||||
ordinal = 0
|
||||
))
|
||||
private void onRender(
|
||||
RenderTickCounter counter,
|
||||
boolean renderBlockOutline,
|
||||
Camera camera,
|
||||
GameRenderer gameRenderer,
|
||||
LightmapTextureManager lightmapTextureManager,
|
||||
Matrix4f matrix4f,
|
||||
Matrix4f matrix4f2, CallbackInfo info) {
|
||||
private void onRender(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f positionMatrix, CallbackInfo info) {
|
||||
RenderPass.swap(RenderPass.HUD);
|
||||
}
|
||||
}
|
|
@ -2,19 +2,18 @@ package com.minelittlepony.client.mixin;
|
|||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.minelittlepony.client.MineLittlePony;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.client.render.item.HeldItemRenderer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.model.json.ModelTransformationMode;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ModelTransformationMode;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.client.render.item.ItemRenderer;
|
||||
|
||||
|
@ -23,7 +22,7 @@ abstract class MixinHeldItemRenderer {
|
|||
private static final String LivingEntity = "Lnet/minecraft/entity/LivingEntity;";
|
||||
private static final String MatrixStack = "Lnet/minecraft/client/util/math/MatrixStack;";
|
||||
private static final String ItemStack = "Lnet/minecraft/item/ItemStack;";
|
||||
private static final String Mode = "Lnet/minecraft/item/ModelTransformationMode;";
|
||||
private static final String Mode = "Lnet/minecraft/client/render/model/json/ModelTransformationMode;";
|
||||
private static final String VertexConsumerProvider = "Lnet/minecraft/client/render/VertexConsumerProvider;";
|
||||
private static final String World = "Lnet/minecraft/world/World;";
|
||||
private static final String ItemRenderer = "Lnet/minecraft/client/render/item/ItemRenderer;";
|
||||
|
@ -31,20 +30,18 @@ abstract class MixinHeldItemRenderer {
|
|||
private static final String Boolean = "Z";
|
||||
private static final String Int = "I";
|
||||
|
||||
@WrapOperation(method = "renderItem(" + LivingEntity + ItemStack + Mode + Boolean + MatrixStack + VertexConsumerProvider + Int + ")V",
|
||||
@Redirect(method = "renderItem(" + LivingEntity + ItemStack + Mode + Boolean + MatrixStack + VertexConsumerProvider + Int + ")V",
|
||||
at = @At(value = "INVOKE",
|
||||
target = ItemRenderer + "renderItem(" + LivingEntity + ItemStack + Mode + Boolean + MatrixStack + VertexConsumerProvider + World + Int + Int + Int + ")V"))
|
||||
private void wrapRenderItem(ItemRenderer target,
|
||||
private void redirectRenderItem(ItemRenderer target,
|
||||
@Nullable LivingEntity entity,
|
||||
ItemStack stack,
|
||||
ModelTransformationMode mode,
|
||||
ItemStack item,
|
||||
ModelTransformationMode transform,
|
||||
boolean left,
|
||||
MatrixStack matrices,
|
||||
VertexConsumerProvider vertices,
|
||||
MatrixStack stack,
|
||||
VertexConsumerProvider renderContext,
|
||||
@Nullable World world,
|
||||
int light, int overlay, int seed, Operation<Void> operation) {
|
||||
if (!MineLittlePony.getInstance().getRenderDispatcher().getMagicRenderer().renderItem(target, entity, stack, mode, left, matrices, vertices, world, light, overlay, seed, operation)) {
|
||||
operation.call(target, entity, stack, mode, left, matrices, vertices, world, light, overlay, seed);
|
||||
}
|
||||
int lightUv, int overlayUv, int posLong) {
|
||||
MineLittlePony.getInstance().getRenderDispatcher().getMagicRenderer().renderItem(target, entity, item, transform, left, stack, renderContext, world, lightUv, posLong);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
package com.minelittlepony.client.mixin;
|
||||
|
||||
import net.minecraft.entity.*;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
|
||||
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 com.llamalad7.mixinextras.injector.ModifyReturnValue;
|
||||
import com.minelittlepony.client.render.EquineRenderManager.RegistrationHandler;
|
||||
import com.minelittlepony.client.render.EquineRenderManager.SyncedPony;
|
||||
|
||||
@Mixin(PlayerEntity.class)
|
||||
abstract class MixinPlayerEntity implements RegistrationHandler {
|
||||
private final SyncedPony syncedPony = new SyncedPony();
|
||||
|
||||
@Override
|
||||
public SyncedPony getSyncedPony() {
|
||||
return syncedPony;
|
||||
}
|
||||
|
||||
@ModifyReturnValue(method = "getBaseDimensions(Lnet/minecraft/entity/EntityPose;)Lnet/minecraft/entity/EntityDimensions;", at = @At("RETURN"))
|
||||
private EntityDimensions modifyEyeHeight(EntityDimensions dimensions, EntityPose pose) {
|
||||
return getSyncedPony().modifyEyeHeight((PlayerEntity)(Object)this, dimensions, pose);
|
||||
}
|
||||
|
||||
@Inject(method = "tick()V", at = @At("TAIL"))
|
||||
private void onTick(CallbackInfo info) {
|
||||
getSyncedPony().synchronize((PlayerEntity)(Object)this);
|
||||
}
|
||||
}
|
|
@ -22,7 +22,8 @@ abstract class MixinPlayerMoveC2SPacket implements Packet<ServerPlayPacketListen
|
|||
@Shadow @Final
|
||||
protected boolean changeLook;
|
||||
|
||||
@Inject(method = "<init>(DDDFFZZZZ)V", at = @At("RETURN"))
|
||||
@Inject(method = "<init>(DDDFFZZZ)V",
|
||||
at = @At("RETURN"))
|
||||
private void onInit(CallbackInfo info) {
|
||||
if (changeLook) {
|
||||
pitch = HorseCam.transformCameraAngle(pitch);
|
||||
|
|
|
@ -4,7 +4,6 @@ import com.minelittlepony.client.HorseCam;
|
|||
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.entity.player.PlayerPosition;
|
||||
import net.minecraft.network.listener.ClientPlayPacketListener;
|
||||
import net.minecraft.network.packet.Packet;
|
||||
import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket;
|
||||
|
@ -18,15 +17,15 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||
@Mixin(PlayerPositionLookS2CPacket.class)
|
||||
abstract class MixinPlayerPositionLookS2CPacket implements Packet<ClientPlayPacketListener> {
|
||||
@Shadow @Mutable
|
||||
private @Final PlayerPosition change;
|
||||
private @Final float pitch;
|
||||
@Shadow
|
||||
private @Final Set<PositionFlag> relatives;
|
||||
private @Final Set<PositionFlag> flags;
|
||||
|
||||
@Inject(method = "apply(Lnet/minecraft/network/listener/ClientPlayPacketListener;)V",
|
||||
at = @At("HEAD"))
|
||||
private void onApply(ClientPlayPacketListener clientPlayPacketListener, CallbackInfo info) {
|
||||
if (!relatives.contains(PositionFlag.Y_ROT)) {
|
||||
change = HorseCam.transformIncomingServerCameraAngle(change);
|
||||
if (!flags.contains(PositionFlag.Y_ROT)) {
|
||||
pitch = HorseCam.transformIncomingServerCameraAngle(pitch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,6 @@ import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
|||
import net.minecraft.client.render.block.entity.SkullBlockEntityModel;
|
||||
import net.minecraft.client.render.block.entity.SkullBlockEntityRenderer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.component.type.ProfileComponent;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
@ -19,28 +17,40 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.minelittlepony.client.render.blockentity.skull.PonySkullRenderer;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Mixin(SkullBlockEntityRenderer.class)
|
||||
abstract class MixinSkullBlockEntityRenderer implements BlockEntityRenderer<SkullBlockEntity> {
|
||||
@Inject(method = "renderSkull", at = @At("HEAD"), cancellable = true)
|
||||
@Inject(method = "renderSkull("
|
||||
+ "Lnet/minecraft/util/math/Direction;"
|
||||
+ "F"
|
||||
+ "F"
|
||||
+ "Lnet/minecraft/client/util/math/MatrixStack;"
|
||||
+ "Lnet/minecraft/client/render/VertexConsumerProvider;"
|
||||
+ "I"
|
||||
+ "Lnet/minecraft/client/render/block/entity/SkullBlockEntityModel;"
|
||||
+ "Lnet/minecraft/client/render/RenderLayer;"
|
||||
+ ")V", at = @At("HEAD"), cancellable = true)
|
||||
private static void onRenderSkull(@Nullable Direction direction,
|
||||
float yaw, float animationProgress,
|
||||
MatrixStack matrices, VertexConsumerProvider vertices,
|
||||
int light,
|
||||
float angle, float poweredTicks,
|
||||
MatrixStack stack, VertexConsumerProvider renderContext, int lightUv,
|
||||
SkullBlockEntityModel model, RenderLayer layer,
|
||||
CallbackInfo info) {
|
||||
|
||||
if (!info.isCancelled() && PonySkullRenderer.INSTANCE.renderSkull(direction, yaw, animationProgress, matrices, vertices, layer, light)) {
|
||||
if (!info.isCancelled() && PonySkullRenderer.renderSkull(direction, angle, poweredTicks, stack, renderContext, layer, lightUv)) {
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "getRenderLayer(Lnet/minecraft/block/SkullBlock$SkullType;Lnet/minecraft/component/type/ProfileComponent;Lnet/minecraft/util/Identifier;)Lnet/minecraft/client/render/RenderLayer;", at = @At("HEAD"), cancellable = true)
|
||||
private static void onGetRenderLayer(SkullBlock.SkullType skullType, @Nullable ProfileComponent profile, @Nullable Identifier texture, CallbackInfoReturnable<RenderLayer> info) {
|
||||
@Inject(method = "getRenderLayer("
|
||||
+ "Lnet/minecraft/block/SkullBlock$SkullType;"
|
||||
+ "Lcom/mojang/authlib/GameProfile;"
|
||||
+ ")Lnet/minecraft/client/render/RenderLayer;", at = @At("HEAD"), cancellable = true)
|
||||
private static void onGetRenderLayer(SkullBlock.SkullType skullType, @Nullable GameProfile profile, CallbackInfoReturnable<RenderLayer> info) {
|
||||
if (!info.isCancelled()) {
|
||||
RenderLayer result = PonySkullRenderer.INSTANCE.getSkullRenderLayer(skullType, profile);
|
||||
RenderLayer result = PonySkullRenderer.getSkullRenderLayer(skullType, profile);
|
||||
if (result != null) {
|
||||
info.setReturnValue(result);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package com.minelittlepony.client.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.*;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.Arrays;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArraySet;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumers;
|
||||
|
||||
|
@ -25,12 +25,15 @@ abstract class MixinVertextConsumers {
|
|||
}
|
||||
}
|
||||
|
||||
@ModifyVariable(method = "union([" + T + ")" + T, at = @At("HEAD"), argsOnly = true)
|
||||
private static VertexConsumer[] onUnion(VertexConsumer[] delegates) {
|
||||
Set<VertexConsumer> set = new ObjectArraySet<>(delegates.length);
|
||||
for (VertexConsumer delegate : delegates) {
|
||||
set.add(delegate);
|
||||
@Inject(method = "union([" + T + ")" + T, at = @At("HEAD"), cancellable = true)
|
||||
private static void onUnion(VertexConsumer[] delegates, CallbackInfoReturnable<VertexConsumer> info) {
|
||||
int oldLength = delegates.length;
|
||||
delegates = Arrays.stream(delegates).distinct().toArray(VertexConsumer[]::new);
|
||||
|
||||
if (delegates.length == 1) {
|
||||
info.setReturnValue(delegates[0]);
|
||||
} else if (delegates.length != oldLength) {
|
||||
info.setReturnValue(new VertexConsumers.Union(delegates));
|
||||
}
|
||||
return set.toArray(VertexConsumer[]::new);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +1,28 @@
|
|||
package com.minelittlepony.client.model;
|
||||
|
||||
import com.minelittlepony.api.model.*;
|
||||
import com.minelittlepony.api.events.PonyModelPrepareCallback;
|
||||
import com.minelittlepony.api.pony.meta.SizePreset;
|
||||
import com.minelittlepony.client.render.entity.state.PonyRenderState;
|
||||
import com.minelittlepony.client.transform.PonyTransformation;
|
||||
import com.minelittlepony.mson.util.RenderList;
|
||||
import com.minelittlepony.client.util.render.RenderList;
|
||||
import com.minelittlepony.util.MathUtil;
|
||||
import com.minelittlepony.util.MathUtil.Angles;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
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.state.PlayerEntityRenderState;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.EntityPose;
|
||||
import net.minecraft.item.consume.UseAction;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.util.*;
|
||||
import net.minecraft.util.math.*;
|
||||
|
||||
/**
|
||||
* Foundation class for all types of ponies.
|
||||
*/
|
||||
public abstract class AbstractPonyModel<T extends PonyRenderState> extends ClientPonyModel<T> {
|
||||
public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPonyModel<T> {
|
||||
public static final float NECK_X = 0.166F;
|
||||
public static final float LEG_SNEAKING_PITCH_ADJUSTMENT = 0.4F;
|
||||
public static final float BODY_RIDING_PITCH = MathHelper.PI * 3.8F;
|
||||
|
@ -33,6 +31,7 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
|
||||
public static final Pivot ORIGIN = new Pivot(0, 0, 0);
|
||||
public static final Pivot HEAD_SNEAKING = new Pivot(0, 6, -2);
|
||||
public static final Pivot HEAD_SLEEPING = new Pivot(1, 2, 0);
|
||||
public static final Pivot BODY_SNEAKING = new Pivot(0, 7, -4);
|
||||
public static final Pivot BODY_RIDING = new Pivot(0, 1, 4);
|
||||
public static final Pivot FONT_LEGS_SLEEPING = new Pivot(0, 2, 6);
|
||||
|
@ -40,128 +39,149 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
|
||||
protected final ModelPart neck;
|
||||
|
||||
public final RenderList helmetRenderList;
|
||||
protected final RenderList neckRenderList;
|
||||
public final RenderList headRenderList;
|
||||
protected final RenderList bodyRenderList;
|
||||
protected final RenderList vestRenderList;
|
||||
|
||||
protected final RenderList legsRenderList;
|
||||
protected final RenderList sleevesRenderList;
|
||||
|
||||
protected final RenderList mainRenderList;
|
||||
|
||||
private final List<SubModel<? super T>> parts = new ArrayList<>();
|
||||
private final List<SubModel> parts = new ArrayList<>();
|
||||
|
||||
public AbstractPonyModel(ModelPart tree, boolean smallArms) {
|
||||
super(tree, smallArms);
|
||||
public AbstractPonyModel(ModelPart tree) {
|
||||
super(tree);
|
||||
|
||||
neck = tree.getChild("neck");
|
||||
mainRenderList = RenderList.of()
|
||||
.add(withStage(BodyPart.BODY, bodyRenderList = RenderList.of(body).add(body::rotate)))
|
||||
.add(withStage(BodyPart.NECK, neckRenderList = RenderList.of(neck)))
|
||||
.add(withStage(BodyPart.HEAD, headRenderList = RenderList.of(head)))
|
||||
.add(withStage(BodyPart.LEGS, legsRenderList = RenderList.of().add(leftArm, rightArm, leftLeg, rightLeg)));
|
||||
.add(withStage(BodyPart.LEGS, legsRenderList = RenderList.of().add(leftArm, rightArm, leftLeg, rightLeg)))
|
||||
.add(withStage(BodyPart.LEGS, sleevesRenderList = RenderList.of().add(leftSleeve, rightSleeve, leftPants, rightPants)))
|
||||
.add(withStage(BodyPart.BODY, vestRenderList = RenderList.of(jacket)))
|
||||
.add(withStage(BodyPart.HEAD, helmetRenderList = RenderList.of(hat)));
|
||||
}
|
||||
|
||||
protected <P extends SubModel<? super T>> P addPart(P part) {
|
||||
protected <P extends SubModel> P addPart(P part) {
|
||||
parts.add(part);
|
||||
return part;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"deprecation"})
|
||||
protected RenderList withStage(BodyPart part, RenderList action) {
|
||||
return (stack, vertices, overlay, light, color) -> {
|
||||
stack.push();
|
||||
if (currentState != null) {
|
||||
transform(currentState, part, stack);
|
||||
}
|
||||
action.accept(stack, vertices, overlay, light, color);
|
||||
stack.pop();
|
||||
protected RenderList forPart(Supplier<SubModel> part) {
|
||||
return (stack, vertices, overlayUv, lightUv, red, green, blue, alpha) -> {
|
||||
part.get().renderPart(stack, vertices, overlayUv, lightUv, red, green, blue, alpha, attributes);
|
||||
};
|
||||
}
|
||||
|
||||
protected RenderList forPart(SubModel part) {
|
||||
return (stack, vertices, overlayUv, lightUv, red, green, blue, alpha) -> {
|
||||
part.renderPart(stack, vertices, overlayUv, lightUv, red, green, blue, alpha, attributes);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void render(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color) {
|
||||
mainRenderList.accept(stack, vertices, overlay, light, color);
|
||||
public void render(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
|
||||
mainRenderList.accept(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
|
||||
}
|
||||
|
||||
protected void setModelVisibilities(T state) {
|
||||
protected RenderList withStage(BodyPart part, RenderList action) {
|
||||
return (stack, vertices, overlayUv, lightUv, red, green, blue, alpha) -> {
|
||||
stack.push();
|
||||
transform(part, stack);
|
||||
action.accept(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
|
||||
stack.pop();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the model's various rotation angles.
|
||||
*/
|
||||
@Override
|
||||
public final void setAngles(T entity, float limbAngle, float limbSpeed, float animationProgress, float headYaw, float headPitch) {
|
||||
attributes.checkRainboom(entity, this, animationProgress);
|
||||
PonyModelPrepareCallback.EVENT.invoker().onPonyModelPrepared(entity, this, ModelAttributes.Mode.OTHER);
|
||||
super.setAngles(entity, limbAngle, limbSpeed, animationProgress, headYaw, headPitch);
|
||||
|
||||
resetPivot(head, neck, leftArm, rightArm, leftLeg, rightLeg);
|
||||
hat.visible = head.visible && !state.attributes.isHorsey;
|
||||
if (state.attributes.isHorsey) {
|
||||
neck.visible = head.visible;
|
||||
} else {
|
||||
neck.hidden = !head.visible;
|
||||
}
|
||||
parts.forEach(part -> part.setVisible(body.visible, state));
|
||||
|
||||
setModelAngles(entity, limbAngle, limbSpeed, animationProgress, headYaw, headPitch);
|
||||
|
||||
leftSleeve.copyTransform(leftArm);
|
||||
rightSleeve.copyTransform(rightArm);
|
||||
leftPants.copyTransform(leftLeg);
|
||||
rightPants.copyTransform(rightLeg);
|
||||
jacket.copyTransform(body);
|
||||
hat.copyTransform(head);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "deprecation"})
|
||||
public void copyTransforms(BipedEntityModel<PlayerEntityRenderState> model) {
|
||||
super.copyTransforms(model);
|
||||
if (model instanceof AbstractPonyModel m) {
|
||||
((AbstractPonyModel<T>)m).currentState = currentState;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setModelAngles(T entity) {
|
||||
float pitch = entity.attributes.motionPitch * MathHelper.RADIANS_PER_DEGREE;
|
||||
protected void setModelAngles(T entity, float limbAngle, float limbSpeed, float animationProgress, float headYaw, float headPitch) {
|
||||
float pitch = attributes.motionPitch * MathHelper.RADIANS_PER_DEGREE;
|
||||
head.setAngles(
|
||||
MathHelper.clamp(entity.attributes.isSleeping ? 0.1f : entity.pitch / 57.29578F, -1.25f - pitch, 0.5f - pitch),
|
||||
entity.attributes.isSleeping ? (Math.signum(MathHelper.wrapDegrees(entity.yawDegrees)) * 1.3F) : entity.yawDegrees * MathHelper.RADIANS_PER_DEGREE,
|
||||
MathHelper.clamp(attributes.isSleeping ? 0.1f : headPitch / 57.29578F, -1.25f - pitch, 0.5f - pitch),
|
||||
attributes.isSleeping ? (Math.signum(MathHelper.wrapDegrees(headYaw)) * 1.3F) : headYaw * MathHelper.RADIANS_PER_DEGREE,
|
||||
0
|
||||
);
|
||||
|
||||
float wobbleAmount = entity.wobbleAmount * getWobbleAmplitude(entity);
|
||||
float wobbleAmount = getWobbleAmount();
|
||||
body.yaw = wobbleAmount;
|
||||
neck.yaw = wobbleAmount;
|
||||
|
||||
rotateLegs(entity);
|
||||
rotateLegs(limbAngle, limbSpeed, animationProgress, entity);
|
||||
|
||||
if (!entity.attributes.isSwimming && !entity.attributes.isGoingFast) {
|
||||
alignArmForAction(entity, getArm(Arm.LEFT), entity.leftArmPose, entity.rightArmPose, 1);
|
||||
alignArmForAction(entity, getArm(Arm.RIGHT), entity.rightArmPose, entity.leftArmPose, -1);
|
||||
if (onSetModelAngles != null) {
|
||||
onSetModelAngles.poseModel(this, limbAngle, limbSpeed, animationProgress, entity);
|
||||
}
|
||||
|
||||
if (!attributes.isSwimming && !attributes.isGoingFast) {
|
||||
holdItem(limbSpeed);
|
||||
}
|
||||
swingItem(entity);
|
||||
|
||||
if (entity.attributes.isCrouching) {
|
||||
ponyCrouch(entity);
|
||||
} else if (entity.isInPose(EntityPose.SITTING)) {
|
||||
if (attributes.isCrouching) {
|
||||
ponyCrouch();
|
||||
} else if (riding) {
|
||||
ponySit();
|
||||
} else {
|
||||
adjustBody(entity, 0, ORIGIN);
|
||||
adjustBody(0, ORIGIN);
|
||||
|
||||
if (!entity.attributes.isLyingDown) {
|
||||
animateBreathing(entity);
|
||||
if (!attributes.isLyingDown) {
|
||||
animateBreathing(animationProgress);
|
||||
}
|
||||
|
||||
if (entity.attributes.isSwimmingRotated) {
|
||||
if (attributes.isSwimmingRotated) {
|
||||
rightLeg.pivotZ -= 1.5F;
|
||||
leftLeg.pivotZ -= 1.5F;
|
||||
}
|
||||
}
|
||||
|
||||
if (entity.attributes.isLyingDown) {
|
||||
if (attributes.isLyingDown) {
|
||||
ponySleep();
|
||||
}
|
||||
|
||||
if (entity.attributes.isHorsey) {
|
||||
if (attributes.isHorsey) {
|
||||
head.pivotY -= 3;
|
||||
head.pivotZ -= 2;
|
||||
head.pitch = 0.5F;
|
||||
}
|
||||
|
||||
parts.forEach(part -> part.setPartAngles(entity, wobbleAmount));
|
||||
parts.forEach(part -> part.setPartAngles(attributes, limbAngle, limbSpeed, wobbleAmount, animationProgress));
|
||||
}
|
||||
|
||||
public void setHeadRotation(float animationProgress, float yaw, float pitch) {
|
||||
head.yaw = yaw * MathHelper.RADIANS_PER_DEGREE;
|
||||
head.pitch = pitch * MathHelper.RADIANS_PER_DEGREE;
|
||||
hat.copyTransform(head);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aligns legs to a sneaky position.
|
||||
*/
|
||||
protected void ponyCrouch(T state) {
|
||||
adjustBody(state, BODY_SNEAKING_PITCH, BODY_SNEAKING);
|
||||
protected void ponyCrouch() {
|
||||
adjustBody(BODY_SNEAKING_PITCH, BODY_SNEAKING);
|
||||
HEAD_SNEAKING.set(head);
|
||||
|
||||
rightArm.pitch -= LEG_SNEAKING_PITCH_ADJUSTMENT;
|
||||
|
@ -175,6 +195,8 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
rightLeg.pitch = MathUtil.Angles._90_DEG;
|
||||
leftLeg.pitch = MathUtil.Angles._90_DEG;
|
||||
|
||||
HEAD_SLEEPING.set(head);
|
||||
|
||||
FONT_LEGS_SLEEPING.add(rightArm);
|
||||
FONT_LEGS_SLEEPING.add(leftArm);
|
||||
BACK_LEGS_SLEEPING.add(rightLeg);
|
||||
|
@ -182,9 +204,14 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
}
|
||||
|
||||
protected void ponySit() {
|
||||
adjustBodyComponents(BODY_RIDING_PITCH, BODY_RIDING);
|
||||
neck.setPivot(NECK_X, 0, 0);
|
||||
head.setPivot(0, 0, 0);
|
||||
adjustBodyComponents(BODY_RIDING_PITCH * (attributes.isRidingInteractive ? 2 : 1), BODY_RIDING);
|
||||
if (attributes.isRidingInteractive) {
|
||||
neck.setPivot(NECK_X, 0, -4);
|
||||
head.setPivot(0, -2, -5);
|
||||
} else {
|
||||
neck.setPivot(NECK_X, 0, 0);
|
||||
head.setPivot(0, 0, 0);
|
||||
}
|
||||
|
||||
leftLeg.pivotZ = 14;
|
||||
leftLeg.pivotY = 17;
|
||||
|
@ -204,6 +231,26 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
leftArm.pitch += body.pitch;
|
||||
rightArm.roll = MathHelper.PI * 0.06f;
|
||||
rightArm.pitch += body.pitch;
|
||||
|
||||
if (attributes.isRidingInteractive) {
|
||||
leftLeg.yaw = MathHelper.PI / 15;
|
||||
leftLeg.pitch = MathHelper.PI / 9;
|
||||
|
||||
leftLeg.pivotZ = 10;
|
||||
leftLeg.pivotY = 7;
|
||||
|
||||
rightLeg.yaw = -MathHelper.PI / 15;
|
||||
rightLeg.pitch = MathHelper.PI / 9;
|
||||
|
||||
rightLeg.pivotZ = 10;
|
||||
rightLeg.pivotY = 7;
|
||||
|
||||
leftArm.pitch = MathHelper.PI / 6;
|
||||
rightArm.pitch = MathHelper.PI / 6;
|
||||
|
||||
leftArm.roll *= 2;
|
||||
rightArm.roll *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -213,11 +260,11 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
* Takes the same parameters as {@link AbstractPonyModel.setRotationAndAngles}
|
||||
*
|
||||
*/
|
||||
protected void rotateLegs(T state) {
|
||||
if (state.attributes.isSwimming) {
|
||||
rotateLegsSwimming(state, state.limbAmplitudeInverse, state.limbAmplitudeMultiplier, state.age);
|
||||
protected void rotateLegs(float move, float swing, float ticks, T entity) {
|
||||
if (attributes.isSwimming) {
|
||||
rotateLegsSwimming(move, swing, ticks, entity);
|
||||
} else {
|
||||
rotateLegsOnGround(state, state.limbAmplitudeInverse, state.limbAmplitudeMultiplier, state.age);
|
||||
rotateLegsOnGround(move, swing, ticks, entity);
|
||||
}
|
||||
|
||||
float sin = MathHelper.sin(body.yaw) * 5;
|
||||
|
@ -226,8 +273,8 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
rightArm.pivotZ = 2 + sin;
|
||||
leftArm.pivotZ = 2 - sin;
|
||||
|
||||
float legRPX = state.attributes.getMainInterpolator().interpolate("legOffset", cos - state.legOutset - 0.001F, 2);
|
||||
if (state.attributes.isHorsey) {
|
||||
float legRPX = attributes.getMainInterpolator().interpolate("legOffset", cos - getLegOutset() - 0.001F, 2);
|
||||
if (attributes.isHorsey) {
|
||||
legRPX += 2;
|
||||
}
|
||||
|
||||
|
@ -240,7 +287,7 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
rightArm.yaw += body.yaw;
|
||||
leftArm.yaw += body.yaw;
|
||||
|
||||
if (state.attributes.isHorsey) {
|
||||
if (attributes.isHorsey) {
|
||||
rightArm.pivotZ = leftArm.pivotZ = -1;
|
||||
rightArm.pivotY = leftArm.pivotY = 6;
|
||||
rightLeg.pivotZ = leftLeg.pivotZ = 19;
|
||||
|
@ -253,13 +300,14 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
*
|
||||
* Takes the same parameters as {@link AbstractPonyModel.setRotationAndAngles}
|
||||
*/
|
||||
protected void rotateLegsSwimming(T state, @Deprecated float move, @Deprecated float swing, @Deprecated float ticks) {
|
||||
float lerp = state.isInPose(EntityPose.SWIMMING) ? (float)state.attributes.motionLerp : 1;
|
||||
protected void rotateLegsSwimming(float move, float swing, float ticks, T entity) {
|
||||
|
||||
float legLeft = (MathUtil.Angles._90_DEG + MathHelper.sin((state.limbFrequency / 3) + 2 * MathHelper.PI/3) / 2) * lerp;
|
||||
float lerp = entity.isSwimming() ? (float)attributes.motionLerp : 1;
|
||||
|
||||
float left = (MathUtil.Angles._90_DEG + MathHelper.sin((state.limbFrequency / 3) + 2 * MathHelper.PI) / 2) * lerp;
|
||||
float right = (MathUtil.Angles._90_DEG + MathHelper.sin(state.limbFrequency / 3) / 2) * lerp;
|
||||
float legLeft = (MathUtil.Angles._90_DEG + MathHelper.sin((move / 3) + 2 * MathHelper.PI/3) / 2) * lerp;
|
||||
|
||||
float left = (MathUtil.Angles._90_DEG + MathHelper.sin((move / 3) + 2 * MathHelper.PI) / 2) * lerp;
|
||||
float right = (MathUtil.Angles._90_DEG + MathHelper.sin(move / 3) / 2) * lerp;
|
||||
|
||||
leftArm.setAngles(-left, -left/2, left/2);
|
||||
rightArm.setAngles(-right, right/2, -right/2);
|
||||
|
@ -271,15 +319,15 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
* Rotates legs in quopy fashion for walking.
|
||||
*
|
||||
*/
|
||||
protected void rotateLegsOnGround(T state, float move, float swing, float ticks) {
|
||||
protected void rotateLegsOnGround(float move, float swing, float ticks, T entity) {
|
||||
float angle = MathHelper.PI * (float) Math.pow(swing, 16);
|
||||
|
||||
float baseRotation = state.limbFrequency * 0.6662F; // magic number ahoy
|
||||
float scale = state.limbAmplitudeMultiplier / 4;
|
||||
float baseRotation = move * 0.6662F; // magic number ahoy
|
||||
float scale = swing / 4;
|
||||
|
||||
float rainboomLegLotation = state.attributes.getMainInterpolator().interpolate(
|
||||
float rainboomLegLotation = attributes.getMainInterpolator().interpolate(
|
||||
"rainboom_leg_rotation",
|
||||
state.attributes.isGoingFast ? 1 : 0,
|
||||
attributes.isGoingFast ? 1 : 0,
|
||||
5
|
||||
);
|
||||
float yAngle = 0.2F * rainboomLegLotation;
|
||||
|
@ -290,6 +338,26 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
rightLeg.setAngles(MathHelper.lerp(rainboomLegLotation, MathHelper.cos(baseRotation + angle / 5) * scale, MathUtil.Angles._90_DEG * rainboomLegLotation), -yAngle, rightLeg.roll);
|
||||
}
|
||||
|
||||
protected float getLegOutset() {
|
||||
if (attributes.isLyingDown) {
|
||||
return 3.6f;
|
||||
}
|
||||
|
||||
if (attributes.isCrouching) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts legs as if holding an item. Delegates to the correct arm/leg/limb as necessary.
|
||||
*/
|
||||
protected void holdItem(float limbSpeed) {
|
||||
alignArmForAction(getArm(Arm.LEFT), leftArmPose, rightArmPose, limbSpeed, 1);
|
||||
alignArmForAction(getArm(Arm.RIGHT), rightArmPose, leftArmPose, limbSpeed, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelPart getBodyPart(BodyPart part) {
|
||||
switch (part) {
|
||||
|
@ -310,25 +378,25 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
* @param pose The post to align to
|
||||
* @param limbSpeed Degree to which each 'limb' swings.
|
||||
*/
|
||||
protected void alignArmForAction(T state, ModelPart arm, ArmPose pose, ArmPose complement, float sigma) {
|
||||
protected void alignArmForAction(ModelPart arm, ArmPose pose, ArmPose complement, float limbSpeed, float sigma) {
|
||||
switch (pose) {
|
||||
case ITEM:
|
||||
arm.yaw = 0;
|
||||
|
||||
boolean both = pose == complement;
|
||||
|
||||
if (state.attributes.shouldLiftArm(pose, complement, sigma)) {
|
||||
if (attributes.shouldLiftArm(pose, complement, sigma)) {
|
||||
float swag = 1;
|
||||
if (!state.attributes.isFlying && both) {
|
||||
swag -= (float)Math.pow(state.limbAmplitudeMultiplier, 2);
|
||||
if (!getAttributes().isFlying && both) {
|
||||
swag -= (float)Math.pow(limbSpeed, 2);
|
||||
}
|
||||
|
||||
float mult = 1 - swag/2;
|
||||
arm.pitch = arm.pitch * mult - (MathHelper.PI / 10) * swag;
|
||||
arm.roll = -sigma * (MathHelper.PI / 15);
|
||||
arm.roll += 0.3F * -state.limbAmplitudeMultiplier * sigma;
|
||||
arm.roll += 0.3F * -limbSpeed * sigma;
|
||||
|
||||
if (state.attributes.isCrouching) {
|
||||
if (attributes.isCrouching) {
|
||||
arm.pivotX -= sigma * 2;
|
||||
}
|
||||
}
|
||||
|
@ -340,52 +408,52 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
case BLOCK:
|
||||
arm.pitch = (arm.pitch / 2 - 0.9424779F) - 0.3F;
|
||||
arm.yaw = sigma * MathHelper.PI / 9;
|
||||
arm.roll += 0.3F * -state.limbAmplitudeMultiplier * sigma;
|
||||
arm.roll += 0.3F * -limbSpeed * sigma;
|
||||
if (complement == pose) {
|
||||
arm.yaw -= sigma * MathHelper.PI / 18;
|
||||
}
|
||||
arm.pivotX += sigma;
|
||||
arm.pivotZ += 3;
|
||||
if (state.attributes.isCrouching) {
|
||||
if (attributes.isCrouching) {
|
||||
arm.pivotY += 4;
|
||||
}
|
||||
break;
|
||||
case BOW_AND_ARROW:
|
||||
aimBow(state, arm);
|
||||
aimBow(arm, limbSpeed);
|
||||
break;
|
||||
case CROSSBOW_HOLD:
|
||||
aimBow(state, arm);
|
||||
aimBow(arm, limbSpeed);
|
||||
|
||||
arm.pitch = head.pitch - MathUtil.Angles._90_DEG;
|
||||
arm.yaw = head.yaw + 0.06F;
|
||||
break;
|
||||
case CROSSBOW_CHARGE:
|
||||
aimBow(state, arm);
|
||||
aimBow(arm, limbSpeed);
|
||||
|
||||
arm.pitch = -0.8F;
|
||||
arm.yaw = head.yaw + 0.06F;
|
||||
arm.roll += 0.3F * -state.limbAmplitudeMultiplier * sigma;
|
||||
arm.roll += 0.3F * -limbSpeed * sigma;
|
||||
break;
|
||||
case THROW_SPEAR:
|
||||
arm.pitch = MathUtil.Angles._90_DEG * 2;
|
||||
arm.roll += (0.3F * -state.limbAmplitudeMultiplier + 0.6F) * sigma;
|
||||
arm.roll += (0.3F * -limbSpeed + 0.6F) * sigma;
|
||||
arm.pivotY ++;
|
||||
break;
|
||||
case SPYGLASS:
|
||||
float addedPitch = state.isInSneakingPose ? -0.2617994F : 0;
|
||||
float minPitch = state.isInSneakingPose ? -1.8F : -2.4F;
|
||||
float addedPitch = sneaking ? -0.2617994F : 0;
|
||||
float minPitch = sneaking ? -1.8F : -2.4F;
|
||||
arm.pitch = MathHelper.clamp(head.pitch - 1.9198622F - addedPitch, minPitch, 3.3F);
|
||||
arm.yaw = head.yaw;
|
||||
|
||||
if (state.isInSneakingPose) {
|
||||
if (sneaking) {
|
||||
arm.pivotY += 9;
|
||||
arm.pivotX -= 6 * sigma;
|
||||
arm.pivotZ -= 2;
|
||||
}
|
||||
if (state.attributes.size == SizePreset.TALL) {
|
||||
if (getSize() == SizePreset.TALL) {
|
||||
arm.pivotY += 1;
|
||||
}
|
||||
if (state.attributes.size == SizePreset.FOAL) {
|
||||
if (getSize() == SizePreset.FOAL) {
|
||||
arm.pivotY -= 2;
|
||||
}
|
||||
|
||||
|
@ -394,36 +462,38 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
arm.pitch = MathHelper.clamp(head.pitch, -0.55f, 1.2f) - 1.7835298f;
|
||||
arm.yaw = head.yaw - 0.1235988f * sigma;
|
||||
arm.pivotY += 3;
|
||||
arm.roll += 0.3F * -state.limbAmplitudeMultiplier * sigma;
|
||||
arm.roll += 0.3F * -limbSpeed * sigma;
|
||||
break;
|
||||
case BRUSH:
|
||||
arm.pitch = arm.pitch * 0.5f - 0.62831855f;
|
||||
arm.yaw = 0;
|
||||
arm.roll += 0.3F * -state.limbAmplitudeMultiplier * sigma;
|
||||
arm.roll += 0.3F * -limbSpeed * sigma;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected final void aimBow(T state, ModelPart arm) {
|
||||
arm.pitch = MathUtil.Angles._270_DEG + head.pitch + (MathHelper.sin(state.limbAmplitudeMultiplier * 0.067F) * 0.05F);
|
||||
protected void aimBow(ModelPart arm, float limbSpeed) {
|
||||
arm.pitch = MathUtil.Angles._270_DEG + head.pitch + (MathHelper.sin(limbSpeed * 0.067F) * 0.05F);
|
||||
arm.yaw = head.yaw - 0.06F;
|
||||
arm.roll = MathHelper.cos(state.limbAmplitudeMultiplier * 0.09F) * 0.05F + 0.05F;
|
||||
arm.roll = MathHelper.cos(limbSpeed * 0.09F) * 0.05F + 0.05F;
|
||||
|
||||
if (state.isInSneakingPose) {
|
||||
if (sneaking) {
|
||||
arm.pivotY += 4;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Animates arm swinging. Delegates to the correct arm/leg/limb as necessary.
|
||||
* Animates arm swinging. Delegates to the correct arm/leg/limb as neccessary.
|
||||
*
|
||||
* @param entity The entity we are being called for.
|
||||
*/
|
||||
protected final void swingItem(T state) {
|
||||
if (state.handSwingProgress > 0 && !state.attributes.isLyingDown) {
|
||||
swingArm(state, getArm(state.preferredArm));
|
||||
protected void swingItem(T entity) {
|
||||
if (getSwingAmount() > 0 && !attributes.isLyingDown) {
|
||||
Arm mainSide = getPreferredArm(entity);
|
||||
|
||||
swingArm(getArm(mainSide));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -432,11 +502,11 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
*
|
||||
* @param arm The arm to swing
|
||||
*/
|
||||
protected final void swingArm(T state, ModelPart arm) {
|
||||
float swing = 1 - (float)Math.pow(1 - state.handSwingProgress, 3);
|
||||
protected void swingArm(ModelPart arm) {
|
||||
float swing = 1 - (float)Math.pow(1 - getSwingAmount(), 3);
|
||||
|
||||
float deltaX = MathHelper.sin(swing * MathHelper.PI);
|
||||
float deltaZ = MathHelper.sin(state.handSwingProgress * MathHelper.PI);
|
||||
float deltaZ = MathHelper.sin(getSwingAmount() * MathHelper.PI);
|
||||
|
||||
float deltaAim = deltaZ * (0.7F - head.pitch) * 0.75F;
|
||||
|
||||
|
@ -451,26 +521,26 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
* @param animationProgress Total whole and partial ticks since the entity's existence.
|
||||
* Used in animations together with {@code swing} and {@code move}.
|
||||
*/
|
||||
protected void animateBreathing(T state) {
|
||||
float cos = MathHelper.cos(state.age * 0.09F) * 0.05F + 0.05F;
|
||||
float sin = MathHelper.sin(state.age * 0.067F) * 0.05F;
|
||||
protected void animateBreathing(float animationProgress) {
|
||||
float cos = MathHelper.cos(animationProgress * 0.09F) * 0.05F + 0.05F;
|
||||
float sin = MathHelper.sin(animationProgress * 0.067F) * 0.05F;
|
||||
|
||||
if (state.attributes.shouldLiftArm(state.rightArmPose, state.leftArmPose, -1)) {
|
||||
if (attributes.shouldLiftArm(rightArmPose, leftArmPose, -1)) {
|
||||
ModelPart arm = getArm(Arm.RIGHT);
|
||||
arm.roll += cos;
|
||||
arm.pitch += sin;
|
||||
}
|
||||
|
||||
if (state.attributes.shouldLiftArm(state.leftArmPose, state.rightArmPose, 1)) {
|
||||
if (attributes.shouldLiftArm(leftArmPose, rightArmPose, 1)) {
|
||||
ModelPart arm = getArm(Arm.LEFT);
|
||||
arm.roll += cos;
|
||||
arm.pitch += sin;
|
||||
}
|
||||
}
|
||||
|
||||
protected void adjustBody(T state, float pitch, Pivot pivot) {
|
||||
protected void adjustBody(float pitch, Pivot pivot) {
|
||||
adjustBodyComponents(pitch, pivot);
|
||||
if (!state.attributes.isHorsey) {
|
||||
if (!attributes.isHorsey) {
|
||||
neck.setPivot(NECK_X + pitch, pivot.y(), pivot.z());
|
||||
rightLeg.pivotY = FRONT_LEGS_Y;
|
||||
leftLeg.pivotY = FRONT_LEGS_Y;
|
||||
|
@ -486,49 +556,92 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
|
|||
body.pivotZ = pivot.z();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getRiderYOffset() {
|
||||
switch ((SizePreset)getSize()) {
|
||||
case NORMAL: return 0.4F;
|
||||
case FOAL:
|
||||
case TALL:
|
||||
case BULKY:
|
||||
default: return 0.25F;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean visible) {
|
||||
super.setVisible(visible);
|
||||
neck.visible = visible;
|
||||
hat.visible = false;
|
||||
hat.visible &= !attributes.isHorsey;
|
||||
parts.forEach(part -> part.setVisible(visible, attributes));
|
||||
}
|
||||
|
||||
public void positionheldItem(T state, Arm arm, MatrixStack matrices) {
|
||||
@Override
|
||||
public final void setArmAngle(Arm arm, MatrixStack matrices) {
|
||||
super.setArmAngle(arm, matrices);
|
||||
positionheldItem(arm, matrices);
|
||||
}
|
||||
|
||||
protected void positionheldItem(Arm arm, MatrixStack matrices) {
|
||||
float left = arm == Arm.LEFT ? -1 : 1;
|
||||
|
||||
UseAction action = state.getHeldItem(arm).action;
|
||||
UseAction action = getAttributes().heldStack.getUseAction();
|
||||
|
||||
if (action == UseAction.SPYGLASS && state.attributes.itemUseTime > 0) {
|
||||
return;
|
||||
if (action == UseAction.SPYGLASS && getAttributes().itemUseTime > 0) {
|
||||
|
||||
Arm main = getAttributes().mainArm;
|
||||
if (getAttributes().activeHand == Hand.OFF_HAND) {
|
||||
main = main.getOpposite();
|
||||
}
|
||||
if (main == arm) {
|
||||
matrices.translate(left * -0.05F, 0.5F, 0.2F);
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(-60));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (getAttributes().isRidingInteractive) {
|
||||
matrices.translate(left / 10, -0.2F, -0.5F);
|
||||
}
|
||||
|
||||
matrices.translate(-left * 0.1F, 0.45F, 0);
|
||||
|
||||
if (action == UseAction.BLOCK && state.attributes.itemUseTime == 0) {
|
||||
if (getAttributes().heldStack.getUseAction() == UseAction.BLOCK && getAttributes().itemUseTime == 0) {
|
||||
matrices.translate(left * 0.02F, -0.25F, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(T state, BodyPart part, MatrixStack stack) {
|
||||
public void transform(BodyPart part, MatrixStack stack) {
|
||||
|
||||
if (state.attributes.isHorsey) {
|
||||
if (attributes.isHorsey) {
|
||||
stack.translate(0, 0.1F, 0);
|
||||
}
|
||||
|
||||
if (state.attributes.isSleeping || state.attributes.isRiptide) {
|
||||
if (attributes.isSleeping || attributes.isRiptide) {
|
||||
stack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
|
||||
stack.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180));
|
||||
}
|
||||
|
||||
if (state.attributes.isLyingDown && !state.attributes.isSleeping) {
|
||||
boolean crouching = attributes.isCrouching;
|
||||
|
||||
if (attributes.isLyingDown && !attributes.isSleeping) {
|
||||
stack.translate(0, 1.35F, 0);
|
||||
attributes.isCrouching = sneaking;
|
||||
}
|
||||
|
||||
if (state.attributes.isHorsey && part == BodyPart.BODY) {
|
||||
stack.scale(1.5F, 1, 1.5F);
|
||||
if (attributes.isHorsey) {
|
||||
if (part == BodyPart.BODY) {
|
||||
stack.scale(1.5F, 1, 1.5F);
|
||||
}
|
||||
|
||||
neck.visible = head.visible;
|
||||
} else {
|
||||
neck.hidden = !head.visible;
|
||||
}
|
||||
|
||||
PonyTransformation.forSize(state.attributes.size).transform(state.attributes, part, stack);
|
||||
PonyTransformation.forSize(getSize()).transform(this, part, stack);
|
||||
|
||||
attributes.isCrouching = crouching;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,19 @@ package com.minelittlepony.client.model;
|
|||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.entity.model.*;
|
||||
import net.minecraft.client.render.entity.state.PlayerEntityRenderState;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.util.Arm;
|
||||
import net.minecraft.util.Hand;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.api.events.PonyModelPrepareCallback;
|
||||
import com.minelittlepony.api.model.*;
|
||||
import com.minelittlepony.client.render.entity.state.PonyRenderState;
|
||||
import com.minelittlepony.api.pony.Pony;
|
||||
import com.minelittlepony.api.pony.PonyData;
|
||||
import com.minelittlepony.api.pony.meta.Size;
|
||||
import com.minelittlepony.api.pony.meta.SizePreset;
|
||||
import com.minelittlepony.mson.api.model.biped.MsonPlayer;
|
||||
|
||||
/**
|
||||
* The raw pony model without any implementations.
|
||||
|
@ -16,43 +23,73 @@ import com.minelittlepony.client.render.entity.state.PonyRenderState;
|
|||
*
|
||||
* Modders can extend this class to make their own pony models if they wish.
|
||||
*/
|
||||
public abstract class ClientPonyModel<T extends PonyRenderState> extends PlayerEntityModel implements PonyModel<T> {
|
||||
public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer<T> implements PonyModel<T> {
|
||||
|
||||
/**
|
||||
* The model attributes.
|
||||
*/
|
||||
protected ModelAttributes attributes = new ModelAttributes();
|
||||
|
||||
@Nullable
|
||||
protected PosingCallback<T> onSetModelAngles;
|
||||
|
||||
@Deprecated
|
||||
@Nullable
|
||||
protected T currentState;
|
||||
|
||||
public ClientPonyModel(ModelPart tree, boolean smallArms) {
|
||||
super(tree, smallArms);
|
||||
public ClientPonyModel(ModelPart tree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
public void onSetModelAngles(PosingCallback<T> callback) {
|
||||
onSetModelAngles = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the model's various rotation angles.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Arm getPreferredArm(T livingEntity) {
|
||||
Arm arm = livingEntity.getMainArm();
|
||||
return livingEntity.preferredHand == Hand.MAIN_HAND ? arm : arm.getOpposite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setAngles(PlayerEntityRenderState entity) {
|
||||
currentState = (T)entity;
|
||||
super.setAngles((PlayerEntityRenderState)entity);
|
||||
public void updateLivingState(T entity, Pony pony, ModelAttributes.Mode mode) {
|
||||
child = entity.isBaby();
|
||||
attributes.updateLivingState(entity, pony, mode);
|
||||
PonyModelPrepareCallback.EVENT.invoker().onPonyModelPrepared(entity, this, mode);
|
||||
sneaking = attributes.isCrouching && !attributes.isLyingDown;
|
||||
riding = attributes.isSitting;
|
||||
}
|
||||
|
||||
setModelVisibilities((T)entity);
|
||||
setModelAngles((T)entity);
|
||||
@Override
|
||||
public final void copyAttributes(BipedEntityModel<T> other) {
|
||||
copyStateTo(other);
|
||||
}
|
||||
|
||||
if (onSetModelAngles != null) {
|
||||
onSetModelAngles.poseModel(this, (T)entity);
|
||||
/**
|
||||
* Copies this model's attributes into the passed model.
|
||||
*/
|
||||
@Override
|
||||
public void copyStateTo(EntityModel<T> model) {
|
||||
super.copyStateTo(model);
|
||||
|
||||
if (model instanceof ClientPonyModel) {
|
||||
((ClientPonyModel<T>)model).attributes = attributes;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setModelVisibilities(T state) {
|
||||
@Override
|
||||
public final ModelAttributes getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
protected void setModelAngles(T entity) {
|
||||
@Override
|
||||
public Size getSize() {
|
||||
return child ? SizePreset.FOAL : PonyModel.super.getSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMetadata(PonyData meta) {
|
||||
attributes.metadata = meta;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSwingAmount() {
|
||||
return handSwingProgress;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -65,8 +102,18 @@ public abstract class ClientPonyModel<T extends PonyRenderState> extends PlayerE
|
|||
return side == Arm.LEFT ? leftLeg : rightLeg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArmPose getArmPoseForSide(Arm side) {
|
||||
return side == Arm.RIGHT ? rightArmPose : leftArmPose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHatVisible(boolean visible) {
|
||||
|
||||
}
|
||||
|
||||
static void resetPivot(ModelPart part) {
|
||||
part.setPivot(part.getDefaultTransform().pivotX(), part.getDefaultTransform().pivotY(), part.getDefaultTransform().pivotZ());
|
||||
part.setPivot(part.getDefaultTransform().pivotX, part.getDefaultTransform().pivotY, part.getDefaultTransform().pivotZ);
|
||||
}
|
||||
|
||||
static void resetPivot(ModelPart...parts) {
|
||||
|
@ -75,7 +122,7 @@ public abstract class ClientPonyModel<T extends PonyRenderState> extends PlayerE
|
|||
}
|
||||
}
|
||||
|
||||
public interface PosingCallback<S extends PonyRenderState> {
|
||||
void poseModel(ClientPonyModel<S> model, S state);
|
||||
public interface PosingCallback<T extends LivingEntity> {
|
||||
void poseModel(ClientPonyModel<T> model, float move, float swing, float ticks, T entity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
package com.minelittlepony.client.model;
|
||||
|
||||
import net.minecraft.client.model.Model;
|
||||
import net.minecraft.client.model.Model.SinglePartModel;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.entity.model.ArmorStandEntityModel;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.mob.VexEntity;
|
||||
import net.minecraft.entity.passive.*;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import com.minelittlepony.api.model.BodyPart;
|
||||
import com.minelittlepony.api.model.PonyModel;
|
||||
import com.minelittlepony.api.model.gear.*;
|
||||
import com.minelittlepony.api.pony.meta.Race;
|
||||
import com.minelittlepony.api.pony.meta.Wearable;
|
||||
import com.minelittlepony.client.MineLittlePony;
|
||||
import com.minelittlepony.client.model.armour.PonyArmourModel;
|
||||
import com.minelittlepony.client.model.entity.*;
|
||||
import com.minelittlepony.client.model.entity.race.*;
|
||||
|
@ -28,7 +29,7 @@ import java.util.function.BiFunction;
|
|||
import java.util.stream.Stream;
|
||||
|
||||
public final class ModelType {
|
||||
private static final Map<Race, PlayerModelKey<?>> PLAYER_MODELS = new HashMap<>();
|
||||
private static final Map<Race, PlayerModelKey<?, ?>> PLAYER_MODELS = new HashMap<>();
|
||||
private static final Map<Wearable, GearModelKey<? extends Gear>> GEAR_MODELS = new HashMap<>();
|
||||
|
||||
public static final ModelKey<DJPon3EarsModel> DJ_PON_3 = register("dj_pon_three", DJPon3EarsModel::new);
|
||||
|
@ -36,64 +37,63 @@ public final class ModelType {
|
|||
public static final ModelKey<WitchPonyModel> WITCH = register("witch", WitchPonyModel::new);
|
||||
public static final ModelKey<ZomponyModel<?>> ZOMBIE = register("zombie", ZomponyModel::new);
|
||||
public static final ModelKey<PiglinPonyModel> PIGLIN = register("piglin", PiglinPonyModel::new);
|
||||
public static final ModelKey<AlicornModel<?>> SKELETON = register("skeleton", tree -> new AlicornModel<>(tree, false));
|
||||
public static final ModelKey<SinglePartModel> BOGGED_MUSHROOMS = register("bogged_mushrooms", tree -> new SinglePartModel(tree, RenderLayer::getEntityTranslucent));
|
||||
public static final ModelKey<AlicornModel<?>> SKELETON_CLOTHES = register("skeleton_clothes", tree -> new AlicornModel<>(tree, false));
|
||||
public static final ModelKey<ChangelingModel<?>> PILLAGER = register("pillager", tree -> new ChangelingModel<>(tree, false));
|
||||
public static final ModelKey<SkeleponyModel<?>> SKELETON = register("skeleton", SkeleponyModel::new);
|
||||
public static final ModelKey<SkeleponyModel<?>> SKELETON_CLOTHES = register("skeleton_clothes", SkeleponyModel::new);
|
||||
public static final ModelKey<PillagerPonyModel<?>> PILLAGER = register("pillager", PillagerPonyModel::new);
|
||||
public static final ModelKey<IllagerPonyModel<?>> ILLAGER = register("illager", IllagerPonyModel::new);
|
||||
public static final ModelKey<SeaponyModel<?>> GUARDIAN = register("guardian", SeaponyModel::new);
|
||||
public static final ModelKey<GuardianPonyModel> GUARDIAN = register("guardian", GuardianPonyModel::new);
|
||||
public static final ModelKey<EnderStallionModel> ENDERMAN = register("enderman", EnderStallionModel::new);
|
||||
public static final ModelKey<ParaspriteModel> VEX = register("vex", ParaspriteModel::new);
|
||||
public static final ModelKey<SpikeModel> STRIDER = register("strider", SpikeModel::new);
|
||||
public static final ModelKey<SaddleModel> STRIDER_SADDLE = register("strider_saddle", SaddleModel::new);
|
||||
public static final ModelKey<BreezieModel> ALLAY = register("allay", BreezieModel::new);
|
||||
public static final ModelKey<ParaspriteModel<VexEntity>> VEX = register("vex", ParaspriteModel::new);
|
||||
public static final ModelKey<SpikeModel<StriderEntity>> STRIDER = register("strider", SpikeModel::new);
|
||||
public static final ModelKey<SaddleModel<StriderEntity>> STRIDER_SADDLE = register("strider_saddle", SaddleModel::new);
|
||||
public static final ModelKey<BreezieModel<AllayEntity>> ALLAY = register("allay", BreezieModel::new);
|
||||
|
||||
public static final ModelKey<PonyElytra<?>> ELYTRA = register("elytra", PonyElytra::new);
|
||||
|
||||
public static final ModelKey<PonyArmourStandModel> ARMOUR_STAND = register("armour_stand", PonyArmourStandModel::new);
|
||||
public static final ModelKey<AbstractPonyModel<?>> INNER_VANILLA_ARMOR = register("armor/inner_vanilla_armor", PonyArmourModel::new);
|
||||
public static final ModelKey<AbstractPonyModel<?>> OUTER_VANILLA_ARMOR = register("armor/outer_vanilla_armor", PonyArmourModel::new);
|
||||
public static final ModelKey<AbstractPonyModel<?>> INNER_PONY_ARMOR = register("armor/inner_pony_armor", PonyArmourModel::new);
|
||||
public static final ModelKey<AbstractPonyModel<?>> OUTER_PONY_ARMOR = register("armor/outer_pony_armor", PonyArmourModel::new);
|
||||
public static final ModelKey<ArmorStandEntityModel> ARMOUR_STAND = register("armour_stand", PonyArmourStandModel::new);
|
||||
public static final ModelKey<PonyArmourModel<?>> INNER_VANILLA_ARMOR = register("armor/inner_vanilla_armor", PonyArmourModel::new);
|
||||
public static final ModelKey<PonyArmourModel<?>> OUTER_VANILLA_ARMOR = register("armor/outer_vanilla_armor", PonyArmourModel::new);
|
||||
public static final ModelKey<PonyArmourModel<?>> INNER_PONY_ARMOR = register("armor/inner_pony_armor", PonyArmourModel::new);
|
||||
public static final ModelKey<PonyArmourModel<?>> OUTER_PONY_ARMOR = register("armor/outer_pony_armor", PonyArmourModel::new);
|
||||
|
||||
public static final GearModelKey<AbstractGearModel> STETSON = registerGear("stetson", Wearable.STETSON, t -> new WearableGear(t, Wearable.STETSON, BodyPart.HEAD, 0.15F));
|
||||
public static final GearModelKey<AbstractGearModel> STETSON = registerGear("stetson", Wearable.STETSON, t -> new WearableGear(Wearable.STETSON, BodyPart.HEAD, 0.15F));
|
||||
public static final GearModelKey<SaddleBags> SADDLEBAGS_BOTH = registerGear("saddlebags", Wearable.SADDLE_BAGS_BOTH, t -> new SaddleBags(t, Wearable.SADDLE_BAGS_BOTH));
|
||||
public static final GearModelKey<SaddleBags> SADDLEBAGS_LEFT = registerGear(SADDLEBAGS_BOTH, Wearable.SADDLE_BAGS_LEFT, t -> new SaddleBags(t, Wearable.SADDLE_BAGS_LEFT));
|
||||
public static final GearModelKey<SaddleBags> SADDLEBAGS_RIGHT = registerGear(SADDLEBAGS_BOTH, Wearable.SADDLE_BAGS_RIGHT, t -> new SaddleBags(t, Wearable.SADDLE_BAGS_RIGHT));
|
||||
public static final GearModelKey<AbstractGearModel> CROWN = registerGear("crown", Wearable.CROWN, t -> new WearableGear(t.getChild("crown"), Wearable.CROWN, BodyPart.HEAD, 0.1F));
|
||||
public static final GearModelKey<AbstractGearModel> MUFFIN = registerGear("muffin", Wearable.MUFFIN, t -> new WearableGear(t.getChild("crown"), Wearable.MUFFIN, BodyPart.HEAD, 0.45F));
|
||||
public static final GearModelKey<AbstractGearModel> WITCH_HAT = registerGear("witch_hat", Wearable.HAT, t -> new WearableGear(t.getChild("hat"), Wearable.HAT, BodyPart.HEAD, 0.7F));
|
||||
public static final GearModelKey<Crown> CROWN = registerGear("crown", Wearable.CROWN, Crown::new);
|
||||
public static final GearModelKey<AbstractGearModel> MUFFIN = registerGear("muffin", Wearable.MUFFIN, t -> new WearableGear(Wearable.MUFFIN, BodyPart.HEAD, 0.45F).addPart(t.getChild("crown")));
|
||||
public static final GearModelKey<AbstractGearModel> WITCH_HAT = registerGear("witch_hat", Wearable.HAT, t -> new WearableGear(Wearable.HAT, BodyPart.HEAD, 0.7F).addPart(t.getChild("hat")));
|
||||
public static final GearModelKey<DeerAntlers> ANTLERS = registerGear("antlers", Wearable.ANTLERS, DeerAntlers::new);
|
||||
|
||||
public static final PlayerModelKey<AlicornModel<?>> ALICORN = registerPlayer("alicorn", Race.ALICORN, AlicornModel::new);
|
||||
public static final PlayerModelKey<UnicornModel<?>> UNICORN = registerPlayer("unicorn", Race.UNICORN, UnicornModel::new);
|
||||
public static final PlayerModelKey<KirinModel<?>> KIRIN = registerPlayer("kirin", Race.KIRIN, KirinModel::new);
|
||||
public static final PlayerModelKey<PegasusModel<?>> PEGASUS = registerPlayer("pegasus", Race.PEGASUS, PegasusModel::new);
|
||||
public static final PlayerModelKey<PegasusModel<?>> GRYPHON = registerPlayer("gryphon", Race.GRYPHON, PegasusModel::new);
|
||||
public static final PlayerModelKey<PegasusModel<?>> HIPPOGRIFF = registerPlayer("hippogriff", Race.HIPPOGRIFF, PegasusModel::new, PonyArmourModel::new);
|
||||
public static final PlayerModelKey<EarthPonyModel<?>> EARTH_PONY = registerPlayer("earth_pony", Race.EARTH, EarthPonyModel::new);
|
||||
public static final PlayerModelKey<SeaponyModel<?>> SEA_PONY = registerPlayer("sea_pony", Race.SEAPONY, SeaponyModel::new, SeaponyModel.Armour::new);
|
||||
public static final PlayerModelKey<PegasusModel<?>> BAT_PONY = registerPlayer("bat_pony", Race.BATPONY, PegasusModel::new);
|
||||
public static final PlayerModelKey<ChangelingModel<?>> CHANGELING = registerPlayer("changeling", Race.CHANGELING, ChangelingModel::new);
|
||||
public static final PlayerModelKey<ChangelingModel<?>> CHANGEDLING = registerPlayer("reformed_changeling", Race.CHANGEDLING, ChangelingModel::new);
|
||||
public static final PlayerModelKey<EarthPonyModel<?>> ZEBRA = registerPlayer("zebra", Race.ZEBRA, EarthPonyModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, AlicornModel<?>> ALICORN = registerPlayer("alicorn", Race.ALICORN, AlicornModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, UnicornModel<?>> UNICORN = registerPlayer("unicorn", Race.UNICORN, UnicornModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, KirinModel<?>> KIRIN = registerPlayer("kirin", Race.KIRIN, KirinModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, PegasusModel<?>> PEGASUS = registerPlayer("pegasus", Race.PEGASUS, PegasusModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, PegasusModel<?>> GRYPHON = registerPlayer("gryphon", Race.GRYPHON, PegasusModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, PegasusModel<?>> HIPPOGRIFF = registerPlayer("hippogriff", Race.HIPPOGRIFF, PegasusModel::new, PonyArmourModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, EarthPonyModel<?>> EARTH_PONY = registerPlayer("earth_pony", Race.EARTH, EarthPonyModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, SeaponyModel<?>> SEA_PONY = registerPlayer("sea_pony", Race.SEAPONY, SeaponyModel::new, SeaponyModel.Armour::new);
|
||||
public static final PlayerModelKey<LivingEntity, PegasusModel<?>> BAT_PONY = registerPlayer("bat_pony", Race.BATPONY, PegasusModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, ChangelingModel<?>> CHANGELING = registerPlayer("changeling", Race.CHANGELING, ChangelingModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, ChangelingModel<?>> CHANGEDLING = registerPlayer("reformed_changeling", Race.CHANGEDLING, ChangelingModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, EarthPonyModel<?>> ZEBRA = registerPlayer("zebra", Race.ZEBRA, EarthPonyModel::new);
|
||||
|
||||
static <E extends LivingEntity, T extends Model & MsonModel & PonyModel<?>> PlayerModelKey<T> registerPlayer(String name, Race race,
|
||||
static <E extends LivingEntity, T extends Model & MsonModel & PonyModel<?>> PlayerModelKey<E, T> registerPlayer(String name, Race race,
|
||||
BiFunction<ModelPart, Boolean, T> constructor) {
|
||||
return registerPlayer(name, race, constructor, PonyArmourModel::new);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T extends Model & PonyModel<?>> PlayerModelKey<T> registerPlayer(String name, Race race,
|
||||
static <E extends LivingEntity, T extends Model & MsonModel & PonyModel<?>> PlayerModelKey<E, T> registerPlayer(String name, Race race,
|
||||
BiFunction<ModelPart, Boolean, T> constructor,
|
||||
MsonModel.Factory<AbstractPonyModel<?>> armorFactory) {
|
||||
return (PlayerModelKey<T>)PLAYER_MODELS.computeIfAbsent(race, r -> new PlayerModelKey<T>(name, constructor, armorFactory));
|
||||
MsonModel.Factory<PonyArmourModel<E>> armorFactory) {
|
||||
return (PlayerModelKey<E, T>)PLAYER_MODELS.computeIfAbsent(race, r -> new PlayerModelKey<>(name, constructor, armorFactory));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T extends AbstractGearModel> GearModelKey<T> registerGear(String name, Wearable wearable, MsonModel.Factory<T> constructor) {
|
||||
return (GearModelKey<T>)GEAR_MODELS.computeIfAbsent(wearable, w -> {
|
||||
return new GearModelKey<T>(Mson.getInstance().registerModel(MineLittlePony.id("gear/" + name), constructor), constructor);
|
||||
return new GearModelKey<T>(Mson.getInstance().registerModel(new Identifier("minelittlepony", "gear/" + name), constructor), constructor);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -103,13 +103,13 @@ public final class ModelType {
|
|||
}
|
||||
|
||||
static <T extends Model> ModelKey<T> register(String name, MsonModel.Factory<T> constructor) {
|
||||
return new ModelKeyImpl<T>(MineLittlePony.id(name), constructor);
|
||||
return new ModelKeyImpl<T>(new Identifier("minelittlepony", name), constructor);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
public static <T extends Model & PonyModel<?>> PlayerModelKey<T> getPlayerModel(Race race) {
|
||||
return (PlayerModelKey<T>)PLAYER_MODELS.get(race);
|
||||
public static <E extends LivingEntity, T extends Model & MsonModel & PonyModel<?>> PlayerModelKey<E, T> getPlayerModel(Race race) {
|
||||
return (PlayerModelKey<E, T>)PLAYER_MODELS.get(race);
|
||||
}
|
||||
|
||||
public static Stream<Map.Entry<Wearable, GearModelKey<? extends Gear>>> getWearables() {
|
||||
|
|
|
@ -2,28 +2,27 @@ package com.minelittlepony.client.model;
|
|||
|
||||
import net.minecraft.client.model.Model;
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.api.model.Models;
|
||||
import com.minelittlepony.api.model.PonyModel;
|
||||
import com.minelittlepony.client.MineLittlePony;
|
||||
import com.minelittlepony.client.model.armour.PonyArmourModel;
|
||||
import com.minelittlepony.mson.api.*;
|
||||
|
||||
import java.util.function.*;
|
||||
|
||||
public record PlayerModelKey<M extends Model & PonyModel<?>> (
|
||||
public record PlayerModelKey<T extends LivingEntity, M extends Model & PonyModel<?>> (
|
||||
ModelKey<M> steveKey,
|
||||
ModelKey<M> alexKey,
|
||||
MsonModel.Factory<AbstractPonyModel<?>> armorFactory
|
||||
MsonModel.Factory<PonyArmourModel<T>> armorFactory
|
||||
) {
|
||||
PlayerModelKey(String name,
|
||||
BiFunction<ModelPart, Boolean, M> modelFactory,
|
||||
MsonModel.Factory<AbstractPonyModel<?>> armorFactory
|
||||
) {
|
||||
PlayerModelKey(String name, BiFunction<ModelPart, Boolean, M> modelFactory, MsonModel.Factory<PonyArmourModel<T>> armorFactory) {
|
||||
this(
|
||||
new ModelKeyImpl<>(MineLittlePony.id("races/steve/" + name), tree -> modelFactory.apply(tree, false)),
|
||||
new ModelKeyImpl<>(MineLittlePony.id("races/alex/" + name), tree -> modelFactory.apply(tree, true)),
|
||||
new ModelKeyImpl<>(new Identifier("minelittlepony", "races/steve/" + name), tree -> modelFactory.apply(tree, false)),
|
||||
new ModelKeyImpl<>(new Identifier("minelittlepony", "races/alex/" + name), tree -> modelFactory.apply(tree, true)),
|
||||
armorFactory
|
||||
);
|
||||
}
|
||||
|
@ -32,11 +31,12 @@ public record PlayerModelKey<M extends Model & PonyModel<?>> (
|
|||
return slimArms ? alexKey : steveKey;
|
||||
}
|
||||
|
||||
public <N extends M> Models<N> create(boolean slimArms) {
|
||||
public <E extends T, N extends M> Models<E, N> create(boolean slimArms) {
|
||||
return create(slimArms, null);
|
||||
}
|
||||
|
||||
public <N extends M> Models<N> create(boolean slimArms, @Nullable Consumer<N> initializer) {
|
||||
return new Models<>(this, slimArms, initializer);
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public <E extends T, N extends M> Models<E, N> create(boolean slimArms, @Nullable Consumer<N> initializer) {
|
||||
return new Models(this, slimArms, initializer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +1,90 @@
|
|||
package com.minelittlepony.client.model;
|
||||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.entity.model.EntityModel;
|
||||
import net.minecraft.client.render.entity.state.BipedEntityRenderState;
|
||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||
import net.minecraft.client.render.entity.model.AnimalModel;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* Modified from ModelElytra.
|
||||
*/
|
||||
public class PonyElytra<T extends BipedEntityRenderState> extends EntityModel<T> {
|
||||
public class PonyElytra<T extends LivingEntity> extends AnimalModel<T> {
|
||||
|
||||
public boolean isSneaking;
|
||||
|
||||
private final ModelPart rightWing;
|
||||
private final ModelPart leftWing;
|
||||
|
||||
public PonyElytra(ModelPart root) {
|
||||
super(root);
|
||||
rightWing = root.getChild("right_wing");
|
||||
leftWing = root.getChild("left_wing");
|
||||
public PonyElytra(ModelPart tree) {
|
||||
rightWing = tree.getChild("right_wing");
|
||||
leftWing = tree.getChild("left_wing");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAngles(T state) {
|
||||
leftWing.pitch = state.leftWingPitch;
|
||||
leftWing.yaw = state.leftWingYaw;
|
||||
leftWing.roll = state.leftWingRoll;
|
||||
protected Iterable<ModelPart> getHeadParts() {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<ModelPart> getBodyParts() {
|
||||
return ImmutableList.of(leftWing, rightWing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the model's various rotation angles.
|
||||
*
|
||||
* See {@link AbstractPonyModel.setRotationAngles} for an explanation of the various parameters.
|
||||
*/
|
||||
@Override
|
||||
public void setAngles(T entity, float limbDistance, float limbAngle, float age, float headYaw, float headPitch) {
|
||||
float rotateX = MathHelper.PI / 2;
|
||||
float rotateY = MathHelper.PI / 8;
|
||||
float rotateZ = MathHelper.PI / 12;
|
||||
|
||||
float rpY = 0;
|
||||
|
||||
if (entity.isFallFlying()) {
|
||||
float velY = 1;
|
||||
|
||||
Vec3d motion = entity.getVelocity();
|
||||
if (motion.y < 0) {
|
||||
velY = 1 - (float) Math.pow(-motion.normalize().y, 1.5);
|
||||
}
|
||||
|
||||
rotateX = velY * MathHelper.PI * (2 / 3F) + (1 - velY) * rotateX;
|
||||
rotateY = velY * (MathHelper.PI / 2) + (1 - velY) * rotateY;
|
||||
} else if (isSneaking) {
|
||||
rotateX = MathHelper.PI * 1.175F;
|
||||
rotateY = MathHelper.PI / 2;
|
||||
rotateZ = MathHelper.PI / 4;
|
||||
rpY = AbstractPonyModel.BODY_SNEAKING.y();
|
||||
}
|
||||
|
||||
leftWing.pivotX = 5;
|
||||
leftWing.pivotY = rpY;
|
||||
|
||||
if (entity instanceof AbstractClientPlayerEntity) {
|
||||
AbstractClientPlayerEntity player = (AbstractClientPlayerEntity) entity;
|
||||
|
||||
player.elytraPitch += (rotateX - player.elytraPitch) / 10;
|
||||
player.elytraYaw += (rotateY - player.elytraYaw) / 10;
|
||||
player.elytraRoll += (rotateZ - player.elytraRoll) / 10;
|
||||
|
||||
leftWing.pitch = player.elytraPitch;
|
||||
leftWing.yaw = player.elytraYaw;
|
||||
leftWing.roll = player.elytraRoll;
|
||||
} else {
|
||||
leftWing.pitch = rotateX;
|
||||
leftWing.yaw = rotateZ;
|
||||
leftWing.roll = rotateY;
|
||||
}
|
||||
|
||||
rightWing.pivotX = -leftWing.pivotX;
|
||||
rightWing.pivotY = leftWing.pivotY;
|
||||
rightWing.pitch = leftWing.pitch;
|
||||
rightWing.yaw = -leftWing.yaw;
|
||||
rightWing.roll = -leftWing.roll;
|
||||
|
|
|
@ -1,25 +1,23 @@
|
|||
package com.minelittlepony.client.model.armour;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.client.render.entity.equipment.EquipmentModel;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import com.minelittlepony.client.model.AbstractPonyModel;
|
||||
import com.minelittlepony.mson.api.ModelKey;
|
||||
import com.minelittlepony.mson.api.Mson;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public interface ArmorModelRegistry {
|
||||
static final Map<Identifier, Optional<ModelKey<AbstractPonyModel<?>>>> REGISTRY = new HashMap<>();
|
||||
static final Map<Identifier, Optional<ModelKey<PonyArmourModel<?>>>> REGISTRY = new HashMap<>();
|
||||
|
||||
public static Optional<ModelKey<AbstractPonyModel<?>>> getModelKey(Item item, EquipmentModel.LayerType layerType) {
|
||||
public static Optional<ModelKey<PonyArmourModel<?>>> getModelKey(Item item, ArmourLayer layer) {
|
||||
Identifier id = Registries.ITEM.getId(item);
|
||||
if (id.getNamespace().equals("minecraft")) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return REGISTRY.computeIfAbsent(id.withPath(p -> "armor/" + layerType.name().toLowerCase(Locale.ROOT) + "_" + p + ".json"), i -> {
|
||||
return REGISTRY.computeIfAbsent(id.withPath(p -> "armor/" + layer.name().toLowerCase(Locale.ROOT) + "_" + p + ".json"), i -> {
|
||||
return Optional.of(Mson.getInstance().registerModel(i, PonyArmourModel::new));
|
||||
}).filter(key -> key.getModelData().isPresent());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package com.minelittlepony.client.model.armour;
|
||||
|
||||
/**
|
||||
* The layer used to render a given armour piece.
|
||||
*/
|
||||
public enum ArmourLayer {
|
||||
/**
|
||||
* Hanging loose and sagging free
|
||||
*/
|
||||
OUTER,
|
||||
/**
|
||||
* Fits snugly to the player's model.
|
||||
*/
|
||||
INNER;
|
||||
|
||||
public int getLegacyId() {
|
||||
return ordinal() + 1;
|
||||
}
|
||||
|
||||
public boolean isInner() {
|
||||
return this == INNER;
|
||||
}
|
||||
}
|
|
@ -1,159 +0,0 @@
|
|||
package com.minelittlepony.client.model.armour;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.model.Model;
|
||||
import net.minecraft.client.render.*;
|
||||
import net.minecraft.client.render.entity.equipment.EquipmentModel;
|
||||
import net.minecraft.client.render.entity.state.BipedEntityRenderState;
|
||||
import net.minecraft.client.render.entity.state.LivingEntityRenderState;
|
||||
import net.minecraft.client.render.item.ItemRenderer;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.component.type.DyedColorComponent;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.item.*;
|
||||
import net.minecraft.item.equipment.EquipmentAsset;
|
||||
import net.minecraft.item.equipment.trim.ArmorTrim;
|
||||
import net.minecraft.item.equipment.trim.ArmorTrimMaterial;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.entry.RegistryEntry;
|
||||
import net.minecraft.registry.tag.ItemTags;
|
||||
import net.minecraft.util.*;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public interface ArmourRendererPlugin {
|
||||
AtomicReference<ArmourRendererPlugin> INSTANCE = new AtomicReference<>(new ArmourRendererPlugin() {});
|
||||
|
||||
static void register(Function<ArmourRendererPlugin, ArmourRendererPlugin> constructor) {
|
||||
INSTANCE.set(constructor.apply(INSTANCE.get()));
|
||||
}
|
||||
|
||||
default ArmourTextureLookup getTextureLookup() {
|
||||
return ArmourTextureResolver.INSTANCE;
|
||||
}
|
||||
|
||||
default void onArmourRendered(LivingEntityRenderState state, MatrixStack matrices, VertexConsumerProvider provider, EquipmentSlot armorSlot, EquipmentModel.LayerType layerType, ArmourType type) {
|
||||
|
||||
}
|
||||
|
||||
default ItemStack[] getArmorStacks(BipedEntityRenderState state, EquipmentSlot armorSlot, EquipmentModel.LayerType layerType, ArmourType type) {
|
||||
return new ItemStack[] { switch (armorSlot) {
|
||||
case HEAD -> state.equippedHeadStack;
|
||||
case CHEST -> state.equippedChestStack;
|
||||
case LEGS -> state.equippedLegsStack;
|
||||
case FEET -> state.equippedFeetStack;
|
||||
case BODY -> state.equippedChestStack;
|
||||
default -> ItemStack.EMPTY;
|
||||
// TODO: Mojaaaaaaang!!
|
||||
//case MAINHAND -> state.getMainHandStack();
|
||||
//case OFFHAND -> state.mainArm == Arm.LEFT ? state.leftHandStack : state.rightHandStack;
|
||||
}};
|
||||
}
|
||||
|
||||
default float getGlintAlpha(EquipmentSlot slot, ItemStack stack) {
|
||||
return stack.hasGlint() ? 1 : 0;
|
||||
}
|
||||
|
||||
default int getDyeColor(EquipmentSlot slot, ItemStack stack) {
|
||||
return stack.isIn(ItemTags.DYEABLE) ? DyedColorComponent.getColor(stack, -6265536) : Colors.WHITE;
|
||||
}
|
||||
|
||||
default float getArmourAlpha(EquipmentSlot slot, EquipmentModel.LayerType layer) {
|
||||
return 1F;
|
||||
}
|
||||
|
||||
default float getTrimAlpha(EquipmentSlot slot, ArmorTrim trim, EquipmentModel.LayerType layer) {
|
||||
return 1F;
|
||||
}
|
||||
|
||||
default float getElytraAlpha(ItemStack stack, Model model, LivingEntityRenderState entity) {
|
||||
return stack.isOf(Items.ELYTRA) ? 1F : 0F;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
default VertexConsumer getTrimConsumer(EquipmentSlot slot, VertexConsumerProvider provider, ArmorTrim trim, EquipmentModel.LayerType layerType, RegistryKey<EquipmentAsset> assetId) {
|
||||
@Nullable VertexConsumer buffer = getOptionalBuffer(provider, getTrimLayer(slot, trim, layerType, assetId));
|
||||
if (buffer == null) {
|
||||
return null;
|
||||
}
|
||||
SpriteAtlasTexture armorTrimsAtlas = MinecraftClient.getInstance().getBakedModelManager().getAtlas(TexturedRenderLayers.ARMOR_TRIMS_ATLAS_TEXTURE);
|
||||
Sprite sprite = armorTrimsAtlas.getSprite(getTexture(trim, layerType, assetId));
|
||||
return sprite.getTextureSpecificVertexConsumer(buffer);
|
||||
}
|
||||
|
||||
private static String getAssetName(RegistryEntry<ArmorTrimMaterial> material, RegistryKey<EquipmentAsset> assetKey) {
|
||||
String string = (String)material.value().overrideArmorAssets().get(assetKey);
|
||||
return string != null ? string : material.value().assetName();
|
||||
}
|
||||
|
||||
private static Identifier getTexture(ArmorTrim trim, EquipmentModel.LayerType layerType, RegistryKey<EquipmentAsset> assetId) {
|
||||
Identifier identifier = trim.pattern().value().assetId();
|
||||
String string = getAssetName(trim.material(), assetId);
|
||||
return identifier.withPath((UnaryOperator<String>)(path -> "trims/entity/" + layerType.asString() + "/" + path + "_" + string));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
default RenderLayer getTrimLayer(EquipmentSlot slot, ArmorTrim trim, EquipmentModel.LayerType layerType, RegistryKey<EquipmentAsset> assetId) {
|
||||
return TexturedRenderLayers.getArmorTrims(trim.pattern().value().decal());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
default VertexConsumer getArmourConsumer(EquipmentSlot slot, VertexConsumerProvider provider, Identifier texture, EquipmentModel.LayerType layer) {
|
||||
return getOptionalBuffer(provider, getArmourLayer(slot, texture, layer));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
default RenderLayer getArmourLayer(EquipmentSlot slot, Identifier texture, EquipmentModel.LayerType layer) {
|
||||
return RenderLayer.getArmorCutoutNoCull(texture);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
default VertexConsumer getGlintConsumer(EquipmentSlot slot, VertexConsumerProvider provider, EquipmentModel.LayerType layer) {
|
||||
return getOptionalBuffer(provider, getGlintLayer(slot, layer));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
default RenderLayer getGlintLayer(EquipmentSlot slot, EquipmentModel.LayerType layer) {
|
||||
return RenderLayer.getArmorEntityGlint();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
default VertexConsumer getCapeConsumer(BipedEntityRenderState entity, VertexConsumerProvider provider, Identifier texture) {
|
||||
if (entity.equippedChestStack.isOf(Items.ELYTRA)) {
|
||||
return null;
|
||||
}
|
||||
return getOptionalBuffer(provider, getCapeLayer(entity, texture));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
default RenderLayer getCapeLayer(BipedEntityRenderState entity, Identifier texture) {
|
||||
return RenderLayer.getEntitySolid(texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Method is no longer used
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
default VertexConsumer getElytraConsumer(ItemStack stack, Model model, BipedEntityRenderState state, VertexConsumerProvider provider, Identifier texture) {
|
||||
return ItemRenderer.getArmorGlintConsumer(provider, RenderLayer.getArmorCutoutNoCull(texture), getGlintAlpha(EquipmentSlot.CHEST, stack) > 0F);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static VertexConsumer getOptionalBuffer(VertexConsumerProvider provider, @Nullable RenderLayer layer) {
|
||||
return layer == null ? null : provider.getBuffer(layer);
|
||||
}
|
||||
|
||||
public enum ArmourType {
|
||||
ARMOUR,
|
||||
CAPE,
|
||||
ELYTRA,
|
||||
SKULL
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package com.minelittlepony.client.model.armour;
|
||||
|
||||
import net.minecraft.client.texture.TextureManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import com.google.common.collect.Interner;
|
||||
import com.google.common.collect.Interners;
|
||||
import com.minelittlepony.api.config.PonyConfig;
|
||||
import com.minelittlepony.util.ResourceUtil;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public record ArmourTexture(Identifier texture, ArmourVariant variant) {
|
||||
private static final Interner<ArmourTexture> INTERNER = Interners.newWeakInterner();
|
||||
public static final ArmourTexture UNKNOWN = legacy(TextureManager.MISSING_IDENTIFIER);
|
||||
|
||||
public boolean validate() {
|
||||
return texture != TextureManager.MISSING_IDENTIFIER && ResourceUtil.textureExists(texture);
|
||||
}
|
||||
|
||||
public static ArmourTexture legacy(Identifier texture) {
|
||||
return INTERNER.intern(new ArmourTexture(texture, ArmourVariant.LEGACY));
|
||||
}
|
||||
|
||||
public static ArmourTexture modern(Identifier texture) {
|
||||
return INTERNER.intern(new ArmourTexture(texture, ArmourVariant.NORMAL));
|
||||
}
|
||||
|
||||
public Stream<ArmourTexture> ponify() {
|
||||
if (!PonyConfig.getInstance().disablePonifiedArmour.get()) {
|
||||
return Stream.of(modern(texture().withPath(p -> p.replace("humanoid", "ponified"))), this);
|
||||
}
|
||||
return Stream.of(this);
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package com.minelittlepony.client.model.armour;
|
||||
|
||||
import net.minecraft.client.render.entity.equipment.EquipmentModel;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public interface ArmourTextureLookup {
|
||||
ArmourTexture getTexture(ItemStack stack, EquipmentModel.LayerType layerType, EquipmentModel.Layer layer);
|
||||
}
|
|
@ -1,19 +1,24 @@
|
|||
package com.minelittlepony.client.model.armour;
|
||||
|
||||
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
|
||||
import net.minecraft.client.render.entity.equipment.EquipmentModel;
|
||||
import net.minecraft.item.*;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.resource.ResourceReloader;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.texture.TextureManager;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.item.ArmorItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.util.Identifier;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.minelittlepony.api.config.PonyConfig;
|
||||
import com.minelittlepony.util.ResourceUtil;
|
||||
|
||||
import com.google.common.cache.*;
|
||||
import com.minelittlepony.client.MineLittlePony;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* The default texture resolver used by Mine Little Pony.
|
||||
|
@ -30,51 +35,100 @@ import java.util.stream.Stream;
|
|||
* - the "minecraft" namespace is always replaced with "minelittlepony"
|
||||
* <p>
|
||||
*/
|
||||
public class ArmourTextureResolver implements ArmourTextureLookup, IdentifiableResourceReloadListener {
|
||||
public static final Identifier ID = MineLittlePony.id("armor_textures");
|
||||
public class ArmourTextureResolver {
|
||||
public static final ArmourTextureResolver INSTANCE = new ArmourTextureResolver();
|
||||
|
||||
private final LoadingCache<ArmourParameters, ArmourTexture> layerCache = CacheBuilder.newBuilder()
|
||||
private final Cache<String, Identifier> cache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(30, TimeUnit.SECONDS)
|
||||
.build(CacheLoader.from(parameters -> Stream.of(ArmourTexture.legacy(parameters.textureId())).flatMap(this::performLookup).findFirst().orElse(ArmourTexture.UNKNOWN)));
|
||||
|
||||
private Stream<ArmourTexture> performLookup(ArmourTexture id) {
|
||||
List<ArmourTexture> options = Stream.of(id).flatMap(ArmourTexture::ponify).toList();
|
||||
return options.stream().distinct()
|
||||
.filter(ArmourTexture::validate)
|
||||
.findFirst()
|
||||
.or(() -> {
|
||||
MineLittlePony.LOGGER.warn("Could not identify correct texture to use for {}. Was none of: [" + System.lineSeparator() + "{}" + System.lineSeparator() + "]", id, options.stream()
|
||||
.map(ArmourTexture::texture)
|
||||
.map(Identifier::toString)
|
||||
.collect(Collectors.joining("," + System.lineSeparator())));
|
||||
return Optional.empty();
|
||||
}).stream();
|
||||
}
|
||||
.<String, Identifier>build();
|
||||
|
||||
public void invalidate() {
|
||||
layerCache.invalidateAll();
|
||||
cache.invalidateAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> reload(ResourceReloader.Synchronizer synchronizer, ResourceManager manager, Executor prepareExecutor, Executor applyExecutor) {
|
||||
return CompletableFuture.runAsync(this::invalidate, prepareExecutor).thenCompose(synchronizer::whenPrepared);
|
||||
}
|
||||
public Identifier getTexture(LivingEntity entity, ItemStack stack, EquipmentSlot slot, ArmourLayer layer, @Nullable String type) {
|
||||
Identifier material = stack.getItem() instanceof ArmorItem armor
|
||||
? new Identifier(armor.getMaterial().getName())
|
||||
: Registries.ITEM.getId(stack.getItem());
|
||||
String custom = getCustom(stack);
|
||||
|
||||
@Override
|
||||
public Identifier getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
try {
|
||||
return cache.get(String.format("%s#%s#%s#%s", material, layer, type, custom), () -> {
|
||||
String typed = Strings.nullToEmpty(type);
|
||||
String extra = typed.isEmpty() ? "" : "_" + typed;
|
||||
|
||||
@Override
|
||||
public ArmourTexture getTexture(ItemStack stack, EquipmentModel.LayerType layerType, EquipmentModel.Layer layer) {
|
||||
layerCache.invalidateAll();
|
||||
return layerCache.getUnchecked(new ArmourParameters(layer, layerType));
|
||||
}
|
||||
Identifier texture;
|
||||
|
||||
private record ArmourParameters(EquipmentModel.Layer layer, EquipmentModel.LayerType layerType) {
|
||||
public Identifier textureId() {
|
||||
return layer.getFullTextureId(layerType);
|
||||
if (!"none".equals(custom)) {
|
||||
texture = resolveNewOrOld(material, layer, custom + extra, typed);
|
||||
if (texture != null) {
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
|
||||
texture = resolveNewOrOld(material, layer, extra, typed);
|
||||
if (texture != null) {
|
||||
return texture;
|
||||
}
|
||||
|
||||
return TextureManager.MISSING_IDENTIFIER;
|
||||
});
|
||||
} catch (ExecutionException ignored) {
|
||||
return TextureManager.MISSING_IDENTIFIER;
|
||||
}
|
||||
}
|
||||
|
||||
private String getCustom(ItemStack stack) {
|
||||
if (stack.hasNbt() && stack.getNbt().contains("CustomModelData", NbtElement.NUMBER_TYPE)) {
|
||||
return "custom_" + stack.getNbt().getInt("CustomModelData");
|
||||
}
|
||||
return "none";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Identifier resolveNewOrOld(Identifier material, ArmourLayer layer, String extra, String type) {
|
||||
Identifier texture = resolveHumanOrPony(ResourceUtil.format("%s:textures/models/armor/%s_layer_%s%s.png", material.getNamespace(), material.getPath(), layer, extra), type);
|
||||
|
||||
if (texture != null) {
|
||||
return texture;
|
||||
}
|
||||
|
||||
return resolveHumanOrPony(ResourceUtil.format("%s:textures/models/armor/%s_layer_%d%s.png", material.getNamespace(), material.getPath(), layer.getLegacyId(), extra), type);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Identifier resolveHumanOrPony(String res, String type) {
|
||||
Identifier human = new Identifier(res);
|
||||
|
||||
String domain = human.getNamespace();
|
||||
if ("minecraft".equals(domain)) {
|
||||
domain = "minelittlepony"; // it's a vanilla armor. I provide these.
|
||||
}
|
||||
|
||||
if (!PonyConfig.getInstance().disablePonifiedArmour.get()) {
|
||||
|
||||
Identifier pony = new Identifier(domain, human.getPath().replace(".png", "_pony.png"));
|
||||
|
||||
if (isValid(pony)) {
|
||||
return pony;
|
||||
}
|
||||
}
|
||||
|
||||
if (isValid(human)) {
|
||||
return human;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private final boolean isValid(Identifier texture) {
|
||||
return MinecraftClient.getInstance().getResourceManager().getResource(texture).isPresent();
|
||||
}
|
||||
|
||||
public ArmourVariant getVariant(ArmourLayer layer, Identifier resolvedTexture) {
|
||||
if (resolvedTexture.getPath().endsWith("_pony.png")) {
|
||||
return ArmourVariant.NORMAL;
|
||||
}
|
||||
return ArmourVariant.LEGACY;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package com.minelittlepony.client.model.armour;
|
||||
|
||||
import net.minecraft.client.render.entity.equipment.EquipmentModel;
|
||||
|
||||
import com.minelittlepony.client.model.AbstractPonyModel;
|
||||
import com.minelittlepony.client.model.ModelType;
|
||||
import com.minelittlepony.mson.api.ModelKey;
|
||||
|
||||
|
@ -13,15 +10,15 @@ public enum ArmourVariant {
|
|||
LEGACY(ModelType.INNER_VANILLA_ARMOR, ModelType.OUTER_VANILLA_ARMOR),
|
||||
TRIM(ModelType.INNER_VANILLA_ARMOR, ModelType.OUTER_VANILLA_ARMOR);
|
||||
|
||||
private final Optional<ModelKey<AbstractPonyModel<?>>> innerModel;
|
||||
private final Optional<ModelKey<AbstractPonyModel<?>>> outerModel;
|
||||
private final Optional<ModelKey<PonyArmourModel<?>>> innerModel;
|
||||
private final Optional<ModelKey<PonyArmourModel<?>>> outerModel;
|
||||
|
||||
ArmourVariant(ModelKey<AbstractPonyModel<?>> inner, ModelKey<AbstractPonyModel<?>> outer) {
|
||||
ArmourVariant(ModelKey<PonyArmourModel<?>> inner, ModelKey<PonyArmourModel<?>> outer) {
|
||||
this.innerModel = Optional.of(inner);
|
||||
this.outerModel = Optional.of(outer);
|
||||
}
|
||||
|
||||
public Optional<ModelKey<AbstractPonyModel<?>>> getDefaultModel(EquipmentModel.LayerType layerType) {
|
||||
return layerType == EquipmentModel.LayerType.HUMANOID_LEGGINGS ? innerModel : outerModel;
|
||||
public Optional<ModelKey<PonyArmourModel<?>>> getDefaultModel(ArmourLayer layer) {
|
||||
return layer.isInner() ? innerModel : outerModel;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,154 +0,0 @@
|
|||
package com.minelittlepony.client.model.armour;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.*;
|
||||
import net.minecraft.client.render.entity.equipment.*;
|
||||
import net.minecraft.client.render.entity.model.EntityModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.component.type.DyedColorComponent;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.equipment.EquipmentAsset;
|
||||
import net.minecraft.item.equipment.trim.ArmorTrim;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.tag.ItemTags;
|
||||
import net.minecraft.util.Colors;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.ColorHelper;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.api.model.Models;
|
||||
import com.minelittlepony.client.model.AbstractPonyModel;
|
||||
import com.minelittlepony.client.model.ClientPonyModel;
|
||||
import com.minelittlepony.client.render.entity.state.PonyRenderState;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class PonifiedEquipmentRenderer extends EquipmentRenderer {
|
||||
private static final int TRANSPARENT = 0;
|
||||
|
||||
private final EquipmentModelLoader modelLoader;
|
||||
|
||||
private @Nullable Set<EntityModel<?>> drawnModels;
|
||||
|
||||
public PonifiedEquipmentRenderer(EquipmentModelLoader modelLoader) {
|
||||
super(modelLoader, MinecraftClient.getInstance().getBakedModelManager().getAtlas(TexturedRenderLayers.ARMOR_TRIMS_ATLAS_TEXTURE));
|
||||
this.modelLoader = modelLoader;
|
||||
}
|
||||
|
||||
public <S extends PonyRenderState, V extends ClientPonyModel<S>> void render(
|
||||
EquipmentSlot equipmentSlot,
|
||||
EquipmentModel.LayerType layerType,
|
||||
RegistryKey<EquipmentAsset> assetId,
|
||||
S entity,
|
||||
Models<V> models,
|
||||
ItemStack stack,
|
||||
MatrixStack matrices,
|
||||
VertexConsumerProvider vertexConsumers,
|
||||
int light
|
||||
) {
|
||||
render(equipmentSlot, layerType, assetId, entity, models, stack, matrices, vertexConsumers, light, null);
|
||||
}
|
||||
|
||||
public <S extends PonyRenderState, V extends ClientPonyModel<S>> void render(
|
||||
EquipmentSlot equipmentSlot,
|
||||
EquipmentModel.LayerType layerType,
|
||||
RegistryKey<EquipmentAsset> assetId,
|
||||
S entity,
|
||||
Models<V> models,
|
||||
ItemStack stack,
|
||||
MatrixStack matrices,
|
||||
VertexConsumerProvider vertices,
|
||||
int light,
|
||||
@Nullable Identifier texture
|
||||
) {
|
||||
List<EquipmentModel.Layer> layers = modelLoader.get(assetId).getLayers(layerType);
|
||||
if (!layers.isEmpty()) {
|
||||
ArmourRendererPlugin plugin = ArmourRendererPlugin.INSTANCE.get();
|
||||
int defaultColor = stack.isIn(ItemTags.DYEABLE) ? DyedColorComponent.getColor(stack, 0) : 0;
|
||||
float armorAlpha = plugin.getArmourAlpha(equipmentSlot, layerType);
|
||||
boolean hasGlint = plugin.getGlintAlpha(equipmentSlot, stack) > 0;
|
||||
|
||||
if (armorAlpha > 0) {
|
||||
for (EquipmentModel.Layer layer : layers) {
|
||||
int dyeColor = getDyeColor(layer, defaultColor);
|
||||
if (dyeColor != TRANSPARENT) {
|
||||
ArmourTexture armorTexture = plugin.getTextureLookup().getTexture(stack, layerType, layer);
|
||||
Identifier layerTexture = layer.usePlayerTexture() && texture != null ? texture : armorTexture.texture();
|
||||
|
||||
@Nullable
|
||||
VertexConsumer armorConsumer = getArmorVertexConsumer(plugin, equipmentSlot, vertices, layerTexture, layerType, hasGlint);
|
||||
if (armorConsumer != null) {
|
||||
ArmourVariant variant = layer.usePlayerTexture() ? ArmourVariant.LEGACY : armorTexture.variant();
|
||||
AbstractPonyModel<?> model = models.getArmourModel(stack, layerType, variant).orElse(null);
|
||||
if (model != null) {
|
||||
model.setAngles(entity);
|
||||
models.body().copyTransforms(model);
|
||||
if (setVisibilities(model, equipmentSlot, layerType)) {
|
||||
model.render(matrices, armorConsumer, light, OverlayTexture.DEFAULT_UV, dyeColor);
|
||||
if (drawnModels == null) {
|
||||
drawnModels = new HashSet<>();
|
||||
}
|
||||
drawnModels.add(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (drawnModels != null) {
|
||||
@Nullable
|
||||
ArmorTrim armorTrim = stack.get(DataComponentTypes.TRIM);
|
||||
@Nullable
|
||||
VertexConsumer trimConsumer = armorTrim != null && plugin.getTrimAlpha(equipmentSlot, armorTrim, layerType) > 0 ? plugin.getTrimConsumer(equipmentSlot, vertices, armorTrim, layerType, assetId) : null;
|
||||
if (trimConsumer != null) {
|
||||
for (EntityModel<?> model : drawnModels) {
|
||||
model.render(matrices, trimConsumer, light, OverlayTexture.DEFAULT_UV);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drawnModels = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static VertexConsumer getArmorVertexConsumer(ArmourRendererPlugin plugin, EquipmentSlot slot, VertexConsumerProvider provider, Identifier texture, EquipmentModel.LayerType layerType, boolean glint) {
|
||||
VertexConsumer armorConsumer = plugin.getArmourConsumer(slot, provider, texture, layerType);
|
||||
if (armorConsumer != null) {
|
||||
VertexConsumer glintConsumer = glint ? plugin.getGlintConsumer(slot, provider, layerType) : null;
|
||||
if (glintConsumer != null) {
|
||||
return VertexConsumers.union(glintConsumer, armorConsumer);
|
||||
}
|
||||
}
|
||||
return armorConsumer;
|
||||
}
|
||||
|
||||
private static int getDyeColor(EquipmentModel.Layer layer, int dyeColor) {
|
||||
Optional<EquipmentModel.Dyeable> optional = layer.dyeable();
|
||||
if (optional.isPresent()) {
|
||||
int i = optional.get().colorWhenUndyed().map(ColorHelper::fullAlpha).orElse(0);
|
||||
return dyeColor != TRANSPARENT ? dyeColor : i;
|
||||
}
|
||||
return Colors.WHITE;
|
||||
}
|
||||
|
||||
public static boolean setVisibilities(AbstractPonyModel<?> model, EquipmentSlot slot, EquipmentModel.LayerType layer) {
|
||||
model.setVisible(false);
|
||||
model.body.visible = slot == EquipmentSlot.CHEST;
|
||||
model.head.visible = layer == EquipmentModel.LayerType.HUMANOID && slot == EquipmentSlot.HEAD;
|
||||
|
||||
if (slot == (layer == EquipmentModel.LayerType.HUMANOID ? EquipmentSlot.FEET : EquipmentSlot.LEGS)) {
|
||||
model.rightArm.visible = true;
|
||||
model.leftArm.visible = true;
|
||||
model.rightLeg.visible = true;
|
||||
model.leftLeg.visible = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return model.head.visible || model.body.visible;
|
||||
}
|
||||
}
|
|
@ -1,13 +1,52 @@
|
|||
package com.minelittlepony.client.model.armour;
|
||||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
|
||||
import com.minelittlepony.api.model.PonyModel;
|
||||
import com.minelittlepony.client.model.AbstractPonyModel;
|
||||
import com.minelittlepony.client.render.entity.state.PonyRenderState;
|
||||
|
||||
public class PonyArmourModel<T extends PonyRenderState> extends AbstractPonyModel<T> {
|
||||
public class PonyArmourModel<T extends LivingEntity> extends AbstractPonyModel<T> {
|
||||
|
||||
public PonyArmourModel(ModelPart tree) {
|
||||
super(tree, false);
|
||||
super(tree);
|
||||
}
|
||||
|
||||
public boolean poseModel(T entity, float limbAngle, float limbDistance, float age, float headYaw, float headPitch,
|
||||
EquipmentSlot slot, ArmourLayer layer,
|
||||
PonyModel<T> mainModel) {
|
||||
|
||||
if (!setVisibilities(slot, layer)) {
|
||||
return false;
|
||||
}
|
||||
mainModel.copyAttributes(this);
|
||||
setAngles(entity, limbAngle, limbDistance, age, headYaw, headPitch);
|
||||
if (mainModel instanceof BipedEntityModel<?> biped) {
|
||||
head.copyTransform(biped.head);
|
||||
body.copyTransform(biped.body);
|
||||
rightArm.copyTransform(biped.rightArm);
|
||||
leftArm.copyTransform(biped.leftArm);
|
||||
rightLeg.copyTransform(biped.rightLeg);
|
||||
leftLeg.copyTransform(biped.leftLeg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean setVisibilities(EquipmentSlot slot, ArmourLayer layer) {
|
||||
setVisible(false);
|
||||
body.visible = slot == EquipmentSlot.CHEST;
|
||||
head.visible = layer == ArmourLayer.OUTER && slot == EquipmentSlot.HEAD;
|
||||
|
||||
if (slot == (layer == ArmourLayer.OUTER ? EquipmentSlot.FEET : EquipmentSlot.LEGS)) {
|
||||
rightArm.visible = true;
|
||||
leftArm.visible = true;
|
||||
rightLeg.visible = true;
|
||||
leftLeg.visible = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return head.visible || body.visible;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,19 +2,24 @@ package com.minelittlepony.client.model.entity;
|
|||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||
import net.minecraft.entity.EntityPose;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.util.Arm;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
import com.minelittlepony.client.render.entity.AllayRenderer;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
public class BreezieModel extends BipedEntityModel<AllayRenderer.State> {
|
||||
public class BreezieModel<T extends LivingEntity> extends BipedEntityModel<T> {
|
||||
|
||||
private ModelPart neck;
|
||||
|
||||
private ModelPart leftWing;
|
||||
private ModelPart rightWing;
|
||||
|
||||
public BreezieModel(ModelPart tree) {
|
||||
super(tree);
|
||||
neck = tree.getChild("neck");
|
||||
leftWing = tree.getChild("left_wing");
|
||||
rightWing = tree.getChild("right_wing");
|
||||
}
|
||||
|
@ -26,13 +31,15 @@ public class BreezieModel extends BipedEntityModel<AllayRenderer.State> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setAngles(AllayRenderer.State state) {
|
||||
protected Iterable<ModelPart> getBodyParts() {
|
||||
return Iterables.concat(super.getBodyParts(), ImmutableList.of(neck, leftWing, rightWing));
|
||||
}
|
||||
|
||||
float move = state.limbFrequency;
|
||||
float swing = state.limbAmplitudeMultiplier;
|
||||
@Override
|
||||
public void setAngles(T entity, float move, float swing, float ticks, float headYaw, float headPitch) {
|
||||
|
||||
head.yaw = state.yawDegrees * 0.017453292F;
|
||||
head.pitch = state.pitch * 0.017453292F;
|
||||
head.yaw = headYaw * 0.017453292F;
|
||||
head.pitch = headPitch * 0.017453292F;
|
||||
|
||||
hat.copyTransform(head);
|
||||
|
||||
|
@ -43,7 +50,7 @@ public class BreezieModel extends BipedEntityModel<AllayRenderer.State> {
|
|||
leftLeg .setAngles(swing * MathHelper.cos(move * 0.6662F + MathHelper.PI) * 1.4F, 0, 0);
|
||||
rightLeg.setAngles(swing * MathHelper.cos(move * 0.6662F) * 1.4F, 0, 0);
|
||||
|
||||
if (state.isInPose(EntityPose.SITTING)) {
|
||||
if (riding) {
|
||||
leftArm.pitch += -MathHelper.PI / 5;
|
||||
rightArm.pitch += -MathHelper.PI / 5;
|
||||
|
||||
|
@ -51,15 +58,15 @@ public class BreezieModel extends BipedEntityModel<AllayRenderer.State> {
|
|||
rotateLegRiding(rightLeg, 1);
|
||||
}
|
||||
|
||||
rotateArm(leftArm, state.leftArmPose, 1);
|
||||
rotateArm(rightArm, state.rightArmPose, 1);
|
||||
rotateArm(leftArm, leftArmPose, 1);
|
||||
rotateArm(rightArm, rightArmPose, 1);
|
||||
|
||||
if (state.handSwingProgress > 0) {
|
||||
swingArms(state, state.preferredArm);
|
||||
if (handSwingProgress > 0) {
|
||||
swingArms(getPreferredArm(entity));
|
||||
}
|
||||
|
||||
float rotX = MathHelper.sin(state.age * 0.067F) * 0.05F;
|
||||
float rotZ = MathHelper.cos(state.age * 0.09F) * 0.05F + 0.05F;
|
||||
float rotX = MathHelper.sin(ticks * 0.067F) * 0.05F;
|
||||
float rotZ = MathHelper.cos(ticks * 0.09F) * 0.05F + 0.05F;
|
||||
|
||||
leftArm.pitch -= rotX;
|
||||
leftArm.roll -= rotZ;
|
||||
|
@ -67,8 +74,8 @@ public class BreezieModel extends BipedEntityModel<AllayRenderer.State> {
|
|||
rightArm.pitch += rotX;
|
||||
rightArm.roll += rotZ;
|
||||
|
||||
rotX = MathHelper.sin(state.age * 0.3F) * 0.05F;
|
||||
rotZ = MathHelper.cos(state.age * 0.2F) * 0.05F + 0.05F;
|
||||
rotX = MathHelper.sin(ticks * 0.3F) * 0.05F;
|
||||
rotZ = MathHelper.cos(ticks * 0.2F) * 0.05F + 0.05F;
|
||||
|
||||
rotX -= 0.05F;
|
||||
|
||||
|
@ -77,19 +84,25 @@ public class BreezieModel extends BipedEntityModel<AllayRenderer.State> {
|
|||
rightWing.yaw = -rotX * 10;
|
||||
rightWing.pitch = rotZ;
|
||||
|
||||
if (state.rightArmPose == ArmPose.BOW_AND_ARROW) {
|
||||
if (rightArmPose == ArmPose.BOW_AND_ARROW) {
|
||||
raiseArm(rightArm, leftArm, -1);
|
||||
} else if (state.leftArmPose == ArmPose.BOW_AND_ARROW) {
|
||||
} else if (leftArmPose == ArmPose.BOW_AND_ARROW) {
|
||||
raiseArm(leftArm, rightArm, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private Arm getPreferredArm(T livingEntity) {
|
||||
Arm arm = livingEntity.getMainArm();
|
||||
return livingEntity.preferredHand == Hand.MAIN_HAND ? arm : arm.getOpposite();
|
||||
}
|
||||
|
||||
|
||||
protected void rotateLegRiding(ModelPart leg, float factor) {
|
||||
leg.setAngles(-1.4137167F, factor * MathHelper.PI / 10, factor * 0.07853982F);
|
||||
}
|
||||
|
||||
protected void swingArms(AllayRenderer.State state, Arm mainHand) {
|
||||
body.yaw = MathHelper.sin(MathHelper.sqrt(state.handSwingProgress) * MathHelper.TAU) / 5;
|
||||
protected void swingArms(Arm mainHand) {
|
||||
body.yaw = MathHelper.sin(MathHelper.sqrt(handSwingProgress) * MathHelper.TAU) / 5;
|
||||
|
||||
if (mainHand == Arm.LEFT) {
|
||||
body.yaw *= -1;
|
||||
|
@ -107,15 +120,15 @@ public class BreezieModel extends BipedEntityModel<AllayRenderer.State> {
|
|||
rightArm.pivotX = -cos;
|
||||
rightArm.pivotZ = sin;
|
||||
|
||||
float swingAmount = 1 - (float)Math.pow(1 - state.handSwingProgress, 4);
|
||||
float swingAmount = 1 - (float)Math.pow(1 - handSwingProgress, 4);
|
||||
|
||||
float swingFactorX = MathHelper.sin(swingAmount * MathHelper.PI);
|
||||
float swingX = MathHelper.sin(state.handSwingProgress * MathHelper.PI) * (0.7F - head.pitch) * 0.75F;
|
||||
float swingX = MathHelper.sin(handSwingProgress * MathHelper.PI) * (0.7F - head.pitch) * 0.75F;
|
||||
|
||||
ModelPart mainArm = getArm(mainHand);
|
||||
mainArm.pitch -= swingFactorX * 1.2F + swingX;
|
||||
mainArm.yaw += body.yaw * 2;
|
||||
mainArm.roll -= MathHelper.sin(state.handSwingProgress * MathHelper.PI) * 0.4F;
|
||||
mainArm.roll -= MathHelper.sin(handSwingProgress * MathHelper.PI) * 0.4F;
|
||||
}
|
||||
|
||||
protected void rotateArm(ModelPart arm, ArmPose pose, float factor) {
|
||||
|
|
|
@ -1,54 +1,92 @@
|
|||
package com.minelittlepony.client.model.entity;
|
||||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.mob.EndermanEntity;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
import com.minelittlepony.api.model.BodyPart;
|
||||
import com.minelittlepony.client.model.entity.race.AlicornModel;
|
||||
import com.minelittlepony.client.render.entity.EnderStallionRenderer;
|
||||
import com.minelittlepony.api.pony.meta.Race;
|
||||
|
||||
public class EnderStallionModel extends SkeleponyModel<EndermanEntity> {
|
||||
|
||||
public boolean isCarrying;
|
||||
public boolean isAttacking;
|
||||
|
||||
public boolean isAlicorn;
|
||||
public boolean isBoss;
|
||||
|
||||
public class EnderStallionModel extends AlicornModel<EnderStallionRenderer.State> {
|
||||
private final ModelPart leftHorn;
|
||||
private final ModelPart rightHorn;
|
||||
|
||||
public EnderStallionModel(ModelPart tree) {
|
||||
super(tree, false);
|
||||
super(tree);
|
||||
leftHorn = tree.getChild("left_horn");
|
||||
rightHorn = tree.getChild("right_horn");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setModelVisibilities(EnderStallionRenderer.State state) {
|
||||
super.setModelVisibilities(state);
|
||||
tail.setVisible(false, state);
|
||||
snout.setVisible(false, state);
|
||||
horn.setVisible(!state.isBoss, state);
|
||||
leftHorn.visible = rightHorn.visible = state.isBoss;
|
||||
public void animateModel(EndermanEntity entity, float move, float swing, float ticks) {
|
||||
rightArmPose = isCarrying ? ArmPose.BLOCK : ArmPose.EMPTY;
|
||||
leftArmPose = rightArmPose;
|
||||
|
||||
isUnicorn = true;
|
||||
isAlicorn = entity.getUuid().getLeastSignificantBits() % 3 == 0;
|
||||
isBoss = !isAlicorn && entity.getUuid().getLeastSignificantBits() % 90 == 0;
|
||||
|
||||
leftHorn.visible = rightHorn.visible = isBoss;
|
||||
horn.setVisible(!isBoss, attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModelAngles(EnderStallionRenderer.State state) {
|
||||
super.setModelAngles(state);
|
||||
public void setModelAngles(EndermanEntity entity, float move, float swing, float ticks, float headYaw, float headPitch) {
|
||||
super.setModelAngles(entity, move, swing, ticks, headYaw, headPitch);
|
||||
|
||||
if (state.isAttacking) {
|
||||
if (isAttacking) {
|
||||
head.pivotY -= 5;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(EnderStallionRenderer.State state, BodyPart part, MatrixStack stack) {
|
||||
public void render(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
|
||||
stack.push();
|
||||
stack.translate(0, -1.15F, 0);
|
||||
super.transform(state, part, stack);
|
||||
super.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Race getRace() {
|
||||
return isAlicorn ? (super.getRace().hasHorn() ? Race.ALICORN : Race.PEGASUS) : super.getRace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotateArmHolding(ModelPart arm, float direction, float swingProgress, float ticks) {
|
||||
arm.pitch = -0.3707964F;
|
||||
arm.pitch += 0.4F + MathHelper.sin(ticks * 0.067F) / 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean visible) {
|
||||
super.setVisible(visible);
|
||||
|
||||
tail.setVisible(false, attributes);
|
||||
snout.setVisible(false, attributes);
|
||||
|
||||
leftSleeve.visible = false;
|
||||
rightSleeve.visible = false;
|
||||
|
||||
leftPants.visible = false;
|
||||
rightPants.visible = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean wingsAreOpen() {
|
||||
return isAttacking;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getWingRotationFactor(float ticks) {
|
||||
return MathHelper.sin(ticks) + WINGS_HALF_SPREAD_ANGLE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package com.minelittlepony.client.model.entity;
|
||||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.entity.model.EntityModel;
|
||||
import net.minecraft.client.render.entity.model.GuardianEntityModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.mob.GuardianEntity;
|
||||
|
||||
import com.minelittlepony.api.model.PonyModelMixin;
|
||||
import com.minelittlepony.client.model.entity.race.SeaponyModel;
|
||||
|
||||
public class GuardianPonyModel extends GuardianEntityModel implements PonyModelMixin.Caster<GuardianEntity, SeaponyModel<GuardianEntity>, ModelPart> {
|
||||
private final SeaponyModel<GuardianEntity> mixin;
|
||||
|
||||
public GuardianPonyModel(ModelPart tree) {
|
||||
super(getTexturedModelData().createModel());
|
||||
mixin = new SeaponyModel<>(tree);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeaponyModel<GuardianEntity> mixin() {
|
||||
return mixin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) {
|
||||
mixin().render(matrices, vertices, light, overlay, red, green, blue, alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void animateModel(GuardianEntity entity, float limbAngle, float limbDistance, float tickDelta) {
|
||||
mixin().animateModel(entity, limbAngle, limbDistance, tickDelta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyStateTo(EntityModel<GuardianEntity> copy) {
|
||||
mixin().copyStateTo(copy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAngles(GuardianEntity entity, float limbAngle, float limbSpeed, float animationProgress, float headYaw, float headPitch) {
|
||||
mixin().setVisible(true);
|
||||
mixin().setAngles(entity, limbAngle, limbSpeed, animationProgress, headYaw, headPitch);
|
||||
}
|
||||
}
|
|
@ -6,30 +6,30 @@ import net.minecraft.util.Arm;
|
|||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
import com.minelittlepony.client.model.entity.race.AlicornModel;
|
||||
import com.minelittlepony.client.render.entity.npc.IllagerPonyRenderer;
|
||||
|
||||
public class IllagerPonyModel<S extends IllagerPonyRenderer.State> extends AlicornModel<S> {
|
||||
public class IllagerPonyModel<T extends IllagerEntity> extends AlicornModel<T> {
|
||||
|
||||
public IllagerPonyModel(ModelPart tree) {
|
||||
super(tree, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModelAngles(S state) {
|
||||
super.setModelAngles(state);
|
||||
IllagerEntity.State pose = state.state;
|
||||
public void setModelAngles(T illager, float move, float swing, float ticks, float headYaw, float headPitch) {
|
||||
super.setModelAngles(illager, move, swing, ticks, headYaw, headPitch);
|
||||
|
||||
boolean rightHanded = state.mainArm == Arm.RIGHT;
|
||||
IllagerEntity.State pose = illager.getState();
|
||||
|
||||
boolean rightHanded = illager.getMainArm() == Arm.RIGHT;
|
||||
float mult = rightHanded ? 1 : -1;
|
||||
ModelPart arm = getArm(state.mainArm);
|
||||
ModelPart arm = getArm(illager.getMainArm());
|
||||
|
||||
if (pose == IllagerEntity.State.ATTACKING) {
|
||||
// vindicator attacking
|
||||
float f = MathHelper.sin(state.handSwingProgress * (float) Math.PI);
|
||||
float f1 = MathHelper.sin((1 - (1 - state.handSwingProgress) * (1 - state.handSwingProgress)) * (float) Math.PI);
|
||||
float f = MathHelper.sin(getSwingAmount() * (float) Math.PI);
|
||||
float f1 = MathHelper.sin((1 - (1 - getSwingAmount()) * (1 - getSwingAmount())) * (float) Math.PI);
|
||||
|
||||
float cos = MathHelper.cos(state.age * 0.09F) * 0.05F + 0.05F;
|
||||
float sin = MathHelper.sin(state.age * 0.067F) * 0.05F;
|
||||
float cos = MathHelper.cos(ticks * 0.09F) * 0.05F + 0.05F;
|
||||
float sin = MathHelper.sin(ticks * 0.067F) * 0.05F;
|
||||
|
||||
rightArm.roll = cos;
|
||||
leftArm.roll = cos;
|
||||
|
@ -37,7 +37,7 @@ public class IllagerPonyModel<S extends IllagerPonyRenderer.State> extends Alico
|
|||
rightArm.yaw = 0.15707964F;
|
||||
leftArm.yaw = -0.15707964F;
|
||||
|
||||
arm.pitch = -1.8849558F + MathHelper.cos(state.age * 0.09F) * 0.15F;
|
||||
arm.pitch = -1.8849558F + MathHelper.cos(ticks * 0.09F) * 0.15F;
|
||||
arm.pitch += f * 2.2F - f1 * 0.4F;
|
||||
|
||||
rightArm.pitch += sin;
|
||||
|
@ -46,10 +46,10 @@ public class IllagerPonyModel<S extends IllagerPonyRenderer.State> extends Alico
|
|||
// waving arms!
|
||||
// rightArm.rotationPointZ = 0;
|
||||
arm.pitch = (float) (-.75F * Math.PI);
|
||||
arm.roll = mult * MathHelper.cos(state.age * 0.6662F) / 4;
|
||||
arm.roll = mult * MathHelper.cos(ticks * 0.6662F) / 4;
|
||||
arm.yaw = mult * 1.1F;
|
||||
} else if (pose == IllagerEntity.State.BOW_AND_ARROW) {
|
||||
aimBow(state, arm);
|
||||
aimBow(arm, ticks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,19 @@ package com.minelittlepony.client.model.entity;
|
|||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.entity.model.EntityModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.mob.VexEntity;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
import com.minelittlepony.client.render.entity.VexRenderer;
|
||||
import com.minelittlepony.common.util.animation.Interpolator;
|
||||
|
||||
public class ParaspriteModel<T extends LivingEntity> extends EntityModel<T> {
|
||||
|
||||
private final ModelPart root;
|
||||
|
||||
public class ParaspriteModel extends EntityModel<VexRenderer.State> {
|
||||
private final ModelPart body;
|
||||
private final ModelPart jaw;
|
||||
private final ModelPart lips;
|
||||
|
@ -17,45 +24,70 @@ public class ParaspriteModel extends EntityModel<VexRenderer.State> {
|
|||
private final ModelPart leftWing2;
|
||||
private final ModelPart rightWing2;
|
||||
|
||||
public ParaspriteModel(ModelPart root) {
|
||||
super(root, RenderLayer::getEntityTranslucent);
|
||||
body = root.getChild("body");
|
||||
public ParaspriteModel(ModelPart tree) {
|
||||
super(RenderLayer::getEntityTranslucent);
|
||||
child = false;
|
||||
root = tree;
|
||||
body = tree.getChild("body");
|
||||
jaw = body.getChild("jaw");
|
||||
lips = body.getChild("lips");
|
||||
leftWing = root.getChild("leftWing");
|
||||
rightWing = root.getChild("rightWing");
|
||||
leftWing2 = root.getChild("leftWing2");
|
||||
rightWing2 = root.getChild("rightWing2");
|
||||
leftWing = tree.getChild("leftWing");
|
||||
rightWing = tree.getChild("rightWing");
|
||||
leftWing2 = tree.getChild("leftWing2");
|
||||
rightWing2 = tree.getChild("rightWing2");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAngles(VexRenderer.State state) {
|
||||
root.pitch = state.bodyPitch;
|
||||
body.pitch = 0;
|
||||
root.pitch = state.pitch * MathHelper.RADIANS_PER_DEGREE;
|
||||
root.yaw = state.yawDegrees * MathHelper.RADIANS_PER_DEGREE;
|
||||
public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) {
|
||||
root.render(matrices, vertices, light, overlay, red, green, blue, alpha);
|
||||
}
|
||||
|
||||
jaw.pivotY = Math.max(0, 1.2F * state.jawOpenAmount);
|
||||
@Override
|
||||
public void setAngles(T entity, float move, float swing, float ticks, float headYaw, float headPitch) {
|
||||
|
||||
root.pitch = MathHelper.clamp((float)entity.getVelocity().horizontalLength() / 10F, 0, 0.1F);
|
||||
body.pitch = 0;
|
||||
|
||||
if (entity.hasPassengers()) {
|
||||
root.yaw = 0;
|
||||
root.pitch = 0;
|
||||
} else {
|
||||
root.yaw = headYaw * 0.017453292F;
|
||||
root.pitch = headPitch * 0.017453292F;
|
||||
}
|
||||
|
||||
float sin = (float)Math.sin(ticks) / 2F;
|
||||
float cos = (float)Math.cos(ticks) / 3F;
|
||||
|
||||
float jawOpenAmount = Interpolator.linear(entity.getUuid()).interpolate("jawOpen", entity instanceof VexEntity vex && vex.isCharging() ? 1 : 0, 10);
|
||||
|
||||
jaw.pivotY = Math.max(0, 1.2F * jawOpenAmount);
|
||||
lips.pivotY = jaw.pivotY - 0.9F;
|
||||
lips.visible = state.jawOpenAmount > 0;
|
||||
body.pitch += 0.3F * state.jawOpenAmount;
|
||||
jaw.pitch = 0.4F * state.jawOpenAmount;
|
||||
lips.pitch = 0.2F * state.jawOpenAmount;
|
||||
lips.visible = jawOpenAmount > 0;
|
||||
body.pitch += 0.3F * jawOpenAmount;
|
||||
jaw.pitch = 0.4F * jawOpenAmount;
|
||||
lips.pitch = 0.2F * jawOpenAmount;
|
||||
|
||||
float basWingExpand = 1;
|
||||
float innerWingExpand = basWingExpand / 2F;
|
||||
|
||||
leftWing.pitch = 0;
|
||||
leftWing.roll = state.wingRoll;
|
||||
leftWing.yaw = state.wingYaw;
|
||||
leftWing.roll = basWingExpand + cos + 0.3F;
|
||||
leftWing.yaw = basWingExpand - sin;
|
||||
|
||||
rightWing.pitch = 0;
|
||||
rightWing.roll = -state.wingRoll;
|
||||
rightWing.yaw = -state.wingYaw;
|
||||
rightWing.roll = -basWingExpand - cos - 0.3F;
|
||||
rightWing.yaw = -basWingExpand + sin;
|
||||
|
||||
sin = -(float)Math.sin(ticks + Math.PI / 4F) / 2F;
|
||||
cos = (float)Math.cos(ticks + Math.PI / 4F) / 3F;
|
||||
|
||||
leftWing2.pitch = 0;
|
||||
leftWing2.roll = state.innerWingRoll;
|
||||
leftWing2.yaw = state.innerWingPitch;
|
||||
leftWing2.roll = innerWingExpand + sin - 0.3F;
|
||||
leftWing2.yaw = innerWingExpand - cos + 0.3F;
|
||||
|
||||
rightWing2.pitch = 0;
|
||||
rightWing2.roll = -state.innerWingRoll;
|
||||
rightWing2.yaw = -state.innerWingPitch;
|
||||
rightWing2.roll = -innerWingExpand - sin + 0.3F;
|
||||
rightWing2.yaw = -innerWingExpand + cos - 0.3F;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
package com.minelittlepony.client.model.entity;
|
||||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.entity.mob.AbstractPiglinEntity;
|
||||
import net.minecraft.entity.mob.HostileEntity;
|
||||
import net.minecraft.entity.mob.PiglinActivity;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
import com.minelittlepony.client.render.entity.PonyPiglinRenderer;
|
||||
import com.minelittlepony.api.model.ModelAttributes;
|
||||
import com.minelittlepony.api.pony.Pony;
|
||||
|
||||
public class PiglinPonyModel extends ZomponyModel<PonyPiglinRenderer.State> {
|
||||
public class PiglinPonyModel extends ZomponyModel<HostileEntity> {
|
||||
|
||||
private PiglinActivity activity;
|
||||
|
||||
private final ModelPart leftFlap;
|
||||
private final ModelPart rightFlap;
|
||||
|
@ -18,39 +23,53 @@ public class PiglinPonyModel extends ZomponyModel<PonyPiglinRenderer.State> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setModelAngles(PonyPiglinRenderer.State state) {
|
||||
super.setModelAngles(state);
|
||||
public void updateLivingState(HostileEntity entity, Pony pony, ModelAttributes.Mode mode) {
|
||||
super.updateLivingState(entity, pony, mode);
|
||||
leftArmPose = ArmPose.EMPTY;
|
||||
rightArmPose = entity.getMainHandStack().isEmpty() ? ArmPose.EMPTY : ArmPose.ITEM;
|
||||
|
||||
float progress = state.age * 0.1F + state.limbFrequency * 0.5F;
|
||||
float range = 0.08F + state.limbAmplitudeMultiplier * 0.4F;
|
||||
if (entity instanceof AbstractPiglinEntity) {
|
||||
activity = ((AbstractPiglinEntity)entity).getActivity();
|
||||
|
||||
if (activity == PiglinActivity.CROSSBOW_HOLD) {
|
||||
rightArmPose = ArmPose.CROSSBOW_HOLD;
|
||||
} else if (activity == PiglinActivity.CROSSBOW_CHARGE) {
|
||||
rightArmPose = ArmPose.CROSSBOW_CHARGE;
|
||||
} else if (activity == PiglinActivity.ADMIRING_ITEM) {
|
||||
leftArmPose = ArmPose.ITEM;
|
||||
}
|
||||
} else {
|
||||
activity = PiglinActivity.DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModelAngles(HostileEntity entity, float move, float swing, float ticks, float headYaw, float headPitch) {
|
||||
super.setModelAngles(entity, move, swing, ticks, headYaw, headPitch);
|
||||
|
||||
float progress = ticks * 0.1F + move * 0.5F;
|
||||
float range = 0.08F + swing * 0.4F;
|
||||
rightFlap.roll = -0.5235988F - MathHelper.cos(progress * 1.2F) * range;
|
||||
leftFlap.roll = 0.5235988F + MathHelper.cos(progress) * range;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeadRotation(float animationProgress, float yaw, float pitch) {
|
||||
super.setHeadRotation(animationProgress, yaw, pitch);
|
||||
leftFlap.roll = -(float)(-(Math.cos((double)(animationProgress * (float) Math.PI * 0.2F * 1.2F)) + 2.5)) * 0.2F;
|
||||
rightFlap.roll = -(float)(Math.cos((double)(animationProgress * (float) Math.PI * 0.2F)) + 2.5) * 0.2F;
|
||||
}
|
||||
protected void rotateLegs(float move, float swing, float ticks, HostileEntity entity) {
|
||||
super.rotateLegs(move, swing, ticks, entity);
|
||||
|
||||
@Override
|
||||
protected void rotateLegs(PonyPiglinRenderer.State state) {
|
||||
super.rotateLegs(state);
|
||||
|
||||
if (state.activity == PiglinActivity.ADMIRING_ITEM) {
|
||||
if (activity == PiglinActivity.ADMIRING_ITEM) {
|
||||
leftArm.yaw = 0.5F;
|
||||
leftArm.pitch = -1.9F;
|
||||
leftArm.pivotY += 4;
|
||||
leftArm.pivotZ += 3;
|
||||
leftArm.pivotX += 2;
|
||||
head.pitch = MathHelper.sin(state.age / 12) / 6 + 0.5F;
|
||||
head.pitch = MathHelper.sin(ticks / 12) / 6 + 0.5F;
|
||||
head.yaw = 0;
|
||||
|
||||
head.roll = MathHelper.sin(state.age / 10) / 3F;
|
||||
} else if (state.activity == PiglinActivity.DANCING) {
|
||||
head.roll = MathHelper.sin(ticks / 10) / 3F;
|
||||
} else if (activity == PiglinActivity.DANCING) {
|
||||
|
||||
float speed = state.age / 60;
|
||||
float speed = ticks / 60;
|
||||
|
||||
head.pivotX = MathHelper.sin(speed * 10);
|
||||
head.pivotY = MathHelper.sin(speed * 40) + 0.4F;
|
||||
|
@ -74,7 +93,7 @@ public class PiglinPonyModel extends ZomponyModel<PonyPiglinRenderer.State> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldLiftBothArms(PonyPiglinRenderer.State state) {
|
||||
return state.zombified && super.shouldLiftBothArms(state);
|
||||
protected boolean isZombified(HostileEntity entity) {
|
||||
return !(entity instanceof AbstractPiglinEntity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package com.minelittlepony.client.model.entity;
|
||||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.entity.mob.IllagerEntity;
|
||||
import net.minecraft.entity.mob.PillagerEntity;
|
||||
import net.minecraft.util.Arm;
|
||||
|
||||
import com.minelittlepony.client.model.entity.race.ChangelingModel;
|
||||
|
||||
public class PillagerPonyModel<T extends PillagerEntity> extends ChangelingModel<T> {
|
||||
|
||||
public PillagerPonyModel(ModelPart tree) {
|
||||
super(tree, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void animateModel(T entity, float move, float swing, float ticks) {
|
||||
ArmPose holdingPose = getHoldingPose(entity.getState());
|
||||
|
||||
if (holdingPose != ArmPose.EMPTY) {
|
||||
boolean rightHanded = entity.getMainArm() == Arm.RIGHT;
|
||||
|
||||
leftArmPose = rightHanded ? ArmPose.EMPTY : holdingPose;
|
||||
rightArmPose = rightHanded ? holdingPose : ArmPose.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
protected ArmPose getHoldingPose(IllagerEntity.State state) {
|
||||
switch (state) {
|
||||
case BOW_AND_ARROW: return ArmPose.BOW_AND_ARROW;
|
||||
case CROSSBOW_CHARGE: return ArmPose.CROSSBOW_CHARGE;
|
||||
case CROSSBOW_HOLD: return ArmPose.CROSSBOW_HOLD;
|
||||
default: return ArmPose.EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,30 +3,42 @@ package com.minelittlepony.client.model.entity;
|
|||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.entity.model.ArmorStandEntityModel;
|
||||
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||
import net.minecraft.client.render.entity.state.ArmorStandEntityRenderState;
|
||||
import net.minecraft.entity.decoration.ArmorStandEntity;
|
||||
import net.minecraft.util.math.EulerAngle;
|
||||
|
||||
import com.minelittlepony.mson.util.PartUtil;
|
||||
|
||||
public class PonyArmourStandModel extends ArmorStandEntityModel {
|
||||
private static final EulerAngle DEFAULT_LEFT_LEG_ROTATION = new EulerAngle(-1, 0, -1);
|
||||
private static final EulerAngle DEFAULT_RIGHT_LEG_ROTATION = new EulerAngle(1, 0, 1);
|
||||
|
||||
public PonyArmourStandModel(ModelPart modelPart) {
|
||||
super(modelPart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyTransforms(BipedEntityModel<ArmorStandEntityRenderState> model) {
|
||||
if (model instanceof PonyArmourStandModel) {
|
||||
super.copyTransforms(model);
|
||||
} else {
|
||||
PartUtil.copyAngles(head, model.head);
|
||||
PartUtil.copyAngles(rightArm, model.rightArm);
|
||||
PartUtil.copyAngles(leftArm, model.leftArm);
|
||||
PartUtil.copyAngles(rightLeg, model.rightLeg);
|
||||
PartUtil.copyAngles(leftLeg, model.leftLeg);
|
||||
public void setAngles(ArmorStandEntity entity, float move, float swing, float ticks, float headYaw, float headPitch) {
|
||||
super.setAngles(entity, move, swing, ticks, headYaw, headPitch);
|
||||
leftArm.visible = true;
|
||||
rightArm.visible = true;
|
||||
|
||||
if (entity.getLeftLegRotation().equals(DEFAULT_LEFT_LEG_ROTATION)) {
|
||||
PartUtil.copyAngles(leftArm, leftLeg);
|
||||
leftLeg.pitch *= -1;
|
||||
}
|
||||
|
||||
if (entity.getRightLegRotation().equals(DEFAULT_RIGHT_LEG_ROTATION)) {
|
||||
PartUtil.copyAngles(rightArm, rightLeg);
|
||||
rightLeg.pitch *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAngles(ArmorStandEntityRenderState state) {
|
||||
super.setAngles(state);
|
||||
public void applyAnglesTo(BipedEntityModel<ArmorStandEntity> dest) {
|
||||
PartUtil.copyAngles(head, dest.head);
|
||||
PartUtil.copyAngles(hat, dest.hat);
|
||||
PartUtil.copyAngles(leftLeg, dest.leftLeg);
|
||||
PartUtil.copyAngles(rightLeg, dest.rightLeg);
|
||||
PartUtil.copyAngles(leftArm, dest.leftArm);
|
||||
PartUtil.copyAngles(rightArm, dest.rightArm);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,27 @@
|
|||
package com.minelittlepony.client.model.entity;
|
||||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.entity.model.EntityModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
import com.minelittlepony.client.render.entity.StriderRenderer;
|
||||
public class SaddleModel<T extends LivingEntity> extends EntityModel<T> {
|
||||
|
||||
private ModelPart root;
|
||||
|
||||
public class SaddleModel extends EntityModel<StriderRenderer.State> {
|
||||
public SaddleModel(ModelPart tree) {
|
||||
super(tree);
|
||||
root = tree;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAngles(StriderRenderer.State entity) {
|
||||
root.pivotY = 2 - MathHelper.cos(entity.limbFrequency * 1.5F) * 3 * entity.limbAmplitudeMultiplier;
|
||||
public void setAngles(T entity, float move, float swing, float ticks, float headYaw, float headPitch) {
|
||||
root.pivotY = 2 - MathHelper.cos(move * 1.5f) * 3.0f * swing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) {
|
||||
root.render(matrices, vertices, light, overlay, red, green, blue, alpha);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
package com.minelittlepony.client.model.entity;
|
||||
|
||||
import net.minecraft.entity.mob.WitherSkeletonEntity;
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.entity.mob.HostileEntity;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Arm;
|
||||
import net.minecraft.util.Hand;
|
||||
|
||||
import com.minelittlepony.api.model.MobPosingHelper;
|
||||
import com.minelittlepony.client.model.entity.race.AlicornModel;
|
||||
|
||||
public class SkeleponyModel<T extends HostileEntity> extends AlicornModel<T> {
|
||||
|
||||
public boolean isUnicorn;
|
||||
|
||||
public boolean isWithered;
|
||||
|
||||
public SkeleponyModel(ModelPart tree) {
|
||||
super(tree, false);
|
||||
this.vestRenderList.clear();
|
||||
this.sleevesRenderList.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void animateModel(T entity, float move, float swing, float ticks) {
|
||||
isUnicorn = entity.getUuid().getLeastSignificantBits() % 3 != 0;
|
||||
isWithered = entity instanceof WitherSkeletonEntity;
|
||||
|
||||
rightArmPose = ArmPose.EMPTY;
|
||||
leftArmPose = ArmPose.EMPTY;
|
||||
|
||||
ItemStack mainHand = entity.getStackInHand(Hand.MAIN_HAND);
|
||||
ItemStack offHand = entity.getStackInHand(Hand.OFF_HAND);
|
||||
|
||||
boolean right = entity.getMainArm() == Arm.RIGHT;
|
||||
|
||||
if (!offHand.isEmpty()) {
|
||||
if (right) {
|
||||
leftArmPose = ArmPose.ITEM;
|
||||
} else {
|
||||
rightArmPose = ArmPose.ITEM;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mainHand.isEmpty()) {
|
||||
ArmPose pose = mainHand.getItem() == Items.BOW && entity.isAttacking() ? ArmPose.BOW_AND_ARROW : ArmPose.ITEM;
|
||||
|
||||
if (right) {
|
||||
rightArmPose = pose;
|
||||
} else {
|
||||
leftArmPose = pose;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void rotateLegs(float move, float swing, float ticks, T entity) {
|
||||
super.rotateLegs(move, swing, ticks, entity);
|
||||
if (rightArmPose != ArmPose.EMPTY) {
|
||||
rotateArmHolding(getArm(Arm.RIGHT), -1, getSwingAmount(), ticks);
|
||||
}
|
||||
|
||||
if (leftArmPose != ArmPose.EMPTY) {
|
||||
rotateArmHolding(getArm(Arm.LEFT), -1, getSwingAmount(), ticks);
|
||||
}
|
||||
}
|
||||
|
||||
protected void rotateArmHolding(ModelPart arm, float direction, float swingProgress, float ticks) {
|
||||
MobPosingHelper.rotateArmHolding(arm, direction, swingProgress, ticks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMagic() {
|
||||
return isUnicorn;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getLegOutset() {
|
||||
if (attributes.isLyingDown) return 2.6f;
|
||||
if (attributes.isCrouching) return 0;
|
||||
return 4;
|
||||
}
|
||||
}
|
|
@ -2,10 +2,11 @@ package com.minelittlepony.client.model.entity;
|
|||
|
||||
import net.minecraft.client.model.ModelPart;
|
||||
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.passive.StriderEntity;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
import com.minelittlepony.client.render.entity.StriderRenderer;
|
||||
|
||||
public class SpikeModel extends BipedEntityModel<StriderRenderer.State> {
|
||||
public class SpikeModel<T extends LivingEntity> extends BipedEntityModel<T> {
|
||||
|
||||
private final ModelPart tail;
|
||||
private final ModelPart tail2;
|
||||
|
@ -19,12 +20,22 @@ public class SpikeModel extends BipedEntityModel<StriderRenderer.State> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setAngles(StriderRenderer.State entity) {
|
||||
super.setAngles(entity);
|
||||
public void setAngles(T entity, float move, float swing, float ticks, float headYaw, float headPitch) {
|
||||
swing *= 2;
|
||||
move *= 1.5F;
|
||||
child = false;
|
||||
|
||||
head.pivotX = 0;
|
||||
head.pivotZ = 0;
|
||||
head.pivotY = 0;
|
||||
|
||||
super.setAngles(entity, move, swing, ticks, headYaw, headPitch);
|
||||
|
||||
leftArm.pivotY++;
|
||||
rightArm.pivotY++;
|
||||
body.pitch += 0.15F;
|
||||
|
||||
if (entity.saddled) {
|
||||
if ((entity instanceof StriderEntity strider && strider.isSaddled())) {
|
||||
leftArm.pitch = 3.15F;
|
||||
leftArm.yaw = 1;
|
||||
rightArm.pitch = 3.15F;
|
||||
|
@ -38,8 +49,10 @@ public class SpikeModel extends BipedEntityModel<StriderRenderer.State> {
|
|||
leftLeg.pitch += 0.4F;
|
||||
rightLeg.pitch += 0.4F;
|
||||
} else {
|
||||
leftArm.roll -= 0.2F * entity.flailAmount;
|
||||
rightArm.roll += 0.2F * entity.flailAmount;
|
||||
float flailAmount = 1 + (float)MathHelper.clamp(entity.getVelocity().y * 10, 0, 7);
|
||||
|
||||
leftArm.roll -= 0.2F * flailAmount;
|
||||
rightArm.roll += 0.2F * flailAmount;
|
||||
|
||||
leftArm.pivotZ += 2;
|
||||
leftArm.pitch -= 0.3F;
|
||||
|
@ -47,8 +60,8 @@ public class SpikeModel extends BipedEntityModel<StriderRenderer.State> {
|
|||
rightArm.pivotZ += 2;
|
||||
rightArm.pitch -= 0.3F;
|
||||
|
||||
if (entity.cold) {
|
||||
float armMotion = (float)Math.sin(entity.age / 10F) / 10F;
|
||||
if (entity instanceof StriderEntity strider && strider.isCold()) {
|
||||
float armMotion = (float)Math.sin(ticks / 10F) / 10F;
|
||||
|
||||
leftArm.pitch = -1 - armMotion;
|
||||
rightArm.pitch = -1 + armMotion;
|
||||
|
@ -61,13 +74,21 @@ public class SpikeModel extends BipedEntityModel<StriderRenderer.State> {
|
|||
}
|
||||
}
|
||||
|
||||
tail.pitch = (float)Math.sin(entity.limbFrequency) / 3F - 0.5F;
|
||||
tail.pitch = (float)Math.sin(move) / 3F - 0.5F;
|
||||
tail2.pitch = -tail.pitch / 2;
|
||||
tail3.pitch = tail2.pitch / 2;
|
||||
|
||||
tail.yaw = (float)Math.sin(entity.age / 20F) / 40 + (float)Math.sin(entity.limbFrequency / 20F) / 4;
|
||||
tail.yaw = (float)Math.sin(ticks / 20F) / 40 + (float)Math.sin(move / 20F) / 4;
|
||||
tail2.yaw = tail.yaw / 2;
|
||||
tail3.yaw = tail2.yaw / 2;
|
||||
|
||||
for (var part : getHeadParts()) {
|
||||
part.pivotY += 7;
|
||||
}
|
||||
|
||||
for (var part : getBodyParts()) {
|
||||
part.pivotY += 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue