Compare commits

...

86 commits

Author SHA1 Message Date
Sollace
c42461cad6
[Backport] Ponify the bogged
# Conflicts:
#	src/main/java/com/minelittlepony/client/render/MobRenderers.java
#	src/main/java/com/minelittlepony/client/render/entity/SkeleponyRenderer.java
#	src/main/java/com/minelittlepony/client/render/entity/feature/AbstractClothingFeature.java
2024-12-15 22:42:50 +01:00
Sollace
5fce5b376c
Packport parrot sizing and fix parrots positioning 2024-12-15 17:19:37 +01:00
Sollace
7328d0c43d
Backport fixes for head position when riding/sitting 2024-12-15 17:19:18 +01:00
Sollace
7988da222f
Bump versions 2024-12-15 17:18:46 +01:00
SKL
a99b3f861b
2 New Bodytypes + Minor Bugfix (#294)
- added stocky bodytype with the trigger pixel of #b2e7dd
- added SQUAT bodytype, based on "big daddy's" and 2 other background pony bodytypes
- fixed #289
2024-12-13 22:06:37 +01:00
Sollace
add012294b
Bump hd skins 2024-11-27 14:54:14 +00:00
Sollace
0dc22d5c14
Update dependencies 2024-11-21 14:35:56 +00:00
Sollace
c8709ea1b8
Fix crash on synatra connector due to mapping differences 2024-09-29 14:28:34 +01:00
Sollace
ce176ab2b5
Update plugins 2024-09-18 00:32:43 +01:00
Sollace
0e57e62f5a
Implement server-side functionality for getting pony data from a texture 2024-07-31 14:38:20 +02:00
Sollace
95b32fca23
Fix error when accessing the pony config in a server environment 2024-07-31 14:35:39 +02:00
Sollace
2fea9b9e55
Unsaved changes 2024-07-25 22:34:59 +02:00
Sollace
5a9d902d97
Added new bat pony parts models by ModernSilver1 2024-07-25 22:31:31 +02:00
Sollace
b3acab046e
Register networking response code when the mod is added to a server (also fix some client/server separation issues) 2024-07-25 16:44:49 +02:00
Sollace
55bf4e209f
Reload when the config is changed from the back 2024-07-25 15:59:26 +02:00
Sollace
eb25692aef
Fix naming convention for the logger 2024-07-25 15:45:14 +02:00
Sollace
36c3136067
Update kirin 2024-07-25 15:21:58 +02:00
Sollace
f4ea6d5ef0
Fix collission with other mods changing eye height/hitboxes 2024-07-23 15:01:17 +02:00
Sollace
8a801e7c41
Fixed reformed changelings' ears 2024-07-22 01:04:16 +02:00
Sollace
cc6cc074e8
Fixed camera height not updating immediately when loading a world 2024-07-22 00:25:24 +02:00
Sollace
90a5ac34fd
Fixed settings screen crash 2024-07-22 00:25:06 +02:00
Sollace
75f26ce061
Update and fix build 2024-07-22 00:20:05 +02:00
Sollace
5fd85964da
Bump dependencies 2024-06-10 22:07:16 +01:00
Sollace
d360ce397f
Fix startup crash 2024-06-10 21:09:58 +01:00
Sollace
86101e0807
Update gitmodules 2024-06-08 14:43:58 +01:00
Sollace
1d0001c702
Bump sockies 2024-06-08 14:42:42 +01:00
Sollace
ca2d21d77e
Add sockies as a plugin 2024-06-07 00:07:33 +01:00
Sollace
fa13d3263d
Bump smyp 2024-06-06 23:42:11 +01:00
Sollace
8db3536250
Update kirin 2024-06-06 23:35:56 +01:00
Sollace
d11fbf63f2
Update mixin 2024-06-06 23:00:49 +01:00
Sollace
7f89ef646e
Update dependencies and remove unneeded access wideners 2024-06-06 23:00:41 +01:00
Sollace
1ff9489a61
Bump hdskins 2024-06-04 23:59:23 +01:00
Sollace
91976a1020
1.20.5 -> 1.21-pre2 2024-06-04 23:43:55 +01:00
Sollace
8afa58f014
Deprecate moved classes 2024-06-04 22:41:56 +01:00
Sollace
20dda1d517
Update SMYP 2024-05-16 15:39:16 +01:00
­Sollace
49ae1f1f01
Update issue templates 2024-05-11 14:03:55 +01:00
­Sollace
a9ede9405f
Update issue templates 2024-05-11 13:56:12 +01:00
­Sollace
6bf9906795
Update issue templates 2024-05-11 13:54:08 +01:00
­Sollace
ed581e6dcc
Update issue templates 2024-05-11 13:52:11 +01:00
Sollace
70e8e23996
More work on magic glows to try and get them looking right 2024-05-07 01:28:57 +01:00
Sollace
2d2dc3b8d6
Bump hdskins version 2024-05-06 22:34:26 +01:00
Sollace
5524f8c7f1
Tools and weapons now keep their orientation when being held by a unicorn 2024-05-06 21:09:35 +01:00
Sollace
ff6b3d182d
Fix stetson 2024-05-06 20:41:11 +01:00
Sollace
ec193657af
Bump hdskins 2024-05-06 19:18:02 +01:00
Sollace
4963796c84
Fix leg position when lying down #259 2024-05-05 19:00:02 +01:00
Sollace
f0ee97bce0
Disable item glints when rendering the auras. Fixes #257 2024-05-05 18:32:57 +01:00
Sollace
1a22b290a6
Fixed hats, gear, stuck arrows, and etc not rendering on npcs 2024-05-05 18:21:04 +01:00
Sollace
0c0d77090f
Hats now move up so they don't clip through skulls/blocks 2024-05-05 18:20:36 +01:00
Sollace
411118d036
Pony skulls now play their animations 2024-05-05 18:02:12 +01:00
Sollace
c6560513bc
Fix misaligned skulls when worn by ponies + implement pony piglin skulls 2024-05-05 17:51:01 +01:00
Sollace
405d9e2bbf
Fix build tasks 2024-05-05 00:43:25 +01:00
Sollace
a1e35bedb6
Bump plugin ref 2024-05-05 00:36:15 +01:00
Sollace
9c103dbddd
Apply alpha for worn heads 2024-05-05 00:34:15 +01:00
Sollace
aac343cd46
Add a callback after rendering armour 2024-05-05 00:11:15 +01:00
Sollace
c4968aed4c
Make sure getArmourStacks is called whenever possible 2024-05-04 23:50:17 +01:00
Sollace
4b6fdd4752
Clean up and simplify a little 2024-05-04 23:23:57 +01:00
Sollace
bf4a0139fb
Add support for the cape and elytra 2024-05-04 23:02:57 +01:00
Sollace
53b8921c50
Update gitmodules 2024-05-04 22:08:04 +01:00
Sollace
0da671b699
Clean up a bit and allow for setting alpha 2024-05-04 22:03:35 +01:00
Sollace
93a895e90e
Add a plugin for show me your skins 2024-05-04 21:38:38 +01:00
Sollace
53c9a85877
Allow for chaining plugins when registering 2024-05-04 21:36:58 +01:00
Sollace
ced4a2d980
Implement a armour renderplugin api 2024-05-04 21:21:16 +01:00
Sollace
85726e8c8d
Fix fillycam 2024-05-04 19:43:24 +01:00
Sollace
eeea8ee184
Fix turtle helmet and clear cached armour lookups when reloading resources 2024-05-04 19:32:05 +01:00
Sollace
3c44b00c1d
Update armour rendering to use the armor material layers defined by the item.
Also fixes #269, #270
2024-05-04 00:03:28 +01:00
Sollace
8d385a3202
Skeletons now lower their bow when not attacking. ;) 2024-04-30 19:11:48 +01:00
Sollace
a9051293b7
Fixed magic rendering on items in third person when it's not supposed to and fixed skeletons having horns when they're not supposed to 2024-04-30 19:11:32 +01:00
Sollace
62d606ada4
Update skin type ids and implement apis for controlling what skin and model the player gets through mine little pony 2024-04-30 19:11:04 +01:00
Sollace
cc463bb293
Fix riding position, and remove pony stacking (it was broken and I can't fix it) 2024-04-30 17:04:59 +01:00
Sollace
807fb3213a
1.20.4 -> 1.20.5 2024-04-30 15:45:36 +01:00
Sollace
36702e1fec
Merge branch '1.20.2' into 1.20.4 2024-04-26 21:04:39 +01:00
Sollace
1fc533babd
New Crowdin updates (#273)
# Conflicts:
#	src/main/resources/assets/minelittlepony/lang/ru_ru.json
2024-04-09 14:20:50 +01:00
­Sollace
4a3b6bb54b
Update Crowdin configuration file 2024-04-09 14:20:46 +01:00
­Sollace
30e899a7e0
Update README.md 2024-04-09 13:32:52 +01:00
­Sollace
1bab1fe79c
Update Crowdin configuration file 2024-04-09 13:32:41 +01:00
Sollace
fce1db2cc7
Update dependencies 2024-04-06 15:19:37 +01:00
Sollace
e8035e97f5
Merge branch '1.20.2' into 1.20.4 2024-03-05 12:26:19 +00:00
Sollace
8aa189f928
Fixed not all wearables being detected 2024-03-05 12:16:28 +00:00
Sollace
50e83bb930
Add mson to the depends block (almost forgot this) 2024-03-05 12:16:28 +00:00
Sollace
58076df09a
Fix various transformations for when a pony is lying down but not sleeping 2024-03-05 12:14:12 +00:00
Sollace
7ad3ab236a
Increase time required before a pony will lie down 2024-03-05 12:14:12 +00:00
横刀天笑(Knife smile)
8687ec443b
update skin form (#262) 2024-02-23 21:45:58 +00:00
Sollace
709879fe61
Update mson 2024-02-09 19:42:41 +00:00
Sollace
9f33f4c06a
Fix typo 2024-01-09 16:44:28 +01:00
Sollace
daa40cc143
Actually use the dynamic depends blocks 2023-12-09 23:33:38 +00:00
Sollace
63ec053bc2
1.20.2 -> 1.20.4 2023-12-09 22:51:59 +00:00
146 changed files with 2108 additions and 1256 deletions

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,38 @@
---
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>

View file

@ -0,0 +1,26 @@
---
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)

View file

@ -12,7 +12,7 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: 17
java-version: 21
- name: Build Gradle
uses: eskatos/gradle-command-action@v1
with:

View file

@ -12,7 +12,7 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: 17
java-version: 21
- name: Build Gradle
uses: eskatos/gradle-command-action@v1
with:

View file

@ -16,7 +16,7 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: 17
java-version: 21
- name: Publish Maven Jar
env:
ACCESS_KEY: ${{ secrets.ACCESS_KEY }}

8
.gitmodules vendored
View file

@ -2,3 +2,11 @@
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

BIN
assets/night_guard_bat.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -1,25 +1,25 @@
buildscript {
dependencies {
classpath 'com.github.dexman545:Outlet:1.3.10'
classpath 'com.github.dexman545:Outlet:1.6.1'
}
}
plugins {
id 'fabric-loom' version '1.5-SNAPSHOT'
id 'fabric-loom' version '1.6-SNAPSHOT'
id 'maven-publish'
id 'com.modrinth.minotaur' version '2.+'
id 'org.ajoberstar.reckon' version '0.13.0'
id 'org.ajoberstar.reckon' version '0.13.1'
}
apply plugin: 'dex.plugins.outlet'
apply plugin: 'io.github.dexman545.outlet'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
languageVersion = JavaLanguageVersion.of(21)
}
withSourcesJar()
}
outlet.allowSnapshotsForProject = false
outlet.mcVersionRange = project.minecraft_version_range
outlet.mcVersionRange = ">=${project.minecraft_version}"
group = project.group
description = project.displayname
@ -123,9 +123,10 @@ modrinth {
gameVersions.add ver
}
dependencies {
required.project 'P7dR8mSH'
optional.project 'FzE9gshV'
optional.project 'h9pJxJR9'
required.project 'P7dR8mSH' // Fabric API
required.project '9aNz8Zqn' // Kirin
optional.project 'FzE9gshV' // HD Skins
optional.project 'h9pJxJR9' // Big Pony
}
}
@ -174,4 +175,4 @@ publishing {
}
}
}
}
}

View file

@ -3,10 +3,10 @@ org.gradle.daemon=false
# Fabric Properties
# check these on https://fabricmc.net/develop
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
minecraft_version=1.21.1
yarn_mappings=1.21.1+build.3
loader_version=0.16.4
fabric_version=0.102.0+1.21.1
# 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.20.2
minecraft_version_range=>=1.21 <1.21.3
modrinth_loader_type=fabric
modrinth_project_id=JBjInUXM
# Dependencies
modmenu_version=8.0.0
kirin_version=1.16.1+1.20.2
hd_skins_version=6.11.2+1.20.2
mson_version=1.9.3+1.20.2
modmenu_version=11.0.0-beta.1
kirin_version=1.20.0+1.21
hd_skins_version=6.14.1+1.21
mson_version=1.10.0+1.21

View file

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

@ -0,0 +1 @@
Subproject commit 1ae97d064e7579d94a93f2784473dc7ce0e1e670

1
plugins/Sockies Submodule

@ -0,0 +1 @@
Subproject commit 31e72eab1b764506c55f00881e05aca513ea7074

View file

@ -1,13 +1,16 @@
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.
@ -85,8 +88,13 @@ 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(HEIRARCHICAL_JSON_ADAPTER, path);
super(new HeirarchicalJsonConfigAdapter(new GsonBuilder()
.registerTypeAdapter(Identifier.class, new ToStringAdapter<>(Identifier::toString, Identifier::of))), path);
instance = this;
}
@ -132,12 +140,12 @@ public class PonyConfig extends Config {
*/
public static Race getEffectiveRace(Race race) {
Race override = instance.raceOverride.get();
Race override = getInstance().raceOverride.get();
if (override != Race.HUMAN) {
return override;
}
if (instance.ponyLevel.get() == PonyLevel.HUMANS) {
if (getInstance().ponyLevel.get() == PonyLevel.HUMANS) {
return Race.HUMAN;
}
@ -145,7 +153,7 @@ public class PonyConfig extends Config {
}
public static Size getEffectiveSize(Size size) {
SizePreset sz = instance.sizeOverride.get();
SizePreset sz = getInstance().sizeOverride.get();
if (sz != SizePreset.UNSET) {
return sz;

View file

@ -1,63 +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.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;
}
}

View file

@ -0,0 +1,46 @@
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;
}
}

View file

@ -0,0 +1,58 @@
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;
}
}
}

View file

@ -7,8 +7,13 @@ 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);

View file

@ -0,0 +1,29 @@
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);
}
}

View file

@ -61,7 +61,7 @@ public class ModelAttributes {
*/
public boolean isLeftHanded;
/**
* True if the model is sitting as in boats.
* True if the model is riding on the back of another pony.
*/
public boolean isRidingInteractive;
/**
@ -169,7 +169,7 @@ public class ModelAttributes {
}
isLeftHanded = entity.getMainArm() == Arm.LEFT;
isHorsey = PonyConfig.getInstance().horsieMode.get();
featureSkins = SkinsProxy.instance.getAvailableSkins(entity);
featureSkins = SkinsProxy.getInstance().getAvailableSkins(entity);
mainArm = entity.getMainArm();
activeHand = entity.getActiveHand();
itemUseTime = entity.getItemUseTimeLeft();

View file

@ -1,7 +1,7 @@
package com.minelittlepony.api.model;
public interface PreviewModel {
boolean forceSeapony();
import net.minecraft.util.Identifier;
boolean forceNirik();
public interface PreviewModel {
Identifier getForm();
}

View file

@ -14,7 +14,7 @@ public interface SubModel {
/**
* Renders this model component.
*/
void renderPart(MatrixStack stack, VertexConsumer vertices, int overlay, int light, float red, float green, float blue, float alpha, ModelAttributes attributes);
void renderPart(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color, ModelAttributes attributes);
/**
* Sets whether this part should be rendered.

View file

@ -27,14 +27,14 @@ public abstract class AbstractGearModel extends Model implements Gear {
}
@Override
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);
public void render(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color, UUID interpolatorId) {
render(stack, vertices, overlay, light, color);
}
@Override
public void render(MatrixStack stack, VertexConsumer renderContext, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
public void render(MatrixStack stack, VertexConsumer renderContext, int overlay, int light, int color) {
parts.forEach(part -> {
part.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha);
part.render(stack, renderContext, overlay, light, color);
});
}

View file

@ -92,7 +92,7 @@ public interface Gear {
/**
* Renders this model component.
*/
void render(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha, UUID interpolatorId);
void render(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color, UUID interpolatorId);
/**
* A render context for instance of IGear.

View file

@ -1,32 +1,35 @@
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 = new Identifier("minelittlepony", "textures/entity/player/wide/steve_pony.png");
public static final Identifier STEVE = Pony.id("textures/entity/player/wide/steve_pony.png");
public static final Identifier SEAPONY_SKIN_TYPE_ID = new Identifier("minelp", "seapony");
public static final Identifier NIRIK_SKIN_TYPE_ID = new Identifier("minelp", "nirik");
public static final Identifier SEAPONY_SKIN_TYPE_ID = Pony.id("seapony");
public static final Identifier NIRIK_SKIN_TYPE_ID = Pony.id("nirik");
private static final Map<SkinTextures, SkinTextures> SKINS = new HashMap<>();
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
));
public static SkinTextures getTextures(SkinTextures 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
);
});
return SKINS.apply(original);
}
public static String getModelType(UUID id) {

View file

@ -26,6 +26,13 @@ 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.
*/

View file

@ -0,0 +1,52 @@
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);
}
}

View file

@ -7,6 +7,8 @@ import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.server.ServerPonyManager;
import java.util.Optional;
import java.util.UUID;
@ -71,6 +73,6 @@ public interface PonyManager {
interface ForcedPony {}
final class Instance {
public static PonyManager instance;
public static PonyManager instance = new ServerPonyManager();
}
}

View file

@ -7,7 +7,6 @@ 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;
@ -86,39 +85,24 @@ 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.forceSeapony();
return preview.getForm() == PonyForm.SEAPONY;
}
return Pony.getManager().getPony(entity).filter(pony -> {
return (pony.race() == Race.SEAPONY
|| (entity instanceof AbstractClientPlayerEntity player && SkinsProxy.instance.getSkin(DefaultPonySkinHelper.SEAPONY_SKIN_TYPE_ID, player).isPresent())
|| (entity instanceof PlayerEntity player && SkinsProxy.getInstance().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.forceNirik();
return preview.getForm() == PonyForm.NIRIK;
}
return Pony.getManager().getPony(entity).filter(pony -> {
return (pony.race() == Race.KIRIN
&& (entity instanceof AbstractClientPlayerEntity player && SkinsProxy.instance.getSkin(DefaultPonySkinHelper.NIRIK_SKIN_TYPE_ID, player).isPresent())
&& (entity instanceof PlayerEntity player && SkinsProxy.getInstance().getSkin(DefaultPonySkinHelper.NIRIK_SKIN_TYPE_ID, player).isPresent())
);
}).isPresent();
}

View file

@ -1,28 +1,60 @@
package com.minelittlepony.api.pony;
import com.mojang.authlib.GameProfile;
import java.util.*;
import java.util.concurrent.TimeUnit;
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.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;
/**
* Proxy handler for getting player skin data from HDSkins
*/
public class SkinsProxy {
public static SkinsProxy instance = new SkinsProxy();
public static SkinsProxy INSTANCE = new SkinsProxy();
private static final SkinsProxy DEFAULT = INSTANCE;
public Identifier getSkinTexture(GameProfile profile) {
PlayerSkinProvider skins = MinecraftClient.getInstance().getSkinProvider();
return skins.getSkinTextures(profile).texture();
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;
}
public Optional<Identifier> getSkin(Identifier skinTypeId, AbstractClientPlayerEntity player) {
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;
}
public Optional<Identifier> getSkin(Identifier skinTypeId, PlayerEntity player) {
return Optional.empty();
}

View file

@ -27,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 new Flags<>(def, values, buffer.readInt());
return of(def, buffer.readInt(), values);
}
public void write(PacketByteBuf buffer) {

View file

@ -0,0 +1,40 @@
package com.minelittlepony.api.pony.meta;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.common.util.Color;
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 Color.argbToHex(color[3], color[0], color[1], color[2]);
};
} catch (IllegalArgumentException e) {
throw new IOException("Could not create mat from image", e);
}
}
}

View file

@ -14,6 +14,8 @@ 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);

View file

@ -3,20 +3,22 @@ package com.minelittlepony.api.pony.meta;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.ColorHelper;
import com.minelittlepony.api.pony.Pony;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public enum Wearable implements TValue<Wearable> {
NONE (0x00, null),
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"));
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"));
private int triggerValue;
@ -29,7 +31,7 @@ public enum Wearable implements TValue<Wearable> {
Wearable(int pixel, Identifier texture) {
triggerValue = pixel;
id = new Identifier("minelittlepony", name().toLowerCase(Locale.ROOT));
id = Pony.id(name().toLowerCase(Locale.ROOT));
this.texture = texture;
}

View file

@ -0,0 +1,16 @@
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();
}
}

View file

@ -87,7 +87,7 @@ public class HorseCam {
public static float rescaleCameraPitch(double toHeight, float originalPitch) {
MinecraftClient client = MinecraftClient.getInstance();
PlayerEntity player = client.player;
client.gameRenderer.updateTargetedEntity(client.getTickDelta());
client.gameRenderer.updateCrosshairTarget(client.getRenderTickCounter().getTickDelta(false));
HitResult hit = client.crosshairTarget;
if (client.targetedEntity != null) {

View file

@ -1,7 +1,7 @@
package com.minelittlepony.client;
import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.events.Channel;
import com.minelittlepony.api.events.ClientChannel;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.armour.ArmourTextureResolver;
import com.minelittlepony.client.render.MobRenderers;
@ -9,7 +9,6 @@ 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;
@ -40,7 +39,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,6 +47,7 @@ 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 boolean initialized;
private boolean hasHdSkins;
private boolean hasModMenu;
@ -63,6 +63,10 @@ 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");
@ -76,27 +80,35 @@ 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);
config.load();
new ClientSkinsProxy();
Channel.bootstrap();
config.load();
config.onChangedExternally(c -> initialized = false);
ClientChannel.bootstrap();
ModelType.bootstrap();
FabricLoader.getInstance().getEntrypoints("minelittlepony", ClientModInitializer.class).forEach(ClientModInitializer::onInitializeClient);
}
private void onTick(MinecraftClient client) {
if (!initialized) {
initialized = true;
renderDispatcher.initialise(client.getEntityRenderDispatcher(), false);
if (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;
@ -124,7 +136,7 @@ public class MineLittlePony implements ClientModInitializer {
button.getStyle()
.setIcon(new TextureSprite()
.setPosition(2, 2)
.setTexture(new Identifier("minelittlepony", "textures/gui/pony.png"))
.setTexture(id("textures/gui/pony.png"))
.setTextureSize(16, 16)
.setSize(16, 16))
.setTooltip("minelp.options.title", 0, 10);

View file

@ -1,50 +1,28 @@
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();
float delta = MinecraftClient.getInstance().getRenderTickCounter().getTickDelta(false);
return new Vec3d(
MathHelper.lerp(delta, entity.prevX, entity.getX()),
MathHelper.lerp(delta, entity.prevY, entity.getY()) + vehicleOffset,
MathHelper.lerp(delta, entity.prevY, entity.getY()),
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 scale = pony.size().scaleFactor();
final float width = entity.getWidth() * scale;
final float height = entity.getHeight() * scale;
return new Box(-width, height, -width, width, 0, width).offset(getAbsoluteRidingOffset(entity));
return new Box(-width, 0, -width, width, height, width).offset(getBaseRidingOffset(entity));
}
}

View file

@ -15,8 +15,8 @@ import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable;
class PonyDataLoader {
static final Supplier<Optional<PonyData>> NULL = loaded(PonyData.NULL);
public class PonyDataLoader {
public 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()
@ -46,7 +46,7 @@ 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(() -> {
@ -54,7 +54,7 @@ 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);
});
});

View file

@ -1,8 +1,10 @@
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;
@ -13,27 +15,26 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.AbstractClientPlayerEntity;
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.Optional;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceReloadListener {
private static final Identifier ID = new Identifier("minelittlepony", "background_ponies");
private static final Identifier ID = MineLittlePony.id("background_ponies");
private final PonyConfig config;
private final LoadingCache<Identifier, Pony> defaultedPoniesCache = CacheBuilder.newBuilder()
private final LoadingCache<Key, Pony> poniesCache = CacheBuilder.newBuilder()
.expireAfterAccess(30, TimeUnit.SECONDS)
.build(CacheLoader.from(resource -> new Pony(resource, PonyDataLoader.parse(resource, true))));
.build(CacheLoader.from(key -> new Pony(key.texture(), PonyDataLoader.parse(key.texture(), key.defaulted()))));
private final WeakHashMap<UUID, Pony> playerPonies = new WeakHashMap<>();
private final LoadingCache<Identifier, Pony> poniesCache = CacheBuilder.newBuilder()
.expireAfterAccess(30, TimeUnit.SECONDS)
.build(CacheLoader.from(resource -> new Pony(resource, PonyDataLoader.parse(resource, false))));
record Key(Identifier texture, boolean defaulted) {}
public PonyManagerImpl(PonyConfig config) {
this.config = config;
@ -42,7 +43,7 @@ public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceRe
private Pony loadPony(Identifier resource, boolean defaulted) {
try {
return (defaulted ? defaultedPoniesCache : poniesCache).get(resource);
return poniesCache.get(new Key(resource, defaulted));
} catch (ExecutionException e) {
return new Pony(resource, PonyDataLoader.NULL);
}
@ -50,7 +51,26 @@ public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceRe
@Override
public Pony getPony(PlayerEntity player) {
return getPony(getSkin(player), player instanceof ForcedPony ? null : player.getGameProfile() == null ? player.getUuid() : player.getGameProfile().getId());
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;
}
@Override
@ -58,7 +78,11 @@ 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));
}
@ -101,19 +125,17 @@ public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceRe
public void removePony(Identifier resource) {
poniesCache.invalidate(resource);
defaultedPoniesCache.invalidate(resource);
}
public void clearCache() {
MineLittlePony.logger.info("Flushed {} cached ponies.", poniesCache.size());
MineLittlePony.LOGGER.info("Turned {} cached ponies into cupcakes.", poniesCache.size());
poniesCache.invalidateAll();
defaultedPoniesCache.invalidateAll();
}
@Override
public void reload(ResourceManager var1) {
public void reload(ResourceManager manager) {
clearCache();
PonySkullRenderer.reload();
PonySkullRenderer.INSTANCE.reload();
}
@Override

View file

@ -136,10 +136,11 @@ public class PonySettingsScreen extends GameGui {
if (hiddenOptions) {
for (Setting<?> i : config.getCategory("customisation").entries()) {
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());
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());
}
}
}

View file

@ -11,9 +11,9 @@ import com.minelittlepony.util.MathUtil;
import java.util.*;
public class VariatedTextureSupplier implements SimpleSynchronousResourceReloadListener {
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 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 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) {

View file

@ -1,6 +1,7 @@
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.*;
@ -20,12 +21,13 @@ class DummyPony extends DummyPlayer implements PreviewModel, PonyManager.ForcedP
}
@Override
public boolean forceSeapony() {
return getTextures().getPosture().getActiveSkinType() == MineLPHDSkins.seaponySkinType;
}
@Override
public boolean forceNirik() {
return getTextures().getPosture().getActiveSkinType() == MineLPHDSkins.nirikSkinType;
public Identifier getForm() {
if (getTextures().getPosture().getActiveSkinType() == MineLPHDSkins.seaponySkinType) {
return PonyForm.SEAPONY;
}
if (getTextures().getPosture().getActiveSkinType() == MineLPHDSkins.nirikSkinType) {
return PonyForm.NIRIK;
}
return PonyForm.DEFAULT;
}
}

View file

@ -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 String[] PANORAMAS = new String[] {
"minelittlepony:textures/cubemap/sugarcubecorner",
"minelittlepony:textures/cubemap/quillsandsofas",
"minelittlepony:textures/cubemap/sweetappleacres"
private static final Identifier[] PANORAMAS = new Identifier[] {
MineLittlePony.id("textures/cubemap/sugarcubecorner"),
MineLittlePony.id("textures/cubemap/quillsandsofas"),
MineLittlePony.id("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(new Identifier("minelittlepony", "textures/gui/pony.png"))
.setTexture(MineLittlePony.id("textures/gui/pony.png"))
.setTextureSize(16, 16)
.setSize(16, 16))
.setTooltip("minelp.options.title", 0, 10);
@ -64,8 +64,6 @@ class GuiSkinsMineLP extends GuiSkins {
@Override
protected Identifier getBackground() {
int i = (int)Math.floor(Math.random() * PANORAMAS.length);
return new Identifier(PANORAMAS[i]);
return PANORAMAS[(int)Math.floor(Math.random() * PANORAMAS.length)];
}
}

View file

@ -6,13 +6,13 @@ 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.common.event.ClientReadyCallback;
import com.minelittlepony.hdskins.HDSkinsServer;
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,6 +24,7 @@ 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;
@ -32,34 +33,33 @@ import com.minelittlepony.client.*;
/**
* All the interactions with HD Skins.
*/
public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
public class MineLPHDSkins extends ClientSkinsProxy implements ClientModInitializer {
static SkinType seaponySkinType;
static SkinType nirikSkinType;
static final Map<SkinType, Wearable> wearableTypes = new HashMap<>();
static final Map<SkinType, Wearable> WEARABLE_TYPES = 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) {
wearableTypes.put(SkinType.register(wearable.getId(), Items.BUNDLE.getDefaultStack()), wearable);
WEARABLE_TYPES.put(SkinType.register(wearable.getId(), Items.BUNDLE.getDefaultStack()), wearable);
}
});
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);
// Clear ponies when skins are cleared
SkinCacheClearCallback.EVENT.register(() -> {
MineLittlePony.getInstance().getManager().clearCache();
});
// Ponify the skins GUI.
GuiSkins.setSkinsGui(GuiSkinsMineLP::new);
HDSkins.getInstance().getSkinPrioritySorter().addSelector((skinType, playerSkins) -> {
if (skinType == SkinType.SKIN && PonyConfig.getInstance().mixedHumanSkins.get()) {
Optional<Pony> hdPony = getPony(playerSkins.hd());
@ -75,7 +75,7 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
});
}
static Optional<Pony> getPony(PlayerSkins.Layer layer) {
static Optional<Pony> getPony(PlayerSkinLayers.Layer layer) {
return layer
.getSkin(SkinType.SKIN)
.map(Pony.getManager()::getPony);
@ -84,15 +84,20 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
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, HDSkins.getInstance().getSkinServerList())
parent instanceof GuiSkins ? parent : GuiSkins.create(screen, HDSkinsServer.getInstance().getServers())
))
.getStyle()
.setText("minelp.options.skins.hdskins.open");
}
@Override
public Optional<Identifier> getSkin(Identifier skinTypeId, AbstractClientPlayerEntity player) {
return SkinType.REGISTRY.getOrEmpty(skinTypeId).flatMap(type -> getSkin(type, player));
public Optional<Identifier> getSkin(Identifier skinTypeId, PlayerEntity player) {
if (player instanceof AbstractClientPlayerEntity clientPlayer) {
return SkinType.REGISTRY.getOrEmpty(skinTypeId).flatMap(type -> getSkin(type, clientPlayer));
}
return Optional.empty();
}
public Set<Identifier> getAvailableSkins(Entity entity) {
@ -103,8 +108,9 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
if (entity instanceof AbstractClientPlayerEntity player) {
return PlayerSkins.of(player)
.map(PlayerSkins::combined)
.map(PlayerSkins.Layer::getProvidedSkinTypes)
.map(PlayerSkins::layers)
.map(PlayerSkinLayers::combined)
.map(PlayerSkinLayers.Layer::getProvidedSkinTypes)
.orElseGet(Set::of);
}
@ -132,13 +138,17 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
}
}
return Optional.of(player).flatMap(PlayerSkins::of).map(PlayerSkins::combined).flatMap(skins -> skins.getSkin(type));
return Optional.of(player)
.flatMap(PlayerSkins::of)
.map(PlayerSkins::layers)
.map(PlayerSkinLayers::combined)
.flatMap(skins -> skins.getSkin(type));
}
@Override
public Identifier getSkinTexture(GameProfile profile) {
return HDSkins.getInstance().getProfileRepository()
.getNow(profile)
.load(profile).getNow(ProvidedSkins.EMPTY)
.getSkin(SkinType.SKIN)
.orElseGet(() -> super.getSkinTexture(profile));
}

View file

@ -35,7 +35,7 @@ class PonifiedDualCarouselWidget extends DualCarouselWidget {
return super.getDefaultSkin(SkinType.SKIN, modelVariant);
}
Wearable wearable = MineLPHDSkins.wearableTypes.getOrDefault(type, Wearable.NONE);
Wearable wearable = MineLPHDSkins.WEARABLE_TYPES.getOrDefault(type, Wearable.NONE);
if (wearable != Wearable.NONE) {
return NativeImageFilters.GREYSCALE.load(wearable.getDefaultTexture(), wearable.getDefaultTexture(), getExclusion());

View file

@ -12,11 +12,11 @@ import net.minecraft.client.render.Camera;
@Mixin(Camera.class)
abstract class MixinCamera {
@Inject(method = "clipToSpace(D)D",
@Inject(method = "clipToSpace(F)F",
at = @At("RETURN"),
cancellable = true)
private void redirectCameraDistance(double initial, CallbackInfoReturnable<Double> info) {
double value = info.getReturnValueD();
private void redirectCameraDistance(float initial, CallbackInfoReturnable<Float> info) {
float value = info.getReturnValueF();
Pony pony = Pony.getManager().getPony(MinecraftClient.getInstance().player);

View file

@ -1,59 +0,0 @@
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;
}
}

View file

@ -1,7 +1,6 @@
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;
@ -14,12 +13,12 @@ import com.minelittlepony.api.model.RenderPass;
@Mixin(GameRenderer.class)
abstract class MixinGameRenderer {
@Inject(method = "renderWorld", at = @At("HEAD"))
private void beforeRenderWorld(float tickDelta, long limitTime, MatrixStack matrices, CallbackInfo info) {
private void beforeRenderWorld(RenderTickCounter counter, CallbackInfo info) {
RenderPass.swap(RenderPass.WORLD);
}
@Inject(method = "renderWorld", at = @At("RETURN"))
private void afterRenderWorld(float tickDelta, long limitTime, MatrixStack matrices, CallbackInfo info) {
private void afterRenderWorld(RenderTickCounter counter, CallbackInfo info) {
RenderPass.swap(RenderPass.GUI);
}
}
@ -31,7 +30,14 @@ abstract class MixinWorldRenderer {
target = "net.minecraft.client.render.VertexConsumerProvider$Immediate.drawCurrentLayer()V",
ordinal = 0
))
private void onRender(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f positionMatrix, CallbackInfo info) {
private void onRender(
RenderTickCounter counter,
boolean renderBlockOutline,
Camera camera,
GameRenderer gameRenderer,
LightmapTextureManager lightmapTextureManager,
Matrix4f matrix4f,
Matrix4f matrix4f2, CallbackInfo info) {
RenderPass.swap(RenderPass.HUD);
}
}

View file

@ -0,0 +1,34 @@
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);
}
}

View file

@ -8,6 +8,7 @@ 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.math.Direction;
import org.spongepowered.asm.mixin.Mixin;
@ -17,7 +18,6 @@ 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;
@ -39,18 +39,18 @@ abstract class MixinSkullBlockEntityRenderer implements BlockEntityRenderer<Skul
SkullBlockEntityModel model, RenderLayer layer,
CallbackInfo info) {
if (!info.isCancelled() && PonySkullRenderer.renderSkull(direction, angle, poweredTicks, stack, renderContext, layer, lightUv)) {
if (!info.isCancelled() && PonySkullRenderer.INSTANCE.renderSkull(direction, angle, poweredTicks, stack, renderContext, layer, lightUv)) {
info.cancel();
}
}
@Inject(method = "getRenderLayer("
+ "Lnet/minecraft/block/SkullBlock$SkullType;"
+ "Lcom/mojang/authlib/GameProfile;"
+ "Lnet/minecraft/component/type/ProfileComponent;"
+ ")Lnet/minecraft/client/render/RenderLayer;", at = @At("HEAD"), cancellable = true)
private static void onGetRenderLayer(SkullBlock.SkullType skullType, @Nullable GameProfile profile, CallbackInfoReturnable<RenderLayer> info) {
private static void onGetRenderLayer(SkullBlock.SkullType skullType, @Nullable ProfileComponent profile, CallbackInfoReturnable<RenderLayer> info) {
if (!info.isCancelled()) {
RenderLayer result = PonySkullRenderer.getSkullRenderLayer(skullType, profile);
RenderLayer result = PonySkullRenderer.INSTANCE.getSkullRenderLayer(skullType, profile);
if (result != null) {
info.setReturnValue(result);
}

View file

@ -1,12 +1,12 @@
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.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Arrays;
import java.util.Set;
import it.unimi.dsi.fastutil.objects.ObjectArraySet;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumers;
@ -25,15 +25,12 @@ abstract class MixinVertextConsumers {
}
}
@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));
@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);
}
return set.toArray(VertexConsumer[]::new);
}
}

View file

@ -4,7 +4,7 @@ import com.minelittlepony.api.model.*;
import com.minelittlepony.api.events.PonyModelPrepareCallback;
import com.minelittlepony.api.pony.meta.SizePreset;
import com.minelittlepony.client.transform.PonyTransformation;
import com.minelittlepony.client.util.render.RenderList;
import com.minelittlepony.mson.util.RenderList;
import com.minelittlepony.util.MathUtil;
import com.minelittlepony.util.MathUtil.Angles;
@ -31,7 +31,6 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
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);
@ -72,27 +71,27 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
}
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);
return (stack, vertices, overlay, light, color) -> {
part.get().renderPart(stack, vertices, overlay, light, color, 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);
return (stack, vertices, overlay, light, color) -> {
part.renderPart(stack, vertices, overlay, light, color, attributes);
};
}
@Override
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);
public void render(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color) {
mainRenderList.accept(stack, vertices, overlay, light, color);
}
protected RenderList withStage(BodyPart part, RenderList action) {
return (stack, vertices, overlayUv, lightUv, red, green, blue, alpha) -> {
return (stack, vertices, overlay, light, color) -> {
stack.push();
transform(part, stack);
action.accept(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
action.accept(stack, vertices, overlay, light, color);
stack.pop();
};
}
@ -195,8 +194,6 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
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);
@ -204,14 +201,9 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
}
protected void ponySit() {
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);
}
adjustBodyComponents(BODY_RIDING_PITCH, BODY_RIDING);
neck.setPivot(NECK_X, 0, 0);
head.setPivot(0, 0, 0);
leftLeg.pivotZ = 14;
leftLeg.pivotY = 17;
@ -231,26 +223,6 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
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;
}
}
/**
@ -600,10 +572,6 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
}
}
if (getAttributes().isRidingInteractive) {
matrices.translate(left / 10, -0.2F, -0.5F);
}
matrices.translate(-left * 0.1F, 0.45F, 0);
if (getAttributes().heldStack.getUseAction() == UseAction.BLOCK && getAttributes().itemUseTime == 0) {
@ -623,11 +591,8 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
stack.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180));
}
boolean crouching = attributes.isCrouching;
if (attributes.isLyingDown && !attributes.isSleeping) {
stack.translate(0, 1.35F, 0);
attributes.isCrouching = sneaking;
}
if (attributes.isHorsey) {
@ -641,7 +606,5 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
}
PonyTransformation.forSize(getSize()).transform(this, part, stack);
attributes.isCrouching = crouching;
}
}

View file

@ -1,18 +1,21 @@
package com.minelittlepony.client.model;
import net.minecraft.client.model.Model;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.entity.model.ArmorStandEntityModel;
import net.minecraft.client.render.entity.model.SinglePartEntityModel;
import net.minecraft.entity.Entity;
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.*;
@ -38,6 +41,15 @@ public final class ModelType {
public static final ModelKey<ZomponyModel<?>> ZOMBIE = register("zombie", ZomponyModel::new);
public static final ModelKey<PiglinPonyModel> PIGLIN = register("piglin", PiglinPonyModel::new);
public static final ModelKey<SkeleponyModel<?>> SKELETON = register("skeleton", SkeleponyModel::new);
public static final ModelKey<SinglePartEntityModel<?>> BOGGED_MUSHROOMS = register("bogged_mushrooms", tree -> new SinglePartEntityModel<>(RenderLayer::getEntityTranslucent) {
@Override
public ModelPart getPart() {
return tree;
}
@Override
public void setAngles(Entity entity, float var2, float var3, float var4, float var5, float var6) {}
});
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);
@ -56,7 +68,7 @@ public final class ModelType {
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(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).addPart(t));
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));
@ -93,7 +105,7 @@ public final class ModelType {
@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(new Identifier("minelittlepony", "gear/" + name), constructor), constructor);
return new GearModelKey<T>(Mson.getInstance().registerModel(MineLittlePony.id("gear/" + name), constructor), constructor);
});
}
@ -103,7 +115,7 @@ public final class ModelType {
}
static <T extends Model> ModelKey<T> register(String name, MsonModel.Factory<T> constructor) {
return new ModelKeyImpl<T>(new Identifier("minelittlepony", name), constructor);
return new ModelKeyImpl<T>(MineLittlePony.id(name), constructor);
}
@SuppressWarnings("unchecked")

View file

@ -3,12 +3,12 @@ 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.*;
@ -21,8 +21,8 @@ public record PlayerModelKey<T extends LivingEntity, M extends Model & PonyModel
) {
PlayerModelKey(String name, BiFunction<ModelPart, Boolean, M> modelFactory, MsonModel.Factory<PonyArmourModel<T>> armorFactory) {
this(
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)),
new ModelKeyImpl<>(MineLittlePony.id("races/steve/" + name), tree -> modelFactory.apply(tree, false)),
new ModelKeyImpl<>(MineLittlePony.id("races/alex/" + name), tree -> modelFactory.apply(tree, true)),
armorFactory
);
}

View file

@ -0,0 +1,129 @@
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.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.entity.LivingEntity;
import net.minecraft.item.*;
import net.minecraft.item.trim.ArmorTrim;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.util.Colors;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
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(LivingEntity entity, MatrixStack matrices, VertexConsumerProvider provider, EquipmentSlot armorSlot, ArmourLayer layer, ArmourType type) {
}
default ItemStack[] getArmorStacks(LivingEntity entity, EquipmentSlot armorSlot, ArmourLayer layer, ArmourType type) {
return new ItemStack[] { entity.getEquippedStack(armorSlot) };
}
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, ArmourLayer layer) {
return 1F;
}
default float getTrimAlpha(EquipmentSlot slot, RegistryEntry<ArmorMaterial> material, ArmorTrim trim, ArmourLayer layer) {
return 1F;
}
default float getElytraAlpha(ItemStack stack, Model model, LivingEntity entity) {
return stack.isOf(Items.ELYTRA) ? 1F : 0F;
}
@Nullable
default VertexConsumer getTrimConsumer(EquipmentSlot slot, VertexConsumerProvider provider, RegistryEntry<ArmorMaterial> material, ArmorTrim trim, ArmourLayer layer) {
@Nullable VertexConsumer buffer = getOptionalBuffer(provider, getTrimLayer(slot, material, trim, layer));
if (buffer == null) {
return null;
}
SpriteAtlasTexture armorTrimsAtlas = MinecraftClient.getInstance().getBakedModelManager().getAtlas(TexturedRenderLayers.ARMOR_TRIMS_ATLAS_TEXTURE);
Sprite sprite = armorTrimsAtlas.getSprite(layer == ArmourLayer.INNER ? trim.getLeggingsModelId(material) : trim.getGenericModelId(material));
return sprite.getTextureSpecificVertexConsumer(buffer);
}
@Nullable
default RenderLayer getTrimLayer(EquipmentSlot slot, RegistryEntry<ArmorMaterial> material, ArmorTrim trim, ArmourLayer layer) {
return TexturedRenderLayers.getArmorTrims(trim.getPattern().value().decal());
}
@Nullable
default VertexConsumer getArmourConsumer(EquipmentSlot slot, VertexConsumerProvider provider, Identifier texture, ArmourLayer layer) {
return getOptionalBuffer(provider, getArmourLayer(slot, texture, layer));
}
@Nullable
default RenderLayer getArmourLayer(EquipmentSlot slot, Identifier texture, ArmourLayer layer) {
return RenderLayer.getArmorCutoutNoCull(texture);
}
@Nullable
default VertexConsumer getGlintConsumer(EquipmentSlot slot, VertexConsumerProvider provider, ArmourLayer layer) {
return getOptionalBuffer(provider, getGlintLayer(slot, layer));
}
@Nullable
default RenderLayer getGlintLayer(EquipmentSlot slot, ArmourLayer layer) {
return RenderLayer.getArmorEntityGlint();
}
@Nullable
default VertexConsumer getCapeConsumer(LivingEntity entity, VertexConsumerProvider provider, Identifier texture) {
if (entity.getEquippedStack(EquipmentSlot.CHEST).isOf(Items.ELYTRA)) {
return null;
}
return getOptionalBuffer(provider, getCapeLayer(entity, texture));
}
@Nullable
default RenderLayer getCapeLayer(LivingEntity entity, Identifier texture) {
return RenderLayer.getEntitySolid(texture);
}
@Nullable
default VertexConsumer getElytraConsumer(ItemStack stack, Model model, LivingEntity entity, VertexConsumerProvider provider, Identifier texture) {
return ItemRenderer.getDirectItemGlintConsumer(provider, model.getLayer(texture), false, 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
}
}

View file

@ -0,0 +1,39 @@
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> named() {
return Stream.of(legacy(texture().withPath(p -> p.replace("1", "inner").replace("2", "outer"))), this);
}
public Stream<ArmourTexture> ponify() {
if (!PonyConfig.getInstance().disablePonifiedArmour.get()) {
return Stream.of(this, modern(ResourceUtil.ponify(texture())));
}
return Stream.of(this);
}
}

View file

@ -0,0 +1,12 @@
package com.minelittlepony.client.model.armour;
import net.minecraft.item.ArmorMaterial;
import net.minecraft.item.ItemStack;
import java.util.List;
public interface ArmourTextureLookup {
ArmourTexture getTexture(ItemStack stack, ArmourLayer layer, ArmorMaterial.Layer armorLayer);
List<ArmorMaterial.Layer> getArmorLayers(ItemStack stack, int dyeColor);
}

View file

@ -1,24 +1,24 @@
package com.minelittlepony.client.model.armour;
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.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.CustomModelDataComponent;
import net.minecraft.item.*;
import net.minecraft.registry.Registries;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Colors;
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 net.minecraft.util.profiler.Profiler;
import org.jetbrains.annotations.Nullable;
import com.google.common.cache.*;
import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
import com.minelittlepony.client.MineLittlePony;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* The default texture resolver used by Mine Little Pony.
@ -35,100 +35,89 @@ import java.util.concurrent.TimeUnit;
* - the "minecraft" namespace is always replaced with "minelittlepony"
* <p>
*/
public class ArmourTextureResolver {
public class ArmourTextureResolver implements ArmourTextureLookup, IdentifiableResourceReloadListener {
public static final Identifier ID = MineLittlePony.id("armor_textures");
public static final ArmourTextureResolver INSTANCE = new ArmourTextureResolver();
private final Cache<String, Identifier> cache = CacheBuilder.newBuilder()
private static final Interner<ArmorMaterial.Layer> LAYER_INTERNER = Interners.newWeakInterner();
private final LoadingCache<ArmourParameters, ArmourTexture> layerCache = CacheBuilder.newBuilder()
.expireAfterAccess(30, TimeUnit.SECONDS)
.<String, Identifier>build();
.build(CacheLoader.from(parameters -> {
return Stream.of(ArmourTexture.legacy(parameters.material().getTexture(parameters.layer() == ArmourLayer.OUTER))).flatMap(i -> {
if (parameters.layer() == ArmourLayer.OUTER) {
return Stream.of(i, ArmourTexture.legacy(parameters.material().getTexture(false)));
}
return Stream.of(i);
}).flatMap(i -> {
if (parameters.customModelId() != 0) {
return Stream.of(ArmourTexture.legacy(i.texture().withPath(p -> p.replace(".png", parameters.customModelId() + ".png"))), i);
}
return Stream.of(i);
}).flatMap(this::performLookup).findFirst().orElse(ArmourTexture.UNKNOWN);
}));
private final LoadingCache<Identifier, List<ArmorMaterial.Layer>> nonDyedLayers = CacheBuilder.newBuilder()
.expireAfterAccess(30, TimeUnit.SECONDS)
.build(CacheLoader.from(material -> List.of(LAYER_INTERNER.intern(new ArmorMaterial.Layer(material, "", false)))));
private final LoadingCache<Identifier, List<ArmorMaterial.Layer>> dyedLayers = CacheBuilder.newBuilder()
.expireAfterAccess(30, TimeUnit.SECONDS)
.build(CacheLoader.from(material -> List.of(
LAYER_INTERNER.intern(new ArmorMaterial.Layer(material, "", false)),
LAYER_INTERNER.intern(new ArmorMaterial.Layer(material, "overlay", true))
)));
private Stream<ArmourTexture> performLookup(ArmourTexture id) {
List<ArmourTexture> options = Stream.of(id)
.flatMap(ArmourTexture::named)
.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();
}
public void invalidate() {
cache.invalidateAll();
layerCache.invalidateAll();
nonDyedLayers.invalidateAll();
dyedLayers.invalidateAll();
}
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);
try {
return cache.get(String.format("%s#%s#%s#%s", material, layer, type, custom), () -> {
String typed = Strings.nullToEmpty(type);
String extra = typed.isEmpty() ? "" : "_" + typed;
Identifier texture;
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;
}
@Override
public CompletableFuture<Void> reload(Synchronizer synchronizer, ResourceManager manager, Profiler prepareProfiler, Profiler applyProfiler, Executor prepareExecutor, Executor applyExecutor) {
return CompletableFuture.runAsync(this::invalidate, prepareExecutor).thenCompose(synchronizer::whenPrepared);
}
private String getCustom(ItemStack stack) {
if (stack.hasNbt() && stack.getNbt().contains("CustomModelData", NbtElement.NUMBER_TYPE)) {
return "custom_" + stack.getNbt().getInt("CustomModelData");
}
return "none";
@Override
public Identifier getFabricId() {
return ID;
}
@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);
@Override
public ArmourTexture getTexture(ItemStack stack, ArmourLayer layer, ArmorMaterial.Layer armorLayer) {
return layerCache.getUnchecked(new ArmourParameters(layer, armorLayer, getCustom(stack)));
}
@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.
@Override
public List<ArmorMaterial.Layer> getArmorLayers(ItemStack stack, int dyeColor) {
if (stack.getItem() instanceof ArmorItem armor) {
return armor.getMaterial().value().layers();
}
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;
return (dyeColor == Colors.WHITE ? nonDyedLayers : dyedLayers).getUnchecked(Registries.ITEM.getId(stack.getItem()));
}
private final boolean isValid(Identifier texture) {
return MinecraftClient.getInstance().getResourceManager().getResource(texture).isPresent();
private int getCustom(ItemStack stack) {
return stack.getOrDefault(DataComponentTypes.CUSTOM_MODEL_DATA, CustomModelDataComponent.DEFAULT).value();
}
public ArmourVariant getVariant(ArmourLayer layer, Identifier resolvedTexture) {
if (resolvedTexture.getPath().endsWith("_pony.png")) {
return ArmourVariant.NORMAL;
}
return ArmourVariant.LEGACY;
private record ArmourParameters(ArmourLayer layer, ArmorMaterial.Layer material, int customModelId) {
}
}

View file

@ -48,10 +48,10 @@ public class EnderStallionModel extends SkeleponyModel<EndermanEntity> {
}
@Override
public void render(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
public void render(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color) {
stack.push();
stack.translate(0, -1.15F, 0);
super.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
super.render(stack, vertices, overlay, light, color);
stack.pop();
}

View file

@ -24,8 +24,8 @@ public class GuardianPonyModel extends GuardianEntityModel implements PonyModelM
}
@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);
public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, int color) {
mixin().render(matrices, vertices, light, overlay, color);
}
@Override

View file

@ -38,8 +38,8 @@ public class ParaspriteModel<T extends LivingEntity> extends EntityModel<T> {
}
@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);
public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, int color) {
root.render(matrices, vertices, light, overlay, color);
}
@Override

View file

@ -53,6 +53,13 @@ public class PiglinPonyModel extends ZomponyModel<HostileEntity> {
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;
}
@Override
protected void rotateLegs(float move, float swing, float ticks, HostileEntity entity) {
super.rotateLegs(move, swing, ticks, entity);

View file

@ -21,7 +21,7 @@ public class SaddleModel<T extends LivingEntity> extends EntityModel<T> {
}
@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);
public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, int color) {
root.render(matrices, vertices, light, overlay, color);
}
}

View file

@ -9,6 +9,7 @@ import net.minecraft.util.Arm;
import net.minecraft.util.Hand;
import com.minelittlepony.api.model.MobPosingHelper;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.client.model.entity.race.AlicornModel;
public class SkeleponyModel<T extends HostileEntity> extends AlicornModel<T> {
@ -58,11 +59,11 @@ public class SkeleponyModel<T extends HostileEntity> extends AlicornModel<T> {
@Override
protected void rotateLegs(float move, float swing, float ticks, T entity) {
super.rotateLegs(move, swing, ticks, entity);
if (rightArmPose != ArmPose.EMPTY) {
if (rightArmPose != ArmPose.EMPTY && entity.isAttacking()) {
rotateArmHolding(getArm(Arm.RIGHT), -1, getSwingAmount(), ticks);
}
if (leftArmPose != ArmPose.EMPTY) {
if (leftArmPose != ArmPose.EMPTY && entity.isAttacking()) {
rotateArmHolding(getArm(Arm.LEFT), -1, getSwingAmount(), ticks);
}
}
@ -72,8 +73,8 @@ public class SkeleponyModel<T extends HostileEntity> extends AlicornModel<T> {
}
@Override
public boolean hasMagic() {
return isUnicorn;
public Race getRace() {
return isUnicorn ? super.getRace() : Race.EARTH;
}
@Override

View file

@ -5,12 +5,13 @@ import com.minelittlepony.api.model.*;
import com.minelittlepony.api.pony.meta.Size;
import com.minelittlepony.api.pony.meta.SizePreset;
import com.minelittlepony.client.model.part.UnicornHorn;
import com.minelittlepony.client.util.render.RenderList;
import com.minelittlepony.mson.api.ModelView;
import com.minelittlepony.mson.util.RenderList;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity;
import net.minecraft.registry.Registries;
import net.minecraft.util.*;
/**
@ -34,7 +35,7 @@ public class UnicornModel<T extends LivingEntity> extends EarthPonyModel<T> impl
super.init(context);
horn = addPart(context.findByName("horn"));
headRenderList.add(RenderList.of().add(head::rotate).add(forPart(horn)).checked(() -> getRace().hasHorn()));
this.mainRenderList.add(withStage(BodyPart.HEAD, RenderList.of().add(head::rotate).add((stack, vertices, overlayUv, lightUv, red, green, blue, alpha) -> {
this.mainRenderList.add(withStage(BodyPart.HEAD, RenderList.of().add(head::rotate).add((stack, vertices, overlay, light, color) -> {
horn.renderMagic(stack, vertices, getAttributes().metadata.glowColor());
})).checked(() -> hasMagic() && isCasting()));
}
@ -89,8 +90,11 @@ public class UnicornModel<T extends LivingEntity> extends EarthPonyModel<T> impl
matrices.translate(0.4F - (0.3F * left), -0.675F, -0.3F);
UseAction action = getAttributes().heldStack.getUseAction();
boolean shouldAimItem =
(action == UseAction.SPYGLASS || action == UseAction.BOW) && getAttributes().itemUseTime > 0
|| PonyConfig.getInstance().forwardHoldingItems.get().contains(Registries.ITEM.getId(getAttributes().heldStack.getItem()));
if ((action == UseAction.SPYGLASS || action == UseAction.BOW) && getAttributes().itemUseTime > 0) {
if (shouldAimItem) {
Arm main = getAttributes().mainArm;
if (getAttributes().activeHand == Hand.OFF_HAND) {
main = main.getOpposite();

View file

@ -10,7 +10,6 @@ import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.model.gear.WearableGear;
import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.common.util.Color;
import java.util.Calendar;
import java.util.UUID;
@ -63,14 +62,12 @@ public class DeerAntlers extends WearableGear {
}
@Override
public void render(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha, UUID interpolatorId) {
public void render(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color, UUID interpolatorId) {
if (tint != 0) {
red = Color.r(tint);
green = Color.g(tint);
blue = Color.b(tint);
color = tint;
}
left.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
right.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
left.render(stack, vertices, overlay, light, color);
right.render(stack, vertices, overlay, light, color);
}
}

View file

@ -63,7 +63,7 @@ public class SaddleBags extends WearableGear {
}
@Override
public void render(MatrixStack stack, VertexConsumer renderContext, int overlayUv, int lightUv, float red, float green, float blue, float alpha, UUID interpolatorId) {
public void render(MatrixStack stack, VertexConsumer renderContext, int overlay, int light, int color, UUID interpolatorId) {
stack.push();
if (wearable == Wearable.SADDLE_BAGS_BOTH) {
@ -77,11 +77,11 @@ public class SaddleBags extends WearableGear {
stack.translate(0, 0.3F, -0.3F);
}
leftBag.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha);
rightBag.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha);
leftBag.render(stack, renderContext, overlay, light, color);
rightBag.render(stack, renderContext, overlay, light, color);
stack.pop();
strap.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha);
strap.render(stack, renderContext, overlay, light, color);
stack.pop();
}

View file

@ -96,7 +96,7 @@ public class LionTail implements SubModel {
}
@Override
public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha, ModelAttributes attributes) {
tail.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color, ModelAttributes attributes) {
tail.render(stack, vertices, overlay, light, color);
}
}

View file

@ -6,7 +6,6 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.MathHelper;
import com.minelittlepony.api.model.SubModel;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.mson.api.*;
import com.minelittlepony.mson.api.model.PartBuilder;
@ -32,18 +31,13 @@ public class PonyEars implements SubModel, MsonModel {
right.resetTransform();
left.resetTransform();
if (attributes.metadata.race() == Race.CHANGEDLING
|| attributes.metadata.race() == Race.CHANGELING) {
return;
}
limbSpeed = MathHelper.clamp(limbSpeed, 0, 1);
float forwardFold = 0.14F * limbSpeed;
float sidewaysFlop = 0.11F * limbSpeed;
right.pitch = forwardFold;
left.pitch = forwardFold;
right.pitch += forwardFold;
left.pitch += forwardFold;
right.roll -= sidewaysFlop;
left.roll += sidewaysFlop;
@ -58,7 +52,7 @@ public class PonyEars implements SubModel, MsonModel {
}
@Override
public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha, ModelAttributes attributes) {
public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color, ModelAttributes attributes) {
}
@Override

View file

@ -34,7 +34,7 @@ public class PonySnout implements SubModel, MsonModel {
}
@Override
public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha, ModelAttributes attributes) {
public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color, ModelAttributes attributes) {
}
@Override

View file

@ -86,12 +86,12 @@ public class PonyTail implements SubModel, MsonModel {
}
@Override
public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha, ModelAttributes attributes) {
public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color, ModelAttributes attributes) {
stack.push();
tail.rotate(stack);
for (int i = 0; i < segments.size(); i++) {
segments.get(i).render(this, stack, vertices, i, overlayUv, lightUv, red, green, blue, alpha, attributes);
segments.get(i).render(this, stack, vertices, i, overlay, light, color, attributes);
}
stack.pop();
@ -104,7 +104,7 @@ public class PonyTail implements SubModel, MsonModel {
this.tree = tree;
}
public void render(PonyTail tail, MatrixStack stack, VertexConsumer renderContext, int index, int overlayUv, int lightUv, float red, float green, float blue, float alpha, ModelAttributes attributes) {
public void render(PonyTail tail, MatrixStack stack, VertexConsumer renderContext, int index, int overlay, int light, int color, ModelAttributes attributes) {
if (index >= tail.tailStop) {
return;
}
@ -118,7 +118,7 @@ public class PonyTail implements SubModel, MsonModel {
if (attributes.isHorsey || tail.shape == TailShape.STRAIGHT) {
tree.yaw = 0;
tree.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha);
tree.render(stack, renderContext, overlay, light, color);
return;
}
@ -145,7 +145,7 @@ public class PonyTail implements SubModel, MsonModel {
tree.yaw = 0.2F * (index % 2 - 1);
tree.pivotZ = 9;
}
tree.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha);
tree.render(stack, renderContext, overlay, light, color);
stack.pop();
}
}

View file

@ -96,9 +96,9 @@ public class PonyWings<T extends Model & WingedPonyModel<?>> implements SubModel
}
@Override
public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha, ModelAttributes attributes) {
getLeft().render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
getRight().render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color, ModelAttributes attributes) {
getLeft().render(stack, vertices, overlay, light, color);
getRight().render(stack, vertices, overlay, light, color);
}
public static class Wing implements MsonModel {
@ -135,19 +135,19 @@ public class PonyWings<T extends Model & WingedPonyModel<?>> implements SubModel
}
}
public void render(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
public void render(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color) {
stack.push();
stack.scale(wingScale, wingScale, wingScale);
if (pegasus.wingsAreOpen()) {
extended.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
extended.render(stack, vertices, overlay, light, color);
} else {
boolean bags = pegasus.isWearing(Wearable.SADDLE_BAGS_BOTH);
if (bags) {
stack.push();
stack.translate(0, 0, 0.198F);
}
folded.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
folded.render(stack, vertices, overlay, light, color);
if (bags) {
stack.pop();
}

View file

@ -39,8 +39,8 @@ public class SeaponyTail implements SubModel, MsonModel {
}
@Override
public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha, ModelAttributes attributes) {
tailBase.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color, ModelAttributes attributes) {
tailBase.render(stack, vertices, overlay, light, color);
}
}

View file

@ -10,7 +10,6 @@ import net.minecraft.client.util.math.MatrixStack;
import com.minelittlepony.api.model.SubModel;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.client.render.MagicGlow;
import com.minelittlepony.common.util.Color;
public class UnicornHorn implements SubModel {
@ -25,8 +24,8 @@ public class UnicornHorn implements SubModel {
}
@Override
public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha, ModelAttributes attributes) {
horn.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color, ModelAttributes attributes) {
horn.render(stack, vertices, overlay, light, color);
}
public void renderMagic(MatrixStack stack, VertexConsumer verts, int tint) {
@ -34,8 +33,7 @@ public class UnicornHorn implements SubModel {
Immediate immediate = MinecraftClient.getInstance().getBufferBuilders().getEntityVertexConsumers();
VertexConsumer vertices = immediate.getBuffer(MagicGlow.getRenderLayer());
glow.render(stack, vertices, OverlayTexture.DEFAULT_UV, 0x0F00F0, Color.r(tint), Color.g(tint), Color.b(tint), 0.4F);
glow.render(stack, vertices, OverlayTexture.DEFAULT_UV, 0x0F00F0, (tint & 0xFFFFFF) | (102 << 24));
}
}

View file

@ -1,26 +1,27 @@
package com.minelittlepony.client.render;
import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.events.Channel;
import com.minelittlepony.api.events.ClientChannel;
import com.minelittlepony.api.events.PonyDataCallback;
import com.minelittlepony.api.model.*;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.client.PonyDataLoader;
import com.minelittlepony.client.transform.PonyPosture;
import com.minelittlepony.mson.api.ModelKey;
import com.minelittlepony.util.MathUtil;
import com.mojang.blaze3d.systems.RenderSystem;
import java.util.Objects;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import net.fabricmc.api.EnvType;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Frustum;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.*;
import net.minecraft.entity.player.PlayerEntity;
import org.jetbrains.annotations.Nullable;
@ -80,61 +81,29 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
}
models.applyMetadata(pony.metadata());
models.body().updateLivingState(entity, pony, mode);
if (entity instanceof PlayerEntity player && entity instanceof RegistrationHandler handler) {
handler.getSyncedPony().synchronize(player, pony);
}
}
public void setupTransforms(T entity, MatrixStack stack, float ageInTicks, float rotationYaw, float tickDelta) {
public void setupTransforms(T entity, MatrixStack stack, float animationProgress, float bodyYaw, float tickDelta, float scale) {
float s = getScaleFactor();
stack.scale(s, s, s);
if (entity.hasVehicle() && entity.getVehicle() instanceof LivingEntity livingVehicles) {
PonyRenderContext<LivingEntity, ?> renderer = MineLittlePony.getInstance().getRenderDispatcher().getPonyRenderer(livingVehicles);
if (renderer != null) {
// negate vanilla translations so the rider begins at the ridees feet.
stack.translate(0, -livingVehicles.getHeight(), 0);
Pony pony = context.getEntityPony(entity);
if (!pony.race().isHuman()) {
renderer.getInternalRenderer().translateRider(livingVehicles, renderer.getEntityPony(livingVehicles), entity, pony, stack, tickDelta);
}
}
}
if (entity instanceof PlayerEntity) {
if (getModels().body().getAttributes().isSitting) {
stack.translate(0, 0.125D, 0);
}
}
rotationYaw = getMountedYaw(entity, rotationYaw, tickDelta);
transformer.setupTransforms(entity, stack, ageInTicks, rotationYaw, tickDelta);
bodyYaw = getMountedYaw(entity, bodyYaw, tickDelta);
transformer.setupTransforms(entity, stack, animationProgress, bodyYaw, tickDelta, scale);
PonyPosture.of(getModels().body().getAttributes()).apply(entity, getModels().body(), stack, rotationYaw, tickDelta, 1);
PonyPosture.of(getModels().body().getAttributes()).apply(entity, getModels().body(), stack, bodyYaw, tickDelta, 1);
}
private void translateRider(T entity, Pony pony, LivingEntity passenger, Pony passengerPony, MatrixStack stack, float tickDelta) {
if (!passengerPony.race().isHuman()) {
float yaw = MathUtil.interpolateDegress((float)entity.prevY, (float)entity.getY(), tickDelta);
models.applyMetadata(pony.metadata());
models.body().transform(BodyPart.BACK, stack);
PonyPosture.of(models.body().getAttributes()).apply(entity, getModels().body(), stack, yaw, tickDelta, -1);
private float getMountedYaw(T entity, float bodyYaw, float tickDelta) {
if (entity.hasVehicle() && entity.getVehicle() instanceof LivingEntity mount) {
return bodyYaw + MathUtil.interpolateDegress(mount.prevBodyYaw, mount.bodyYaw, tickDelta);
}
}
private float getMountedYaw(T entity, float rotationYaw, float partialTicks) {
if (entity.hasVehicle()) {
Entity mount = entity.getVehicle();
if (mount instanceof LivingEntity) {
return MathUtil.interpolateDegress(((LivingEntity) mount).prevBodyYaw, ((LivingEntity) mount).bodyYaw, partialTicks);
}
}
return rotationYaw;
return bodyYaw;
}
public float getScaleFactor() {
@ -168,7 +137,7 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
}
public interface Transformer<T extends LivingEntity> {
void setupTransforms(T entity, MatrixStack stack, float ageInTicks, float rotationYaw, float partialTicks);
void setupTransforms(T entity, MatrixStack stack, float animationProgress, float bodyYaw, float tickDelta, float scale);
}
public interface RegistrationHandler {
@ -182,24 +151,53 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
public static class SyncedPony {
@Nullable
private Pony lastRenderedPony;
private Supplier<Optional<PonyData>> lastPonyData = PonyDataLoader.NULL;
@Nullable
private Pony lastTransmittedPony;
private boolean seated;
public void synchronize(PlayerEntity player, Pony pony) {
public Pony getCachedPony() {
return lastRenderedPony;
}
public PonyData getCachedPonyData() {
return lastPonyData.get().orElse(PonyData.NULL);
}
public EntityDimensions modifyEyeHeight(PlayerEntity player, EntityDimensions dimensions, EntityPose pose) {
float factor = lastRenderedPony == null ? 1 : lastRenderedPony.size().eyeHeightFactor();
if (factor == 1) {
return dimensions;
}
float eyeHeight = dimensions.eyeHeight() * factor;
if (player.hasVehicle()) {
eyeHeight += player.getVehicleAttachmentPos(player.getVehicle()).getY();
}
return dimensions.withEyeHeight(eyeHeight);
}
public void synchronize(PlayerEntity player) {
Pony pony = Pony.getManager().getPony(player);
boolean changed = pony.compareTo(lastRenderedPony) != 0;
boolean seated = player.hasVehicle();
if (changed) {
if (changed || seated != this.seated) {
lastRenderedPony = pony;
lastPonyData = pony.metadataGetter();
player.calculateDimensions();
}
this.seated = seated;
if (!(player instanceof PreviewModel)) {
@Nullable
PlayerEntity clientPlayer = MinecraftClient.getInstance().player;
if (Channel.isRegistered() && pony.compareTo(lastTransmittedPony) != 0) {
if (ClientChannel.isRegistered() && pony.compareTo(lastTransmittedPony) != 0) {
if (clientPlayer != null && (Objects.equals(player, clientPlayer) || Objects.equals(player.getGameProfile(), clientPlayer.getGameProfile()))) {
if (Channel.broadcastPonyData(pony.metadata())) {
if (ClientChannel.broadcastPonyData(pony.metadata())) {
lastTransmittedPony = pony;
}
}

View file

@ -1,31 +1,36 @@
package com.minelittlepony.client.render;
import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.model.HornedPonyModel;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.client.util.render.RenderLayerUtil;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.common.util.render.RenderLayerUtil;
import org.jetbrains.annotations.Nullable;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.*;
import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.client.render.model.json.ModelTransformationMode;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.CrossbowItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.*;
import net.minecraft.registry.Registries;
import net.minecraft.screen.PlayerScreenHandler;
import net.minecraft.util.UseAction;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis;
import net.minecraft.world.World;
public class LevitatingItemRenderer {
private VertexConsumerProvider getProvider(Pony pony, VertexConsumerProvider renderContext) {
private VertexConsumerProvider getProvider(Pony pony, VertexConsumerProvider provider) {
final int color = pony.metadata().glowColor();
return layer -> {
if (layer.getVertexFormat() != VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL) {
return renderContext.getBuffer(layer);
return provider.getBuffer(layer);
}
return renderContext.getBuffer(MagicGlow.getColoured(RenderLayerUtil.getTexture(layer).orElse(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE), color));
return provider.getBuffer(MagicGlow.getColoured(RenderLayerUtil.getTexture(layer).orElse(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE), color));
};
}
@ -34,39 +39,55 @@ public class LevitatingItemRenderer {
*/
public void renderItem(ItemRenderer itemRenderer, @Nullable LivingEntity entity, ItemStack stack, ModelTransformationMode mode, boolean left, MatrixStack matrix, VertexConsumerProvider renderContext, @Nullable World world, int lightUv, int posLong) {
if (mode.isFirstPerson()
if (entity != null && (mode.isFirstPerson()
|| mode == ModelTransformationMode.THIRD_PERSON_LEFT_HAND
|| mode == ModelTransformationMode.THIRD_PERSON_RIGHT_HAND
|| mode == ModelTransformationMode.THIRD_PERSON_RIGHT_HAND)
) {
Pony.getManager().getPony(entity).ifPresentOrElse(pony -> {
matrix.push();
if (MineLittlePony.getInstance().getRenderDispatcher().getPonyRenderer(entity) instanceof PonyRenderContext<LivingEntity, ?> context) {
Pony pony = context.getEntityPony(entity);
if (context.getInternalRenderer().getModels().body() instanceof HornedPonyModel model) {
matrix.push();
boolean doMagic = PonyConfig.getInstance().fpsmagic.get() && pony.hasMagic();
boolean doMagic = (mode.isFirstPerson() ? PonyConfig.getInstance().fpsmagic : PonyConfig.getInstance().tpsmagic).get() && model.hasMagic();
if (doMagic && mode.isFirstPerson()) {
setupPerspective(itemRenderer, entity, stack, left, matrix);
if (doMagic && mode.isFirstPerson()) {
setupPerspective(itemRenderer, entity, stack, left, matrix);
}
itemRenderer.renderItem(entity, stack, mode, left, matrix, renderContext, world, lightUv, OverlayTexture.DEFAULT_UV, posLong);
if (doMagic) {
VertexConsumerProvider interceptedContext = getProvider(pony, renderContext);
if (stack.hasGlint()) {
stack = stack.copy();
stack.set(DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE, false);
}
float tickDelta = MinecraftClient.getInstance().getRenderTickCounter().getTickDelta(false) + entity.age;
float driftStrength = 0.002F;
float xDrift = MathHelper.sin(tickDelta / 20F) * driftStrength;
float zDrift = MathHelper.cos((tickDelta + 20) / 20F) * driftStrength;
float scale = 1.1F + (MathHelper.sin(tickDelta / 20F) + 1) * driftStrength;
matrix.scale(scale, scale, scale);
matrix.translate(0.015F + xDrift, 0.01F, 0.01F + zDrift);
itemRenderer.renderItem(entity, stack, mode, left, matrix, interceptedContext, world, lightUv, OverlayTexture.DEFAULT_UV, posLong);
matrix.scale(scale, scale, scale);
matrix.translate(-0.03F - xDrift, -0.02F, -0.02F - zDrift);
itemRenderer.renderItem(entity, stack, mode, left, matrix, interceptedContext, world, lightUv, OverlayTexture.DEFAULT_UV, posLong);
}
matrix.pop();
return;
}
itemRenderer.renderItem(entity, stack, mode, left, matrix, renderContext, world, lightUv, OverlayTexture.DEFAULT_UV, posLong);
if (doMagic) {
VertexConsumerProvider interceptedContext = getProvider(pony, renderContext);
matrix.scale(1.1F, 1.1F, 1.1F);
matrix.translate(0.015F, 0.01F, 0.01F);
itemRenderer.renderItem(entity, stack, mode, left, matrix, interceptedContext, world, lightUv, OverlayTexture.DEFAULT_UV, posLong);
matrix.translate(-0.03F, -0.02F, -0.02F);
itemRenderer.renderItem(entity, stack, mode, left, matrix, interceptedContext, world, lightUv, OverlayTexture.DEFAULT_UV, posLong);
}
matrix.pop();
}, () -> {
itemRenderer.renderItem(entity, stack, mode, left, matrix, renderContext, world, lightUv, OverlayTexture.DEFAULT_UV, posLong);
});
} else {
itemRenderer.renderItem(entity, stack, mode, left, matrix, renderContext, world, lightUv, OverlayTexture.DEFAULT_UV, posLong);
}
}
itemRenderer.renderItem(entity, stack, mode, left, matrix, renderContext, world, lightUv, OverlayTexture.DEFAULT_UV, posLong);
}
/**
@ -87,7 +108,10 @@ public class LevitatingItemRenderer {
boolean handHeldTool =
action == UseAction.BOW
|| action == UseAction.CROSSBOW
|| action == UseAction.BLOCK;
|| action == UseAction.BLOCK
|| item.getItem() instanceof ToolItem
|| item.getItem() instanceof RangedWeaponItem
|| PonyConfig.getInstance().forwardHoldingItems.get().contains(Registries.ITEM.getId(item.getItem()));
float distanceChange = handHeldTool ? -0.3F : -0.6F;

View file

@ -30,6 +30,7 @@ public abstract class MagicGlow extends RenderPhase {
.transparency(LIGHTNING_TRANSPARENCY)
.lightmap(DISABLE_LIGHTMAP)
.cull(DISABLE_CULLING)
.layering(VIEW_OFFSET_Z_LAYERING)
.build(false));
});
@ -42,6 +43,7 @@ public abstract class MagicGlow extends RenderPhase {
.transparency(LIGHTNING_TRANSPARENCY)
.lightmap(DISABLE_LIGHTMAP)
.cull(DISABLE_CULLING)
.layering(VIEW_OFFSET_Z_LAYERING)
.build(true));
});

View file

@ -15,7 +15,7 @@ import net.minecraft.entity.EntityType;
/**
* Central location where new entity renderers are registered and applied.
*/
public final class MobRenderers {
public class MobRenderers {
public static final Map<String, MobRenderers> REGISTRY = new HashMap<>();
public static final MobRenderers VILLAGER = register("villagers", (state, pony) -> {
@ -48,6 +48,7 @@ public final class MobRenderers {
public static final MobRenderers SKELETON = register("skeletons", (state, pony) -> {
pony.switchRenderer(state, EntityType.SKELETON, SkeleponyRenderer::skeleton);
pony.switchRenderer(state, EntityType.STRAY, SkeleponyRenderer::stray);
pony.switchRenderer(state, EntityType.BOGGED, SkeleponyRenderer::bogged);
pony.switchRenderer(state, EntityType.WITHER_SKELETON, SkeleponyRenderer::wither);
});
public static final MobRenderers GUARDIAN = register("guardians", (state, pony) -> {

View file

@ -2,7 +2,9 @@ package com.minelittlepony.client.render;
import java.util.function.Function;
import com.google.common.base.Predicates;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.model.PreviewModel;
import com.minelittlepony.api.pony.*;
import com.minelittlepony.client.mixin.MixinEntityRenderers;
import com.minelittlepony.client.render.entity.*;
@ -18,7 +20,6 @@ import net.minecraft.client.util.SkinTextures;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Identifier;
/**
* Render manager responsible for replacing and restoring entity renderers when the client settings change.
@ -26,6 +27,17 @@ import net.minecraft.util.Identifier;
public class PonyRenderDispatcher {
private LevitatingItemRenderer magicRenderer = new LevitatingItemRenderer();
public PonyRenderDispatcher() {
PonyForm.register(PonyForm.DEFAULT, Predicates.alwaysTrue(), PlayerPonyRenderer::new);
PonyForm.register(PonyForm.SEAPONY, PonyPosture::hasSeaponyForm, (context, slimArms) -> new AquaticPlayerPonyRenderer(context, slimArms, DefaultPonySkinHelper.SEAPONY_SKIN_TYPE_ID, entity -> {
if (entity instanceof PreviewModel preview) {
return preview.getForm() == PonyForm.SEAPONY;
}
return PonyPosture.hasSeaponyForm(entity) && PonyPosture.isPartiallySubmerged(entity);
}));
PonyForm.register(PonyForm.NIRIK, PonyPosture::hasNirikForm, (context, slimArms) -> new FormChangingPlayerPonyRenderer(context, slimArms, DefaultPonySkinHelper.NIRIK_SKIN_TYPE_ID, PonyPosture::hasNirikForm));
}
public LevitatingItemRenderer getMagicRenderer() {
return magicRenderer;
}
@ -34,42 +46,20 @@ public class PonyRenderDispatcher {
* Registers all new player skin types. (currently only pony and slimpony).
*/
public void initialise(EntityRenderDispatcher manager, boolean force) {
for (SkinTextures.Model armShape : SkinTextures.Model.values()) {
addPlayerRenderer(armShape);
}
PonyForm.REGISTRY.values().forEach(form -> {
for (SkinTextures.Model armShape : SkinTextures.Model.values()) {
Mson.getInstance().getEntityRendererRegistry().registerPlayerRenderer(
form.id().withSuffixedPath("/" + armShape.getName()),
player -> !Pony.getManager().getPony(player).race().isHuman()
&& player.getSkinTextures().model() == armShape
&& form.shouldApply().test(player) && PonyForm.of(player) == form,
context -> form.factory().create(context, armShape == SkinTextures.Model.SLIM)
);
}
});
MobRenderers.REGISTRY.values().forEach(i -> i.apply(this, force));
}
private void addPlayerRenderer(SkinTextures.Model armShape) {
Mson.getInstance().getEntityRendererRegistry().registerPlayerRenderer(
new Identifier("minelittlepony", "sea/" + armShape.getName()),
player -> {
return !Pony.getManager().getPony(player).race().isHuman()
&& PonyPosture.hasSeaponyForm(player)
&& player.getSkinTextures().model() == armShape;
},
context -> new AquaticPlayerPonyRenderer(context, armShape == SkinTextures.Model.SLIM)
);
Mson.getInstance().getEntityRendererRegistry().registerPlayerRenderer(
new Identifier("minelittlepony", "nirik/" + armShape.getName()),
player -> {
return !Pony.getManager().getPony(player).race().isHuman()
&& PonyPosture.hasNirikForm(player)
&& player.getSkinTextures().model() == armShape;
},
context -> new FormChangingPlayerPonyRenderer(context, armShape == SkinTextures.Model.SLIM, DefaultPonySkinHelper.NIRIK_SKIN_TYPE_ID, PonyPosture::isNirikModifier)
);
Mson.getInstance().getEntityRendererRegistry().registerPlayerRenderer(
new Identifier("minelittlepony", "land/" + armShape.getName()),
player -> {
return !Pony.getManager().getPony(player).race().isHuman()
&& !PonyPosture.hasSeaponyForm(player) && !PonyPosture.hasNirikForm(player)
&& player.getSkinTextures().model() == armShape;
},
context -> new PlayerPonyRenderer(context, armShape == SkinTextures.Model.SLIM)
);
}
/**
*
* Replaces an entity renderer depending on whether we want ponies or not.
@ -80,25 +70,17 @@ public class PonyRenderDispatcher {
* @param <T> The entity type
*/
<T extends Entity, V extends T> void switchRenderer(MobRenderers state, EntityType<V> type, Function<EntityRendererFactory.Context, EntityRenderer<T>> factory) {
Mson.getInstance().getEntityRendererRegistry().registerEntityRenderer(type, ctx -> {
if (!state.get()) {
return MixinEntityRenderers.getRendererFactories().get(type).create(ctx);
}
return factory.apply(ctx);
});
Mson.getInstance().getEntityRendererRegistry().registerEntityRenderer(type, ctx -> state.get()
? factory.apply(ctx)
: MixinEntityRenderers.getRendererFactories().get(type).create(ctx)
);
}
@SuppressWarnings("unchecked")
@Nullable
public <T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> PonyRenderContext<T, M> getPonyRenderer(@Nullable T entity) {
if (entity == null) {
return null;
}
EntityRenderer<?> renderer = MinecraftClient.getInstance().getEntityRenderDispatcher().getRenderer(entity);
if (renderer instanceof PonyRenderContext) {
return (PonyRenderContext<T, M>) renderer;
if (entity != null && MinecraftClient.getInstance().getEntityRenderDispatcher().getRenderer(entity) instanceof PonyRenderContext c) {
return c;
}
return null;

View file

@ -7,13 +7,13 @@ import com.minelittlepony.client.model.AbstractPonyModel;
import com.minelittlepony.client.render.MobRenderers;
import com.minelittlepony.client.render.blockentity.skull.PonySkullRenderer.ISkull;
import com.minelittlepony.mson.api.ModelKey;
import com.mojang.authlib.GameProfile;
import java.util.function.Supplier;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.component.type.ProfileComponent;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.RotationAxis;
@ -38,7 +38,7 @@ public class MobSkull implements ISkull {
}
@Override
public Identifier getSkinResource(@Nullable GameProfile profile) {
public Identifier getSkinResource(@Nullable ProfileComponent profile) {
return texture;
}
@ -61,7 +61,7 @@ public class MobSkull implements ISkull {
}
@Override
public void render(MatrixStack stack, VertexConsumer vertices, int lightUv, int overlayUv, float red, float green, float blue, float alpha) {
ponyHead.get().headRenderList.accept(stack, vertices, lightUv, overlayUv, red, green, blue, alpha);
public void render(MatrixStack stack, VertexConsumer vertices, int light, int overlay, int color) {
ponyHead.get().headRenderList.accept(stack, vertices, light, overlay, color);
}
}

View file

@ -7,7 +7,6 @@ import com.minelittlepony.api.pony.SkinsProxy;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.client.model.*;
import com.minelittlepony.client.render.blockentity.skull.PonySkullRenderer.ISkull;
import com.mojang.authlib.GameProfile;
import java.util.HashMap;
import java.util.Map;
@ -15,6 +14,7 @@ import java.util.Map;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.DefaultSkinHelper;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.component.type.ProfileComponent;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.RotationAxis;
@ -35,17 +35,17 @@ public class PlayerPonySkull implements ISkull {
}
@Override
public Identifier getSkinResource(@Nullable GameProfile profile) {
renderingEars = profile != null && "deadmau5".equals(profile.getName());
public Identifier getSkinResource(@Nullable ProfileComponent profile) {
renderingEars = profile != null && "deadmau5".equals(profile.gameProfile().getName());
if (profile != null) {
Identifier skin = SkinsProxy.instance.getSkinTexture(profile);
Identifier skin = SkinsProxy.getInstance().getSkinTexture(profile.gameProfile());
if (skin != null) {
return skin;
}
return DefaultSkinHelper.getSkinTextures(profile).texture();
return DefaultSkinHelper.getSkinTextures(profile.gameProfile()).texture();
}
return DefaultSkinHelper.getTexture();
@ -80,18 +80,18 @@ public class PlayerPonySkull implements ISkull {
}
@Override
public void render(MatrixStack stack, VertexConsumer vertices, int lightUv, int overlayUv, float red, float green, float blue, float alpha) {
public void render(MatrixStack stack, VertexConsumer vertices, int light, int overlay, int color) {
stack.push();
ponyHead.headRenderList.accept(stack, vertices, lightUv, overlayUv, red, green, blue, alpha);
ponyHead.headRenderList.accept(stack, vertices, light, overlay, color);
stack.pop();
stack.push();
ponyHead.helmetRenderList.accept(stack, vertices, lightUv, overlayUv, red, green, blue, alpha);
ponyHead.helmetRenderList.accept(stack, vertices, light, overlay, color);
stack.pop();
if (renderingEars) {
stack.push();
stack.scale(1.3333334f, 1.3333334f, 1.3333334f);
stack.translate(0, 0.05F, 0);
deadMau5.render(stack, vertices, lightUv, overlayUv, red, green, blue, alpha);
deadMau5.render(stack, vertices, light, overlay, color);
stack.pop();
}
}

View file

@ -1,23 +1,36 @@
package com.minelittlepony.client.render.blockentity.skull;
import com.google.common.collect.Maps;
import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.armour.ArmourLayer;
import com.minelittlepony.client.model.armour.ArmourRendererPlugin;
import com.minelittlepony.client.render.MobRenderers;
import com.minelittlepony.client.render.entity.SkeleponyRenderer;
import com.minelittlepony.client.render.entity.ZomponyRenderer;
import com.mojang.authlib.GameProfile;
import com.minelittlepony.client.render.entity.*;
import com.minelittlepony.common.util.Color;
import net.minecraft.block.AbstractSkullBlock;
import net.minecraft.block.SkullBlock;
import net.minecraft.block.SkullBlock.SkullType;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
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.DataComponentTypes;
import net.minecraft.component.type.ProfileComponent;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.math.Direction;
import java.util.HashMap;
import java.util.Map;
import org.jetbrains.annotations.Nullable;
@ -25,29 +38,44 @@ import org.jetbrains.annotations.Nullable;
* PonySkullRenderer! It renders ponies as skulls, or something...
*/
public class PonySkullRenderer {
public static final PonySkullRenderer INSTANCE = new PonySkullRenderer();
private static final Map<SkullBlock.SkullType, ISkull> SKULLS = Maps.newHashMap();
private Map<SkullBlock.SkullType, ISkull> skulls = Map.of();
private Map<SkullBlock.SkullType, SkullBlockEntityModel> headModels = Map.of();
private static ISkull selectedSkull;
private static Identifier selectedSkin;
private ISkull selectedSkull;
private Identifier selectedSkin;
public static void reload() {
SKULLS.clear();
loadSkulls(SKULLS);
boolean isBeingWorn;
boolean isPony;
public void reload() {
skulls = Util.make(new HashMap<>(), skullMap -> {
skullMap.put(SkullBlock.Type.SKELETON, new MobSkull(SkeleponyRenderer.SKELETON, MobRenderers.SKELETON, ModelType.SKELETON));
skullMap.put(SkullBlock.Type.WITHER_SKELETON, new MobSkull(SkeleponyRenderer.WITHER, MobRenderers.SKELETON, ModelType.SKELETON));
skullMap.put(SkullBlock.Type.ZOMBIE, new MobSkull(ZomponyRenderer.ZOMBIE, MobRenderers.ZOMBIE, ModelType.ZOMBIE));
skullMap.put(SkullBlock.Type.PIGLIN, new MobSkull(PonyPiglinRenderer.PIGLIN, MobRenderers.PIGLIN, ModelType.PIGLIN));
skullMap.put(SkullBlock.Type.PLAYER, new PlayerPonySkull());
});
headModels = SkullBlockEntityRenderer.getModels(MinecraftClient.getInstance().getEntityModelLoader());
}
private static void loadSkulls(Map<SkullBlock.SkullType, ISkull> skullMap) {
skullMap.put(SkullBlock.Type.SKELETON, new MobSkull(SkeleponyRenderer.SKELETON, MobRenderers.SKELETON, ModelType.SKELETON));
skullMap.put(SkullBlock.Type.WITHER_SKELETON, new MobSkull(SkeleponyRenderer.WITHER, MobRenderers.SKELETON, ModelType.SKELETON));
skullMap.put(SkullBlock.Type.ZOMBIE, new MobSkull(ZomponyRenderer.ZOMBIE, MobRenderers.ZOMBIE, ModelType.ZOMBIE));
skullMap.put(SkullBlock.Type.PLAYER, new PlayerPonySkull());
public void renderSkull(MatrixStack matrices, VertexConsumerProvider provider, ItemStack stack, LivingEntity entity, float tickDelta, int light, boolean isPony) {
isBeingWorn = true;
this.isPony = isPony;
SkullType type = ((AbstractSkullBlock) ((BlockItem) stack.getItem()).getBlock()).getSkullType();
SkullBlockEntityModel skullBlockEntityModel = headModels.get(type);
RenderLayer renderLayer = SkullBlockEntityRenderer.getRenderLayer(type, stack.get(DataComponentTypes.PROFILE));
SkullBlockEntityRenderer.renderSkull(null, 180, (entity.getVehicle() instanceof LivingEntity l ? l : entity).limbAnimator.getPos(tickDelta), matrices, provider, light, skullBlockEntityModel, renderLayer);
isBeingWorn = false;
this.isPony = false;
}
public static RenderLayer getSkullRenderLayer(SkullBlock.SkullType skullType, @Nullable GameProfile profile) {
public RenderLayer getSkullRenderLayer(SkullBlock.SkullType skullType, @Nullable ProfileComponent profile) {
selectedSkull = null;
selectedSkin = null;
ISkull skull = SKULLS.get(skullType);
ISkull skull = skulls.get(skullType);
if (skull == null || !skull.canRender(PonyConfig.getInstance())) {
return null;
@ -58,16 +86,12 @@ public class PonySkullRenderer {
return RenderLayer.getEntityTranslucent(selectedSkin);
}
public static boolean renderSkull(@Nullable Direction direction,
public boolean renderSkull(@Nullable Direction direction,
float yaw, float animationProgress,
MatrixStack stack, VertexConsumerProvider renderContext, RenderLayer layer,
int lightUv) {
int light) {
if (selectedSkull == null || !selectedSkull.canRender(PonyConfig.getInstance())) {
return false;
}
if (!selectedSkull.bindPony(Pony.getManager().getPony(selectedSkin))) {
if (selectedSkull == null || !selectedSkull.canRender(PonyConfig.getInstance()) || !selectedSkull.bindPony(Pony.getManager().getPony(selectedSkin))) {
return false;
}
@ -76,7 +100,6 @@ public class PonySkullRenderer {
if (direction == null) {
stack.translate(0.5, 0, 0.5);
} else {
final float offset = 0.25F;
stack.translate(
0.5F - direction.getOffsetX() * offset,
@ -89,7 +112,7 @@ public class PonySkullRenderer {
VertexConsumer vertices = renderContext.getBuffer(layer);
selectedSkull.setAngles(yaw, animationProgress);
selectedSkull.render(stack, vertices, lightUv, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1);
selectedSkull.render(stack, vertices, light, OverlayTexture.DEFAULT_UV, Color.argbToHex(ArmourRendererPlugin.INSTANCE.get().getArmourAlpha(EquipmentSlot.HEAD, ArmourLayer.OUTER), 1, 1, 1));
stack.pop();
@ -102,15 +125,18 @@ public class PonySkullRenderer {
* Implement this interface if you want to extend our behaviour, modders.
*/
public interface ISkull {
void setAngles(float angle, float poweredTicks);
void render(MatrixStack stack, VertexConsumer vertices, int lightUv, int overlayUv, float red, float green, float blue, float alpha);
void render(MatrixStack stack, VertexConsumer vertices, int light, int overlay, int color);
boolean canRender(PonyConfig config);
Identifier getSkinResource(@Nullable GameProfile profile);
Identifier getSkinResource(@Nullable ProfileComponent profile);
boolean bindPony(Pony pony);
}
public interface SkullRenderer {
Map<SkullBlock.SkullType, SkullBlockEntityModel> getModels();
}
}

View file

@ -49,7 +49,7 @@ public abstract class AbstractPonyRenderer<T extends MobEntity, M extends Entity
protected void addFeatures(EntityRendererFactory.Context context) {
addFeature(new ArmourFeature<>(this, context.getModelManager()));
addFeature(createHeldItemFeature(context));
addFeature(new SkullFeature<>(this, context.getModelLoader()));
addFeature(new SkullFeature<>(this, context.getModelLoader(), context.getItemRenderer()));
addFeature(new ElytraFeature<>(this));
addFeature(new GearFeature<>(this));
}
@ -74,8 +74,8 @@ public abstract class AbstractPonyRenderer<T extends MobEntity, M extends Entity
}
@Override
protected void setupTransforms(T entity, MatrixStack stack, float ageInTicks, float rotationYaw, float partialTicks) {
manager.setupTransforms(entity, stack, ageInTicks, rotationYaw, partialTicks);
protected void setupTransforms(T entity, MatrixStack stack, float animationProgress, float bodyYaw, float tickDelta, float scale) {
manager.setupTransforms(entity, stack, animationProgress, bodyYaw, tickDelta, scale);
}
@Override
@ -94,18 +94,20 @@ public abstract class AbstractPonyRenderer<T extends MobEntity, M extends Entity
if (!entity.hasVehicle()) {
stack.translate(0, 0, -entity.getWidth() / 2); // move us to the center of the shadow
} else {
stack.translate(0, entity.getRidingOffset(entity.getVehicle()), 0);
if (manager.getModels().body().getAttributes().isSitting && entity.hasVehicle()) {
stack.translate(0, 0.25F, 0);
}
}
stack.scale(scale, scale, scale);
}
@Override
protected void renderLabelIfPresent(T entity, Text name, MatrixStack stack, VertexConsumerProvider renderContext, int maxDistance) {
stack.push();
stack.translate(0, manager.getNamePlateYOffset(entity), 0);
super.renderLabelIfPresent(entity, name, stack, renderContext, maxDistance);
stack.pop();
protected void renderLabelIfPresent(T entity, Text name, MatrixStack matrices, VertexConsumerProvider vertices, int light, float tickDelta) {
matrices.push();
matrices.translate(0, manager.getNamePlateYOffset(entity), 0);
super.renderLabelIfPresent(entity, name, matrices, vertices, light, tickDelta);
matrices.pop();
}
@Override

View file

@ -16,7 +16,7 @@ import com.minelittlepony.client.model.entity.BreezieModel;
* AKA a breezie :D
*/
public class AllayRenderer extends MobEntityRenderer<AllayEntity, BreezieModel<AllayEntity>> {
public static final Identifier BREEZIE_PONIES = new Identifier("minelittlepony", "textures/entity/allay/pony");
public static final Identifier BREEZIE_PONIES = MineLittlePony.id("textures/entity/allay/pony");
public AllayRenderer(EntityRendererFactory.Context context) {
super(context, ModelType.ALLAY.createModel(), 0.4f);

View file

@ -5,16 +5,19 @@ import com.minelittlepony.api.pony.*;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.util.MathUtil;
import java.util.function.Predicate;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.util.Identifier;
public class AquaticPlayerPonyRenderer extends FormChangingPlayerPonyRenderer {
public AquaticPlayerPonyRenderer(EntityRendererFactory.Context context, boolean slim) {
super(context, slim, DefaultPonySkinHelper.SEAPONY_SKIN_TYPE_ID, PonyPosture::isSeaponyModifier);
public AquaticPlayerPonyRenderer(EntityRendererFactory.Context context, boolean slim, Identifier alternateFormSkinId, Predicate<AbstractClientPlayerEntity> formModifierPredicate) {
super(context, slim, alternateFormSkinId, formModifierPredicate);
}
@Override
@ -32,18 +35,18 @@ public class AquaticPlayerPonyRenderer extends FormChangingPlayerPonyRenderer {
@Override
protected Race getPlayerRace(AbstractClientPlayerEntity entity, Pony pony) {
Race race = super.getPlayerRace(entity, pony);
return PonyPosture.isSeaponyModifier(entity) ? Race.SEAPONY : race == Race.SEAPONY ? Race.UNICORN : race;
return transformed ? Race.SEAPONY : race == Race.SEAPONY ? Race.UNICORN : race;
}
@Override
protected void setupTransforms(AbstractClientPlayerEntity player, MatrixStack stack, float ageInTicks, float rotationYaw, float partialTicks) {
if (PonyPosture.isSeaponyModifier(player)) {
stack.translate(0, 0.6, 0);
protected void setupTransforms(AbstractClientPlayerEntity player, MatrixStack matrices, float animationProgress, float bodyYaw, float tickDelta, float scale) {
if (transformed) {
matrices.translate(0, 0.6 * scale, 0);
if (player.isInSneakingPose()) {
stack.translate(0, 0.125, 0);
matrices.translate(0, 0.125 * scale, 0);
}
}
super.setupTransforms(player, stack, ageInTicks, rotationYaw, partialTicks);
super.setupTransforms(player, matrices, animationProgress, bodyYaw, tickDelta, scale);
}
@Override

View file

@ -1,5 +1,6 @@
package com.minelittlepony.client.render.entity;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.entity.EnderStallionModel;
import com.minelittlepony.client.render.entity.feature.GlowingEyesFeature;
@ -19,9 +20,8 @@ import net.minecraft.util.Identifier;
import java.util.Random;
public class EnderStallionRenderer extends PonyRenderer<EndermanEntity, EnderStallionModel> implements IGlowingRenderer {
public static final Identifier ENDERMAN = new Identifier("minelittlepony", "textures/entity/enderman/enderman_pony.png");
private static final Identifier EYES = new Identifier("minelittlepony", "textures/entity/enderman/enderman_pony_eyes.png");
public static final Identifier ENDERMAN = MineLittlePony.id("textures/entity/enderman/enderman_pony.png");
private static final Identifier EYES = MineLittlePony.id("textures/entity/enderman/enderman_pony_eyes.png");
private final Random rnd = new Random();

View file

@ -1,14 +1,12 @@
package com.minelittlepony.client.render.entity;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.pony.*;
import java.util.function.Predicate;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Arm;
import net.minecraft.util.Identifier;
public class FormChangingPlayerPonyRenderer extends PlayerPonyRenderer {
@ -27,20 +25,14 @@ public class FormChangingPlayerPonyRenderer extends PlayerPonyRenderer {
@Override
public Identifier getTexture(AbstractClientPlayerEntity player) {
if (transformed) {
return SkinsProxy.instance.getSkin(alternateFormSkinId, player).orElseGet(() -> super.getTexture(player));
return SkinsProxy.getInstance().getSkin(alternateFormSkinId, player).orElseGet(() -> super.getTexture(player));
}
return super.getTexture(player);
}
@Override
public void render(AbstractClientPlayerEntity player, float entityYaw, float tickDelta, MatrixStack stack, VertexConsumerProvider renderContext, int light) {
super.render(player, entityYaw, tickDelta, stack, renderContext, light);
updateForm(player);
}
@Override
protected void renderArm(MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, AbstractClientPlayerEntity player, Arm side) {
super.renderArm(stack, renderContext, lightUv, player, side);
protected final void preRender(AbstractClientPlayerEntity player, ModelAttributes.Mode mode) {
super.preRender(player, mode);
updateForm(player);
}

View file

@ -10,7 +10,7 @@ import com.minelittlepony.client.model.*;
import com.minelittlepony.client.render.DebugBoundingBoxRenderer;
import com.minelittlepony.client.render.PonyRenderContext;
import com.minelittlepony.client.render.entity.feature.*;
import com.minelittlepony.client.util.render.RenderLayerUtil;
import com.minelittlepony.common.util.render.RenderLayerUtil;
import java.util.*;
import java.util.function.Function;
@ -37,11 +37,11 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements PonyRend
modelsCache = Util.memoize(race -> ModelType.getPlayerModel(race).create(slim));
manager = new EquineRenderManager<>(this, super::setupTransforms, modelsCache.apply(Race.EARTH));
manager.setModelsLookup(entity -> modelsCache.apply(getPlayerRace(entity, getEntityPony(entity))));
addLayers(context);
addPonyFeatures(context);
}
@SuppressWarnings({"unchecked", "rawtypes"})
protected void addLayers(EntityRendererFactory.Context context) {
protected void addPonyFeatures(EntityRendererFactory.Context context) {
// remove vanilla features (keep modded ones)
features.removeIf(feature -> {
return feature instanceof ArmorFeatureRenderer
@ -52,32 +52,37 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements PonyRend
|| feature instanceof ElytraFeatureRenderer
|| feature instanceof ShoulderParrotFeatureRenderer;
});
addLayer(new ArmourFeature<>(this, context.getModelManager()));
addLayer(new HeldItemFeature(this, context.getHeldItemRenderer()));
addLayer(new DJPon3Feature<>(this));
addLayer(new CapeFeature<>(this));
addLayer(new SkullFeature<>(this, context.getModelLoader()));
addLayer(new ElytraFeature<>(this));
addLayer(new PassengerFeature<>(this, context));
addLayer(new GearFeature<>(this));
addPonyFeature(new ArmourFeature<>(this, context.getModelManager()));
addPonyFeature(new HeldItemFeature(this, context.getHeldItemRenderer()));
addPonyFeature(new DJPon3Feature<>(this));
addPonyFeature(new CapeFeature<>(this));
addPonyFeature(new SkullFeature<>(this, context.getModelLoader(), context.getItemRenderer()));
addPonyFeature(new ElytraFeature<>(this));
addPonyFeature(new PassengerFeature<>(this, context));
addPonyFeature(new GearFeature<>(this));
}
@SuppressWarnings({"unchecked", "rawtypes"})
protected boolean addLayer(FeatureRenderer<AbstractClientPlayerEntity, ? extends ClientPonyModel<AbstractClientPlayerEntity>> feature) {
protected final boolean addPonyFeature(FeatureRenderer<AbstractClientPlayerEntity, ? extends ClientPonyModel<AbstractClientPlayerEntity>> feature) {
return ((List)features).add(feature);
}
@Override
protected void scale(AbstractClientPlayerEntity entity, MatrixStack stack, float tickDelta) {
if (manager.getModels().body().getAttributes().isSitting && entity.hasVehicle()) {
stack.translate(0, entity.getRidingOffset(entity.getVehicle()), 0);
stack.translate(0, -0.25F * manager.getScaleFactor(), 0);
}
super.scale(entity, stack, tickDelta);
}
protected void preRender(AbstractClientPlayerEntity player, ModelAttributes.Mode mode) {
manager.preRender(player, mode);
}
@Override
public void render(AbstractClientPlayerEntity entity, float entityYaw, float tickDelta, MatrixStack stack, VertexConsumerProvider renderContext, int lightUv) {
// EntityModelFeatures: We have to force it to use our models otherwise EMF overrides it and breaks pony rendering
manager.preRender(entity, ModelAttributes.Mode.THIRD_PERSON);
preRender(entity, ModelAttributes.Mode.THIRD_PERSON);
shadowRadius = manager.getShadowSize();
super.render(entity, entityYaw, tickDelta, stack, renderContext, lightUv);
DebugBoundingBoxRenderer.render(getEntityPony(entity), this, entity, stack, renderContext, tickDelta);
@ -102,8 +107,8 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements PonyRend
}
@Override
protected void setupTransforms(AbstractClientPlayerEntity entity, MatrixStack stack, float ageInTicks, float rotationYaw, float partialTicks) {
manager.setupTransforms(entity, stack, ageInTicks, rotationYaw, partialTicks);
protected void setupTransforms(AbstractClientPlayerEntity entity, MatrixStack matrices, float animationProgress, float bodyYaw, float tickDelta, float scale) {
manager.setupTransforms(entity, matrices, animationProgress, bodyYaw, tickDelta, scale);
}
@Override
@ -116,7 +121,7 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements PonyRend
}
@Override
protected void renderLabelIfPresent(AbstractClientPlayerEntity entity, Text name, MatrixStack stack, VertexConsumerProvider renderContext, int maxDistance) {
protected void renderLabelIfPresent(AbstractClientPlayerEntity entity, Text name, MatrixStack stack, VertexConsumerProvider renderContext, int light, float tickDelta) {
stack.push();
if (entity.isSleeping()) {
@ -127,7 +132,7 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements PonyRend
}
}
stack.translate(0, manager.getNamePlateYOffset(entity), 0);
super.renderLabelIfPresent(entity, name, stack, renderContext, maxDistance);
super.renderLabelIfPresent(entity, name, stack, renderContext, light, tickDelta);
stack.pop();
}
@ -142,7 +147,7 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements PonyRend
}
protected void renderArm(MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, AbstractClientPlayerEntity player, Arm side) {
manager.preRender(player, ModelAttributes.Mode.FIRST_PERSON);
preRender(player, ModelAttributes.Mode.FIRST_PERSON);
stack.push();
float reflect = side == Arm.LEFT ? 1 : -1;
@ -191,7 +196,7 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements PonyRend
@Override
public Identifier getDefaultTexture(AbstractClientPlayerEntity entity, Wearable wearable) {
return SkinsProxy.instance.getSkin(wearable.getId(), entity).orElseGet(() -> {
return SkinsProxy.getInstance().getSkin(wearable.getId(), entity).orElseGet(() -> {
if (wearable.isSaddlebags() && getInternalRenderer().getModels().body().getRace().supportsLegacySaddlebags()) {
return getTexture(entity);
}

View file

@ -36,7 +36,7 @@ public class PonyPigRenderer extends PigEntityRenderer {
model.animateModel(entity, limbAngle, limbDistance, tickDelta);
model.setAngles(entity, limbAngle, limbDistance, animationProgress, headYaw, headPitch);
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(RenderLayer.getEntityCutoutNoCull(Wearable.CROWN.getDefaultTexture()));
model.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1);
model.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV, 0xFFFFFFFF);
}
}
}

View file

@ -5,14 +5,15 @@ import net.minecraft.entity.mob.AbstractPiglinEntity;
import net.minecraft.entity.mob.HostileEntity;
import net.minecraft.util.Identifier;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.entity.PiglinPonyModel;
import com.minelittlepony.client.render.entity.npc.textures.TextureSupplier;
public class PonyPiglinRenderer extends PonyRenderer<HostileEntity, PiglinPonyModel> {
private static final Identifier PIGLIN = new Identifier("minelittlepony", "textures/entity/piglin/piglin_pony.png");
private static final Identifier PIGLIN_BRUTE = new Identifier("minelittlepony", "textures/entity/piglin/piglin_brute_pony.png");
private static final Identifier ZOMBIFIED_PIGLIN = new Identifier("minelittlepony", "textures/entity/piglin/zombified_piglin_pony.png");
public static final Identifier PIGLIN = MineLittlePony.id("textures/entity/piglin/piglin_pony.png");
public static final Identifier PIGLIN_BRUTE = MineLittlePony.id("textures/entity/piglin/piglin_brute_pony.png");
public static final Identifier ZOMBIFIED_PIGLIN = MineLittlePony.id("textures/entity/piglin/zombified_piglin_pony.png");
public PonyPiglinRenderer(EntityRendererFactory.Context context, Identifier texture, float scale) {
super(context, ModelType.PIGLIN, TextureSupplier.of(texture), scale);

View file

@ -7,7 +7,6 @@ import net.minecraft.client.render.entity.feature.*;
import net.minecraft.client.render.entity.model.ArmorStandArmorEntityModel;
import net.minecraft.client.render.entity.model.EntityModelLayers;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.util.math.Vec3d;
@ -15,7 +14,6 @@ import com.minelittlepony.api.model.Models;
import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.armour.ArmourLayer;
import com.minelittlepony.client.model.entity.PonyArmourStandModel;
import com.minelittlepony.client.model.entity.race.EarthPonyModel;
import com.minelittlepony.client.render.entity.feature.ArmourFeature;
@ -52,10 +50,10 @@ public class PonyStandRenderer extends ArmorStandEntityRenderer {
}
@Override
protected void setupTransforms(ArmorStandEntity entity, MatrixStack stack, float f, float g, float h) {
super.setupTransforms(entity, stack, f, g, h);
protected void setupTransforms(ArmorStandEntity entity, MatrixStack stack, float animationProgress, float bodyYaw, float tickDelta, float scale) {
super.setupTransforms(entity, stack, animationProgress, bodyYaw, tickDelta, scale);
if (isPonita(entity)) {
stack.translate(0, 0, -4/16F);
stack.translate(0, 0, scale * -4/16F);
}
}
@ -82,13 +80,7 @@ public class PonyStandRenderer extends ArmorStandEntityRenderer {
pony.body().animateModel(entity, limbDistance, limbAngle, tickDelta);
pony.body().setAngles(entity, limbDistance, limbAngle, age, headYaw, headPitch);
PonyStandRenderer.this.pony.applyAnglesTo(pony.body());
for (EquipmentSlot i : EquipmentSlot.values()) {
if (i.getType() == EquipmentSlot.Type.ARMOR) {
ArmourFeature.renderArmor(pony, stack, renderContext, lightUv, entity, limbDistance, limbAngle, age, headYaw, headPitch, i, ArmourLayer.INNER);
ArmourFeature.renderArmor(pony, stack, renderContext, lightUv, entity, limbDistance, limbAngle, age, headYaw, headPitch, i, ArmourLayer.OUTER);
}
}
ArmourFeature.renderArmor(pony, stack, renderContext, lightUv, entity, limbDistance, limbAngle, age, headYaw, headPitch);
} else {
super.render(stack, renderContext, lightUv, entity, limbDistance, limbAngle, tickDelta, age, headYaw, headPitch);
}

View file

@ -3,6 +3,7 @@ package com.minelittlepony.client.render.entity;
import org.jetbrains.annotations.NotNull;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.mixin.IResizeable;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.entity.GuardianPonyModel;
@ -17,10 +18,10 @@ import net.minecraft.entity.mob.GuardianEntity;
import net.minecraft.util.Identifier;
public class SeaponyRenderer extends GuardianEntityRenderer {
public static final Identifier SEAPONY = new Identifier("minelittlepony", "textures/entity/guardian/blueball.png");
private static final Identifier SEAPONY_TEXTURES = new Identifier("minelittlepony", "textures/entity/guardian");
public static final Identifier ELDER_SEAPONY = new Identifier("minelittlepony", "textures/entity/elder_guardian/blueball.png");
private static final Identifier ELDER_SEAPONY_TEXTURES = new Identifier("minelittlepony", "textures/entity/elder_guardian");
public static final Identifier SEAPONY = MineLittlePony.id("textures/entity/guardian/blueball.png");
private static final Identifier SEAPONY_TEXTURES = MineLittlePony.id("textures/entity/guardian");
public static final Identifier ELDER_SEAPONY = MineLittlePony.id("textures/entity/elder_guardian/blueball.png");
private static final Identifier ELDER_SEAPONY_TEXTURES = MineLittlePony.id("textures/entity/elder_guardian");
private final AbstractPonyRenderer<GuardianEntity, GuardianPonyModel> ponyRenderer;
@ -64,7 +65,7 @@ public class SeaponyRenderer extends GuardianEntityRenderer {
}
@Override
protected void setupTransforms(GuardianEntity entity, MatrixStack stack, float ageInTicks, float rotationYaw, float partialTicks) {
ponyRenderer.manager.setupTransforms(entity, stack, ageInTicks, rotationYaw, partialTicks);
protected void setupTransforms(GuardianEntity entity, MatrixStack stack, float animationProgress, float bodyYaw, float tickDelta, float scale) {
ponyRenderer.manager.setupTransforms(entity, stack, animationProgress, bodyYaw, tickDelta, scale);
}
}

View file

@ -1,19 +1,30 @@
package com.minelittlepony.client.render.entity;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.entity.SkeleponyModel;
import com.minelittlepony.client.render.entity.feature.StrayClothingFeature;
import com.minelittlepony.client.render.entity.feature.ClothingFeature;
import com.minelittlepony.client.render.entity.npc.textures.TextureSupplier;
import net.minecraft.client.render.*;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.LivingEntityRenderer;
import net.minecraft.client.render.entity.feature.FeatureRenderer;
import net.minecraft.client.render.entity.model.SinglePartEntityModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.mob.*;
import net.minecraft.util.Colors;
import net.minecraft.util.Identifier;
public class SkeleponyRenderer<Skeleton extends AbstractSkeletonEntity> extends PonyRenderer<Skeleton, SkeleponyModel<Skeleton>> {
public static final Identifier SKELETON = MineLittlePony.id("textures/entity/skeleton/skeleton_pony.png");
public static final Identifier WITHER = MineLittlePony.id("textures/entity/skeleton/skeleton_wither_pony.png");
public static final Identifier STRAY = MineLittlePony.id("textures/entity/skeleton/stray_pony.png");
public static final Identifier BOGGED = MineLittlePony.id("textures/entity/skeleton/bogged_pony.png");
public static final Identifier SKELETON = new Identifier("minelittlepony", "textures/entity/skeleton/skeleton_pony.png");
public static final Identifier WITHER = new Identifier("minelittlepony", "textures/entity/skeleton/skeleton_wither_pony.png");
public static final Identifier STRAY = new Identifier("minelittlepony", "textures/entity/skeleton/stray_pony.png");
public static final Identifier STRAY_SKELETON_OVERLAY = MineLittlePony.id("textures/entity/skeleton/stray_pony_overlay.png");
public static final Identifier BOGGED_SKELETON_OVERLAY = MineLittlePony.id("textures/entity/skeleton/bogged_pony_overlay.png");
public SkeleponyRenderer(EntityRendererFactory.Context context, Identifier texture, float scale) {
super(context, ModelType.SKELETON, TextureSupplier.of(texture), scale);
@ -24,10 +35,40 @@ public class SkeleponyRenderer<Skeleton extends AbstractSkeletonEntity> extends
}
public static SkeleponyRenderer<StrayEntity> stray(EntityRendererFactory.Context context) {
return PonyRenderer.appendFeature(new SkeleponyRenderer<>(context, STRAY, 1), StrayClothingFeature::new);
return PonyRenderer.appendFeature(new SkeleponyRenderer<StrayEntity>(context, STRAY, 1), ctx -> {
return new ClothingFeature<StrayEntity, SkeleponyModel<StrayEntity>>(ctx, ModelType.SKELETON_CLOTHES, STRAY_SKELETON_OVERLAY);
});
}
public static SkeleponyRenderer<BoggedEntity> bogged(EntityRendererFactory.Context context) {
return PonyRenderer.appendFeature(PonyRenderer.appendFeature(new SkeleponyRenderer<>(context, BOGGED, 1), ctx -> {
return new ClothingFeature<BoggedEntity, SkeleponyModel<BoggedEntity>>(ctx, ModelType.SKELETON_CLOTHES, BOGGED_SKELETON_OVERLAY);
}), BoggedMushroomsFeature::new);
}
public static SkeleponyRenderer<WitherSkeletonEntity> wither(EntityRendererFactory.Context context) {
return new SkeleponyRenderer<>(context, WITHER, 1.2F);
}
public static class BoggedMushroomsFeature extends FeatureRenderer<BoggedEntity, SkeleponyModel<BoggedEntity>> {
public static final Identifier MUSHROOMS = MineLittlePony.id("textures/entity/skeleton/bogged_pony_mushrooms.png");
private final SinglePartEntityModel<BoggedEntity> model = ModelType.BOGGED_MUSHROOMS.createModel();
public BoggedMushroomsFeature(LivingEntityRenderer<BoggedEntity, SkeleponyModel<BoggedEntity>> renderer) {
super(renderer);
}
@Override
public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, BoggedEntity entity, float limbDistance, float limbAngle, float tickDelta, float age, float headYaw, float headPitch) {
if (!entity.isSheared()) {
matrices.push();
getContextModel().transform(BodyPart.HEAD, matrices);
getContextModel().head.rotate(matrices);
VertexConsumer buffer = vertices.getBuffer(model.getLayer(MUSHROOMS));
model.render(matrices, buffer, light, OverlayTexture.DEFAULT_UV, Colors.WHITE);
matrices.pop();
}
}
}
}

View file

@ -13,10 +13,10 @@ import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.model.ModelType;
public class StriderRenderer extends MobEntityRenderer<StriderEntity, EntityModel<StriderEntity>> {
public static final Identifier DRAGON_PONIES = new Identifier("minelittlepony", "textures/entity/strider/pony");
public static final Identifier COLD_DRAGON_PONIES = new Identifier("minelittlepony", "textures/entity/strider/cold_pony");
public static final Identifier DRAGON_PONIES = MineLittlePony.id("textures/entity/strider/pony");
public static final Identifier COLD_DRAGON_PONIES = MineLittlePony.id("textures/entity/strider/cold_pony");
private static final Identifier SADDLE = new Identifier("minelittlepony", "textures/entity/strider/strider_saddle_pony.png");
private static final Identifier SADDLE = MineLittlePony.id("textures/entity/strider/strider_saddle_pony.png");
public StriderRenderer(EntityRendererFactory.Context context) {
super(context, ModelType.STRIDER.createModel(), 0.5F);

View file

@ -11,7 +11,7 @@ import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.entity.ParaspriteModel;
public class VexRenderer extends MobEntityRenderer<VexEntity, ParaspriteModel<VexEntity>> {
public static final Identifier PARASPRITE_PONIES = new Identifier("minelittlepony", "textures/entity/illager/vex_pony");
public static final Identifier PARASPRITE_PONIES = MineLittlePony.id("textures/entity/illager/vex_pony");
public VexRenderer(EntityRendererFactory.Context context) {
super(context, ModelType.VEX.createModel(), 0.3F);

View file

@ -1,5 +1,6 @@
package com.minelittlepony.client.render.entity;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.entity.WitchPonyModel;
import com.minelittlepony.client.render.entity.npc.textures.TextureSupplier;
@ -9,8 +10,7 @@ import net.minecraft.entity.mob.WitchEntity;
import net.minecraft.util.Identifier;
public class WitchRenderer extends PonyRenderer<WitchEntity, WitchPonyModel> {
private static final Identifier WITCH_TEXTURES = new Identifier("minelittlepony", "textures/entity/witch_pony.png");
private static final Identifier WITCH_TEXTURES = MineLittlePony.id("textures/entity/witch_pony.png");
public WitchRenderer(EntityRendererFactory.Context context) {
super(context, ModelType.WITCH, TextureSupplier.of(WITCH_TEXTURES), BASE_MODEL_SCALE);

View file

@ -4,17 +4,17 @@ import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.entity.mob.*;
import net.minecraft.util.Identifier;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.entity.ZomponyModel;
import com.minelittlepony.client.render.entity.npc.textures.TextureSupplier;
public class ZomponyRenderer<Zombie extends HostileEntity> extends PonyRenderer<Zombie, ZomponyModel<Zombie>> {
public static final Identifier ZOMBIE = MineLittlePony.id("textures/entity/zombie/zombie_pony.png");
public static final Identifier HUSK = MineLittlePony.id("textures/entity/zombie/husk_pony.png");
public static final Identifier DROWNED = MineLittlePony.id("textures/entity/zombie/drowned_pony.png");
public static final Identifier ZOMBIE = new Identifier("minelittlepony", "textures/entity/zombie/zombie_pony.png");
public static final Identifier HUSK = new Identifier("minelittlepony", "textures/entity/zombie/husk_pony.png");
public static final Identifier DROWNED = new Identifier("minelittlepony", "textures/entity/zombie/drowned_pony.png");
public static final Identifier DEMON_CHILD = new Identifier("minelittlepony", "textures/entity/zombie/demon_child.png");
public static final Identifier DEMON_CHILD = MineLittlePony.id("textures/entity/zombie/demon_child.png");
public ZomponyRenderer(EntityRendererFactory.Context context, TextureSupplier<Zombie> texture, float scale) {
super(context, ModelType.ZOMBIE, texture, scale);

View file

@ -8,6 +8,7 @@ import net.minecraft.client.render.entity.feature.FeatureRendererContext;
import net.minecraft.client.render.entity.model.BipedEntityModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Colors;
import net.minecraft.util.Identifier;
import com.minelittlepony.api.model.PonyModel;
@ -31,7 +32,7 @@ public abstract class AbstractClothingFeature<T extends LivingEntity, M extends
overlayModel.setAngles(entity, limbDistance, limbAngle, age, headYaw, headPitch);
VertexConsumer vertexConsumer = renderContext.getBuffer(overlayModel.getLayer(getOverlayTexture()));
overlayModel.render(stack, vertexConsumer, lightUv, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1);
overlayModel.render(stack, vertexConsumer, lightUv, OverlayTexture.DEFAULT_UV, Colors.WHITE);
}
protected abstract M getOverlayModel();

Some files were not shown because too many files have changed in this diff Show more