mirror of
https://github.com/MineLittlePony/MineLittlePony.git
synced 2025-03-13 15:10:09 +01:00
Compare commits
167 commits
Author | SHA1 | Date | |
---|---|---|---|
|
57754d8dec | ||
|
ec8f92e151 | ||
|
e21ce62631 | ||
|
c78cf32bd4 | ||
|
4ef2d4ab54 | ||
|
82a89eb1ba | ||
|
8bf3bc38a4 | ||
|
e01580f804 | ||
|
040105c792 | ||
|
18591c0720 | ||
|
31a9a9b0e6 | ||
|
c46cbea872 | ||
|
299a81088c | ||
|
bdc807b102 | ||
|
e149e926d2 | ||
|
4d55f546bb | ||
|
c0e4620355 | ||
|
a3ea4f5982 | ||
|
39f4a7d26d | ||
|
71518d9478 | ||
|
dfa9ce8977 | ||
|
0d97f6b9d4 | ||
|
76211930d5 | ||
|
a40b55e142 | ||
|
aa08f12320 | ||
|
f3cc92dee6 | ||
|
9c8d6d0a86 | ||
|
8ce2fc4e6d | ||
|
7da44b879c | ||
|
f5bfa14bb1 | ||
|
d392b204a3 | ||
|
21a33ebc76 | ||
|
0895e94053 | ||
|
387c9307d0 | ||
|
475e96726e | ||
|
9d65185fcd | ||
|
c365c141ef | ||
|
a94137fda9 | ||
|
34087bd105 | ||
|
cb423186e7 | ||
|
af99765bf2 | ||
|
1faa192f33 | ||
|
b9baba84de | ||
|
814dac6414 | ||
|
667ce0ce4b | ||
|
8832beac32 | ||
|
4de3f3daa2 | ||
|
9064272771 | ||
|
011ceedafe | ||
|
2ed7f91786 | ||
|
d011c11689 | ||
|
060c4abfff | ||
|
9f77999baf | ||
|
fa0c903c0f | ||
|
a7acd2a1c1 | ||
|
101b2bd20c | ||
|
9334836aa7 | ||
|
a69140b761 | ||
|
50ce9f92d1 | ||
|
971f3623cf | ||
|
24e220bb29 | ||
|
f8b21e78ba | ||
|
131bc7cb3f | ||
|
31857e2de0 | ||
|
d3a5c80981 | ||
|
be5382ebad | ||
|
3ae6a48204 | ||
|
4717c9e458 | ||
|
e31ee1c53b | ||
|
509f6477f2 | ||
|
3322e7eaff | ||
|
4904c78e01 | ||
|
8dad366317 | ||
|
b1869c824e | ||
|
72ff58015d | ||
|
76a2e043b7 | ||
|
f54cd5682d | ||
|
26aa16d684 | ||
|
9f280f79eb | ||
|
b538174933 | ||
|
f70ec0996c | ||
|
c2337058f6 | ||
|
1c4fa62676 | ||
|
f5603b05b7 | ||
|
ca728ded81 | ||
|
24a8afc508 | ||
|
6013fa2ad5 | ||
|
2c6c23d05c | ||
|
0f9e865dc4 | ||
|
15274aba2b | ||
|
429cdb644e | ||
|
5cf082d28d | ||
|
dcb8631eb9 | ||
|
f99309cd55 | ||
|
5b9d85d8ea | ||
|
cd25b9e269 | ||
|
b37ffa9860 | ||
|
0e30b2c8dd | ||
|
4b842c9e9a | ||
|
a9b870547a | ||
|
0d226b51f9 | ||
|
8eca1796e1 | ||
|
ff800006f7 | ||
|
ba0ab4149e | ||
|
e45c237e82 | ||
|
627adab1f6 | ||
|
9a59f2444e | ||
|
47adfd5d83 | ||
|
d346f7f60d | ||
|
91918bab0c | ||
|
72004812f2 | ||
|
da790fc984 | ||
|
5a0d3a073d | ||
|
db75aa1600 | ||
|
0096dec423 | ||
|
7c099cd0b1 | ||
|
b4632c7358 | ||
|
4db4a239bd | ||
|
5de74f27f3 | ||
|
4d98160738 | ||
|
0aee3343f8 | ||
|
262a39e1d8 | ||
|
be474aa579 | ||
|
ab84884677 | ||
|
8042e83e8a | ||
|
c2380013a9 | ||
|
528a527e36 | ||
|
8d24807ae0 | ||
|
d6f8df66e8 | ||
|
23d0bd131b | ||
|
385d09e0f5 | ||
|
891aa73254 | ||
|
3fd07b4874 | ||
|
b6a6adbbf6 | ||
|
19f4a4781e | ||
|
5a794ed611 | ||
|
bee3060697 | ||
|
3aabd80e5b | ||
|
b38c8530f8 | ||
|
ee536cfe6a | ||
|
c7c5e588c2 | ||
|
43c6375e43 | ||
|
3f76f6057e | ||
|
73dae14934 | ||
|
f433f7d66f | ||
|
7f9bdcbde5 | ||
|
471b2f01a0 | ||
|
b842f3d4df | ||
|
ef83ca820f | ||
|
a1d15e4da2 | ||
|
5f7fe72d28 | ||
|
031628d0ce | ||
|
b7a15cda83 | ||
|
dad8f83718 | ||
|
f1b6bb23a7 | ||
|
cb232cc145 | ||
|
437d361170 | ||
|
2e5fec3106 | ||
|
d97403fd26 | ||
|
77584ea2fa | ||
|
0881cf6e5b | ||
|
e55b17f3a7 | ||
|
d438d0f5bb | ||
|
fb3973a3f1 | ||
|
d9769e32ee | ||
|
32d1ffbe7c | ||
|
b2fe56334f |
242 changed files with 3757 additions and 3680 deletions
|
@ -1,10 +1,12 @@
|
||||||
# Mine Little Pony
|
# Mine Little Pony
|
||||||
|
|
||||||
[](https://img.shields.io/github/v/tag/MineLittlePony/MineLittlePony)
|
[](https://github.com/MineLittlePony/MineLittlePony/releases/latest)
|
||||||
[](https://github.com/MineLittlePony/MineLittlePony/actions/workflows/gradle-build.yml)
|
[](https://github.com/MineLittlePony/MineLittlePony/actions/workflows/gradle-build.yml)
|
||||||

|

|
||||||
|
[](https://modrinth.com/mod/mine-little-pony)
|
||||||
[](https://discord.gg/HbJSFyu)
|
[](https://discord.gg/HbJSFyu)
|
||||||

|

|
||||||
|
[](https://crowdin.com/project/mine-little-pony)
|
||||||

|

|
||||||
|
|
||||||
Turns players and mobs into ponies.
|
Turns players and mobs into ponies.
|
||||||
|
|
34
build.gradle
34
build.gradle
|
@ -1,16 +1,15 @@
|
||||||
buildscript {
|
buildscript {
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.github.dexman545:Outlet:1.3.10'
|
classpath 'com.github.dexman545:Outlet:1.6.1'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
plugins {
|
plugins {
|
||||||
id 'java-library'
|
id 'fabric-loom' version '1.5-SNAPSHOT'
|
||||||
id 'fabric-loom' version '0.12-SNAPSHOT'
|
|
||||||
id 'maven-publish'
|
id 'maven-publish'
|
||||||
id 'com.modrinth.minotaur' version '2.+'
|
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 {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
|
@ -38,18 +37,9 @@ reckon {
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
maven {
|
maven { name 'modmenu'; url 'https://maven.terraformersmc.com/releases' }
|
||||||
name = 'modmenu'
|
maven { name 'minelp'; url 'https://repo.minelittlepony-mod.com/maven/snapshot' }
|
||||||
url = 'https://maven.terraformersmc.com/releases'
|
maven { name 'minelp-release'; url 'https://repo.minelittlepony-mod.com/maven/release' }
|
||||||
}
|
|
||||||
maven {
|
|
||||||
name = 'minelp'
|
|
||||||
url = 'https://repo.minelittlepony-mod.com/maven/snapshot'
|
|
||||||
}
|
|
||||||
maven {
|
|
||||||
name = 'minelp-release'
|
|
||||||
url = 'https://repo.minelittlepony-mod.com/maven/release'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -69,7 +59,7 @@ dependencies {
|
||||||
include "com.minelittlepony:mson:${project.mson_version}"
|
include "com.minelittlepony:mson:${project.mson_version}"
|
||||||
|
|
||||||
modImplementation "com.minelittlepony:hdskins:${project.hd_skins_version}"
|
modImplementation "com.minelittlepony:hdskins:${project.hd_skins_version}"
|
||||||
modCompileOnly("com.terraformersmc:modmenu:${project.modmenu_version}")
|
modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}"
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -93,7 +83,12 @@ processResources {
|
||||||
inputs.property "version", project.version.toString()
|
inputs.property "version", project.version.toString()
|
||||||
|
|
||||||
filesMatching("fabric.mod.json") {
|
filesMatching("fabric.mod.json") {
|
||||||
expand "version": project.version.toString()
|
expand "version": project.version.toString(),
|
||||||
|
"minecraftVersion": project.minecraft_version_range,
|
||||||
|
"loaderVersion": ">=${project.loader_version}",
|
||||||
|
"fabricVersion": ">=${project.fabric_version}",
|
||||||
|
"kirinVersion": ">=${project.kirin_version}",
|
||||||
|
"msonVersion": ">=${project.mson_version}"
|
||||||
}
|
}
|
||||||
|
|
||||||
from 'LICENSE'
|
from 'LICENSE'
|
||||||
|
@ -122,6 +117,7 @@ modrinth {
|
||||||
versionNumber = version.toString()
|
versionNumber = version.toString()
|
||||||
versionName = archivesBaseName + '-' + version
|
versionName = archivesBaseName + '-' + version
|
||||||
changelog = "[Changelog](https://github.com/MineLittlePony/MineLittlePony/releases/tag/${version.toString()})"
|
changelog = "[Changelog](https://github.com/MineLittlePony/MineLittlePony/releases/tag/${version.toString()})"
|
||||||
|
loaders = ['fabric', 'quilt']
|
||||||
uploadFile = remapJar
|
uploadFile = remapJar
|
||||||
outlet.mcVersions().each{ver ->
|
outlet.mcVersions().each{ver ->
|
||||||
gameVersions.add ver
|
gameVersions.add ver
|
||||||
|
|
3
crowdin.yml
Normal file
3
crowdin.yml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
files:
|
||||||
|
- source: src/main/resources/assets/minelittlepony/lang/en_us.json
|
||||||
|
translation: /%original_path%/%locale_with_underscore%.%file_extension%
|
|
@ -3,10 +3,10 @@ org.gradle.daemon=false
|
||||||
|
|
||||||
# Fabric Properties
|
# Fabric Properties
|
||||||
# check these on https://fabricmc.net/develop
|
# check these on https://fabricmc.net/develop
|
||||||
minecraft_version=1.19.4
|
minecraft_version=1.20.2
|
||||||
yarn_mappings=1.19.4+build.1
|
yarn_mappings=1.20.2+build.4
|
||||||
loader_version=0.14.17
|
loader_version=0.15.1
|
||||||
fabric_version=0.76.0+1.19.4
|
fabric_version=0.91.1+1.20.2
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
group=com.minelittlepony
|
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.
|
description=Mine Little Pony turns players and mobs into ponies. Press F9 ingame to access settings.
|
||||||
|
|
||||||
# Publishing
|
# Publishing
|
||||||
minecraft_version_range=>=1.19.4
|
minecraft_version_range=>=1.20.2
|
||||||
modrinth_loader_type=fabric
|
modrinth_loader_type=fabric
|
||||||
modrinth_project_id=JBjInUXM
|
modrinth_project_id=JBjInUXM
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
modmenu_version=6.1.0-rc.4
|
modmenu_version=8.0.0
|
||||||
kirin_version=1.14.0
|
kirin_version=1.16.1+1.20.2
|
||||||
hd_skins_version=6.8.0
|
hd_skins_version=6.12.4+1.20.2
|
||||||
mson_version=1.8.0
|
mson_version=1.9.3+1.20.2
|
||||||
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,5 +1,5 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven {
|
maven { name 'Fabric'; url 'https://maven.fabricmc.net/' }
|
||||||
name = 'Fabric'
|
maven { name 'Jitpack'; url 'https://jitpack.io' }
|
||||||
url = 'https://maven.fabricmc.net/'
|
|
||||||
}
|
|
||||||
maven {
|
|
||||||
name = 'Jitpack'
|
|
||||||
url = 'https://jitpack.io'
|
|
||||||
}
|
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
skins
2
skins
|
@ -1 +1 @@
|
||||||
Subproject commit 357cd1775f9bbf1620ca97c5f7e5b59d0e9ec4c4
|
Subproject commit 45dfe1101b4506077b3d3f2246b08c9b485735eb
|
|
@ -2,8 +2,8 @@ package com.minelittlepony.api.config;
|
||||||
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.meta.Race;
|
import com.minelittlepony.api.pony.meta.*;
|
||||||
import com.minelittlepony.api.pony.meta.Sizes;
|
import com.minelittlepony.common.client.gui.VisibilityMode;
|
||||||
import com.minelittlepony.common.util.GamePaths;
|
import com.minelittlepony.common.util.GamePaths;
|
||||||
import com.minelittlepony.common.util.settings.*;
|
import com.minelittlepony.common.util.settings.*;
|
||||||
|
|
||||||
|
@ -52,8 +52,15 @@ public class PonyConfig extends Config {
|
||||||
public final Setting<Boolean> frustrum = value("settings", "frustrum", true)
|
public final Setting<Boolean> frustrum = value("settings", "frustrum", true)
|
||||||
.addComment("Adjust camera intersection checks to properly cull entities when they're not in view.")
|
.addComment("Adjust camera intersection checks to properly cull entities when they're not in view.")
|
||||||
.addComment("Helps to prevent entities from vanishing when they're in long stacks");
|
.addComment("Helps to prevent entities from vanishing when they're in long stacks");
|
||||||
|
public final Setting<Boolean> horsieMode = value("settings", "horsieMode", false)
|
||||||
|
.addComment("Enables the alternative horsey models from the April Fools 2023 update");
|
||||||
|
public final Setting<Boolean> mixedHumanSkins = value("settings", "dualSkinMode", false)
|
||||||
|
.addComment("(Experimental) Use priority to decide between displaying the HDSkins' texture, or vanilla mojang server skin")
|
||||||
|
.addComment("(Experimental) eg. On pony level = HUMANS")
|
||||||
|
.addComment("(Experimental) Any time both skins resolve to the same race (eg. on pony-level HUMANS, or if both are ponies)")
|
||||||
|
.addComment("(Experimental) the skin with the highest priority will be chosen.");;
|
||||||
|
|
||||||
public final Setting<Sizes> sizeOverride = value("debug", "sizeOverride", Sizes.UNSET)
|
public final Setting<SizePreset> sizeOverride = value("debug", "sizeOverride", SizePreset.UNSET)
|
||||||
.addComment("Overrides pony sizes")
|
.addComment("Overrides pony sizes")
|
||||||
.addComment("Possible values: TALL, BULKY, LANKY, NORMAL, YEARLING, FOAL, UNSET (default)");
|
.addComment("Possible values: TALL, BULKY, LANKY, NORMAL, YEARLING, FOAL, UNSET (default)");
|
||||||
|
|
||||||
|
@ -67,10 +74,17 @@ public class PonyConfig extends Config {
|
||||||
|
|
||||||
public final Setting<Boolean> flappyElytras = value("customisation", "flappyElytras", false)
|
public final Setting<Boolean> flappyElytras = value("customisation", "flappyElytras", false)
|
||||||
.addComment("Pegasi will use their wings to fly even when they're wearing an elytra");
|
.addComment("Pegasi will use their wings to fly even when they're wearing an elytra");
|
||||||
|
|
||||||
public final Setting<Boolean> noFun = value("customisation", "noFun", false)
|
public final Setting<Boolean> noFun = value("customisation", "noFun", false)
|
||||||
.addComment("Disables certain easter eggs and secrets (party pooper)")
|
.addComment("Disables certain easter eggs and secrets (party pooper)")
|
||||||
.addComment("Turning this off may help with compatibility in some cases");
|
.addComment("Turning this off may help with compatibility in some cases");
|
||||||
|
|
||||||
|
public final Setting<VisibilityMode> horseButton = value("horseButton", VisibilityMode.AUTO)
|
||||||
|
.addComment("Whether to show the mine little pony settings button on the main menu")
|
||||||
|
.addComment("AUTO (default) - only show when HDSkins is not installed")
|
||||||
|
.addComment("ON - always show")
|
||||||
|
.addComment("OFF - never show");
|
||||||
|
|
||||||
public PonyConfig(Path path) {
|
public PonyConfig(Path path) {
|
||||||
super(HEIRARCHICAL_JSON_ADAPTER, path);
|
super(HEIRARCHICAL_JSON_ADAPTER, path);
|
||||||
instance = this;
|
instance = this;
|
||||||
|
@ -129,4 +143,18 @@ public class PonyConfig extends Config {
|
||||||
|
|
||||||
return race;
|
return race;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Size getEffectiveSize(Size size) {
|
||||||
|
SizePreset sz = instance.sizeOverride.get();
|
||||||
|
|
||||||
|
if (sz != SizePreset.UNSET) {
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == SizePreset.UNSET || !instance.sizes.get()) {
|
||||||
|
return SizePreset.NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.minelittlepony.api.pony.network.fabric;
|
package com.minelittlepony.api.events;
|
||||||
|
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.Environment;
|
import net.fabricmc.api.Environment;
|
||||||
|
@ -8,62 +8,56 @@ import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.IPony;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import com.minelittlepony.api.pony.network.MsgPonyData;
|
import org.apache.logging.log4j.Logger;
|
||||||
import com.minelittlepony.client.MineLittlePony;
|
|
||||||
|
import com.minelittlepony.api.pony.PonyData;
|
||||||
|
|
||||||
@Environment(EnvType.CLIENT)
|
@Environment(EnvType.CLIENT)
|
||||||
public class Channel {
|
public class Channel {
|
||||||
private static final Identifier CLIENT_PONY_DATA = new Identifier("minelittlepony", "pony_data");
|
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 Identifier REQUEST_PONY_DATA = new Identifier("minelittlepony", "request_pony_data");
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger("MineLittlePony:Networking");
|
||||||
|
|
||||||
private static boolean registered;
|
private static boolean registered;
|
||||||
|
|
||||||
public static void bootstrap() {
|
public static void bootstrap() {
|
||||||
ClientLoginConnectionEvents.INIT.register((handler, client) -> {
|
ClientLoginConnectionEvents.INIT.register((handler, client) -> {
|
||||||
registered = false;
|
registered = false;
|
||||||
MineLittlePony.logger.info("Resetting registered flag");
|
|
||||||
});
|
});
|
||||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||||
MineLittlePony.logger.info("Sending consent packet to " + handler.getPlayer().getName().getString());
|
LOGGER.info("Sending consent packet to " + handler.getPlayer().getName().getString());
|
||||||
|
|
||||||
sender.sendPacket(REQUEST_PONY_DATA, PacketByteBufs.empty());
|
sender.sendPacket(REQUEST_PONY_DATA, PacketByteBufs.empty());
|
||||||
});
|
});
|
||||||
|
|
||||||
ClientPlayNetworking.registerGlobalReceiver(REQUEST_PONY_DATA, (client, handler, ignored, sender) -> {
|
ClientPlayNetworking.registerGlobalReceiver(REQUEST_PONY_DATA, (client, handler, ignored, sender) -> {
|
||||||
if (client.player != null) {
|
|
||||||
IPony pony = IPony.getManager().getPony(client.player);
|
|
||||||
registered = true;
|
registered = true;
|
||||||
MineLittlePony.logger.info("Server has just consented");
|
LOGGER.info("Server has just consented");
|
||||||
|
|
||||||
sender.sendPacket(CLIENT_PONY_DATA, new MsgPonyData(pony.metadata(), pony.defaulted()).toBuffer(PacketByteBufs.create()));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
ServerPlayNetworking.registerGlobalReceiver(CLIENT_PONY_DATA, (server, player, ignore, buffer, ignore2) -> {
|
ServerPlayNetworking.registerGlobalReceiver(CLIENT_PONY_DATA, (server, player, ignore, buffer, ignore2) -> {
|
||||||
MsgPonyData packet = new MsgPonyData(buffer);
|
PonyData packet = MsgPonyData.read(buffer);
|
||||||
server.execute(() -> {
|
server.execute(() -> {
|
||||||
PonyDataCallback.EVENT.invoker().onPonyDataAvailable(player, packet, packet.isNoSkin(), EnvType.SERVER);
|
PonyDataCallback.EVENT.invoker().onPonyDataAvailable(player, packet, EnvType.SERVER);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void broadcastPonyData(MsgPonyData packet) {
|
public static boolean isRegistered() {
|
||||||
|
return registered;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean broadcastPonyData(PonyData packet) {
|
||||||
|
if (!isRegistered()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (FabricLoader.getInstance().getEnvironmentType() != EnvType.CLIENT) {
|
if (FabricLoader.getInstance().getEnvironmentType() != EnvType.CLIENT) {
|
||||||
throw new RuntimeException("Client packet send called by the server");
|
throw new RuntimeException("Client packet send called by the server");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!registered) {
|
ClientPlayNetworking.send(CLIENT_PONY_DATA, MsgPonyData.write(packet, PacketByteBufs.create()));
|
||||||
if (MinecraftClient.getInstance().isInSingleplayer() || MinecraftClient.getInstance().isIntegratedServerRunning()) {
|
return true;
|
||||||
MineLittlePony.logger.info("Sending pony skin data over as we are either in single-player or lan");
|
|
||||||
} else {
|
|
||||||
MineLittlePony.logger.info("Skipping network packet as the server has not consented");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientPlayNetworking.send(CLIENT_PONY_DATA, packet.toBuffer(PacketByteBufs.create()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
73
src/main/java/com/minelittlepony/api/events/MsgPonyData.java
Normal file
73
src/main/java/com/minelittlepony/api/events/MsgPonyData.java
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
package com.minelittlepony.api.events;
|
||||||
|
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
|
||||||
|
import com.minelittlepony.api.pony.PonyData;
|
||||||
|
import com.minelittlepony.api.pony.meta.*;
|
||||||
|
|
||||||
|
public class MsgPonyData {
|
||||||
|
private static final short API_IDENTIFIER = (short) 0xABCD;
|
||||||
|
// API version - increment this number before any time any data is added/removed/moved in the data stream
|
||||||
|
private static final byte API_VERSION = 3;
|
||||||
|
|
||||||
|
public static PonyData read(PacketByteBuf buffer) {
|
||||||
|
short data = buffer.readShort();
|
||||||
|
if (data != API_IDENTIFIER || buffer.readByte() != API_VERSION) {
|
||||||
|
return PonyData.NULL;
|
||||||
|
}
|
||||||
|
return new PonyData(
|
||||||
|
buffer.readEnumConstant(Race.class),
|
||||||
|
buffer.readEnumConstant(TailLength.class),
|
||||||
|
buffer.readEnumConstant(TailShape.class),
|
||||||
|
buffer.readEnumConstant(Gender.class),
|
||||||
|
new MsgSize(buffer),
|
||||||
|
buffer.readInt(),
|
||||||
|
buffer.readBoolean(),
|
||||||
|
buffer.readVarInt(),
|
||||||
|
Flags.read(Wearable.NONE, buffer)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PacketByteBuf write(PonyData data, PacketByteBuf buffer) {
|
||||||
|
buffer.writeShort(API_IDENTIFIER);
|
||||||
|
buffer.writeByte(API_VERSION);
|
||||||
|
buffer.writeEnumConstant(data.race());
|
||||||
|
buffer.writeEnumConstant(data.tailLength());
|
||||||
|
buffer.writeEnumConstant(data.tailShape());
|
||||||
|
buffer.writeEnumConstant(data.gender());
|
||||||
|
write(data.size(), buffer);
|
||||||
|
buffer.writeInt(data.glowColor());
|
||||||
|
buffer.writeBoolean(data.noSkin());
|
||||||
|
buffer.writeVarInt(data.priority());
|
||||||
|
data.gear().write(buffer);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void write(Size size, PacketByteBuf buffer) {
|
||||||
|
buffer.writeInt(size.ordinal());
|
||||||
|
buffer.writeString(size.name());
|
||||||
|
buffer.writeFloat(size.shadowSize());
|
||||||
|
buffer.writeFloat(size.scaleFactor());
|
||||||
|
buffer.writeFloat(size.eyeHeightFactor());
|
||||||
|
buffer.writeFloat(size.eyeDistanceFactor());
|
||||||
|
buffer.writeFloat(size.colorCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
private record MsgSize (
|
||||||
|
int ordinal,
|
||||||
|
String name,
|
||||||
|
float shadowSize,
|
||||||
|
float scaleFactor,
|
||||||
|
float eyeHeightFactor,
|
||||||
|
float eyeDistanceFactor,
|
||||||
|
int colorCode) implements Size {
|
||||||
|
MsgSize(PacketByteBuf buffer) {
|
||||||
|
this(buffer.readInt(), buffer.readString(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,23 +1,20 @@
|
||||||
package com.minelittlepony.api.pony.network.fabric;
|
package com.minelittlepony.api.events;
|
||||||
|
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.fabric.api.event.Event;
|
import net.fabricmc.fabric.api.event.Event;
|
||||||
import net.fabricmc.fabric.api.event.EventFactory;
|
import net.fabricmc.fabric.api.event.EventFactory;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.IPonyData;
|
import com.minelittlepony.api.pony.PonyData;
|
||||||
import com.minelittlepony.client.MineLittlePony;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback triggered on the server when receiving pony data from a client.
|
* Callback triggered on the server when receiving pony data from a client.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public interface PonyDataCallback {
|
public interface PonyDataCallback {
|
||||||
|
Event<PonyDataCallback> EVENT = EventFactory.createArrayBacked(PonyDataCallback.class, listeners -> (sender, data, env) -> {
|
||||||
Event<PonyDataCallback> EVENT = EventFactory.createArrayBacked(PonyDataCallback.class, listeners -> (sender, data, noSkin, env) -> {
|
|
||||||
MineLittlePony.logger.info("Got pony data on the " + env + " from " + sender.getUuidAsString() + " with " + (noSkin ? "un" : "") + "set skin and he is a " + data.getRace() + "!");
|
|
||||||
for (PonyDataCallback event : listeners) {
|
for (PonyDataCallback event : listeners) {
|
||||||
event.onPonyDataAvailable(sender, data, noSkin, env);
|
event.onPonyDataAvailable(sender, data, env);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -25,8 +22,7 @@ public interface PonyDataCallback {
|
||||||
* Called when pony data is received.
|
* Called when pony data is received.
|
||||||
* @param sender The player who sent the data - this is the owner of the skin/pony data.
|
* @param sender The player who sent the data - this is the owner of the skin/pony data.
|
||||||
* @param data The skin/pony data
|
* @param data The skin/pony data
|
||||||
* @param noSkin Whether the data is for a player with a default/unset custom skin.
|
|
||||||
* @param env The environment. Whether this call is coming from the client or server. Clients may get two calls, one for both.
|
* @param env The environment. Whether this call is coming from the client or server. Clients may get two calls, one for both.
|
||||||
*/
|
*/
|
||||||
void onPonyDataAvailable(PlayerEntity sender, IPonyData data, boolean noSkin, EnvType env);
|
void onPonyDataAvailable(PlayerEntity sender, PonyData data, EnvType env);
|
||||||
}
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
package com.minelittlepony.api.model.fabric;
|
package com.minelittlepony.api.events;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.event.Event;
|
import net.fabricmc.fabric.api.event.Event;
|
||||||
import net.fabricmc.fabric.api.event.EventFactory;
|
import net.fabricmc.fabric.api.event.EventFactory;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.IModel;
|
import com.minelittlepony.api.model.PonyModel;
|
||||||
import com.minelittlepony.api.model.ModelAttributes;
|
import com.minelittlepony.api.model.ModelAttributes;
|
||||||
|
|
||||||
public interface PonyModelPrepareCallback {
|
public interface PonyModelPrepareCallback {
|
||||||
|
@ -15,5 +15,5 @@ public interface PonyModelPrepareCallback {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
void onPonyModelPrepared(Entity entity, IModel model, ModelAttributes.Mode mode);
|
void onPonyModelPrepared(Entity entity, PonyModel<?> model, ModelAttributes.Mode mode);
|
||||||
}
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.minelittlepony.api.model;
|
||||||
|
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
|
||||||
|
public interface HornedPonyModel<T extends LivingEntity> extends PonyModel<T> {
|
||||||
|
/**
|
||||||
|
* Returns true if this model is being applied to a race that can use magic.
|
||||||
|
*/
|
||||||
|
default boolean hasMagic() {
|
||||||
|
return getRace().hasHorn() && getAttributes().metadata.glowColor() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this model is currently using magic (horn is lit).
|
||||||
|
*/
|
||||||
|
boolean isCasting();
|
||||||
|
}
|
|
@ -1,11 +0,0 @@
|
||||||
package com.minelittlepony.api.model;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for models that have a head.
|
|
||||||
*/
|
|
||||||
public interface ICapitated<T> {
|
|
||||||
/**
|
|
||||||
* Gets the head of this capitated object.
|
|
||||||
*/
|
|
||||||
T getHead();
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
package com.minelittlepony.api.model;
|
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.IPonyData;
|
|
||||||
|
|
||||||
public interface IModelWrapper {
|
|
||||||
/**
|
|
||||||
* Updates metadata values to this wrapper's contained models.
|
|
||||||
*/
|
|
||||||
IModelWrapper applyMetadata(IPonyData meta);
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
package com.minelittlepony.api.model;
|
|
||||||
|
|
||||||
public interface IUnicorn extends IModel {
|
|
||||||
/**
|
|
||||||
* Returns true if this model is being applied to a race that can use magic.
|
|
||||||
*/
|
|
||||||
default boolean hasMagic() {
|
|
||||||
return getRace().hasHorn() && getMagicColor() != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if this model has an visible horns.
|
|
||||||
*/
|
|
||||||
default boolean hasHorn() {
|
|
||||||
return getRace().hasHorn();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if this model is currently using magic (horn is lit).
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
boolean isCasting();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the preferred magic color for this mode.
|
|
||||||
*/
|
|
||||||
default int getMagicColor() {
|
|
||||||
return getMetadata().getGlowColor();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.minelittlepony.client.model;
|
package com.minelittlepony.api.model;
|
||||||
|
|
||||||
import net.minecraft.client.model.ModelPart;
|
import net.minecraft.client.model.ModelPart;
|
||||||
import net.minecraft.util.Arm;
|
import net.minecraft.util.Arm;
|
||||||
|
@ -6,10 +6,7 @@ import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
import com.minelittlepony.mson.util.PartUtil;
|
import com.minelittlepony.mson.util.PartUtil;
|
||||||
|
|
||||||
/**
|
public final class MobPosingHelper {
|
||||||
* Common interface for all undead enemies.
|
|
||||||
*/
|
|
||||||
public interface IMobModel {
|
|
||||||
/**
|
/**
|
||||||
* Rotates the provided arm to the correct orientation for holding an item.
|
* Rotates the provided arm to the correct orientation for holding an item.
|
||||||
*
|
*
|
||||||
|
@ -18,7 +15,7 @@ public interface IMobModel {
|
||||||
* @param swingProgress How far we are through the current swing
|
* @param swingProgress How far we are through the current swing
|
||||||
* @param ticks Render partial ticks
|
* @param ticks Render partial ticks
|
||||||
*/
|
*/
|
||||||
static void rotateArmHolding(ModelPart arm, float direction, float swingProgress, float ticks) {
|
public static void rotateArmHolding(ModelPart arm, float direction, float swingProgress, float ticks) {
|
||||||
float swing = MathHelper.sin(swingProgress * MathHelper.PI);
|
float swing = MathHelper.sin(swingProgress * MathHelper.PI);
|
||||||
float roll = MathHelper.sin((1 - (1 - swingProgress) * (1 - swingProgress)) * MathHelper.PI);
|
float roll = MathHelper.sin((1 - (1 - swingProgress) * (1 - swingProgress)) * MathHelper.PI);
|
||||||
|
|
||||||
|
@ -33,20 +30,26 @@ public interface IMobModel {
|
||||||
arm.roll = cos;
|
arm.roll = cos;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rotateUndeadArms(ClientPonyModel<?> model, float move, float ticks) {
|
public static void rotateUndeadArms(PonyModel<?> model, float move, float ticks) {
|
||||||
ModelPart leftArm = model.getArm(Arm.LEFT);
|
ModelPart leftArm = model.getForeLeg(Arm.LEFT);
|
||||||
ModelPart rightArm = model.getArm(Arm.RIGHT);
|
ModelPart rightArm = model.getForeLeg(Arm.RIGHT);
|
||||||
|
|
||||||
if (islookAngleRight(move)) {
|
if (islookAngleRight(move)) {
|
||||||
IMobModel.rotateArmHolding(rightArm, 1, model.getSwingAmount(), ticks);
|
rotateArmHolding(rightArm, 1, model.getSwingAmount(), ticks);
|
||||||
|
if (model.getAttributes().isSitting) {
|
||||||
|
rightArm.pitch += 0.6F;
|
||||||
|
}
|
||||||
PartUtil.shift(rightArm, 0.5F, 1.5F, 3);
|
PartUtil.shift(rightArm, 0.5F, 1.5F, 3);
|
||||||
} else {
|
} else {
|
||||||
IMobModel.rotateArmHolding(leftArm, -1, model.getSwingAmount(), ticks);
|
rotateArmHolding(leftArm, -1, model.getSwingAmount(), ticks);
|
||||||
|
if (model.getAttributes().isSitting) {
|
||||||
|
leftArm.pitch += 0.6F;
|
||||||
|
}
|
||||||
PartUtil.shift(leftArm, -0.5F, 1.5F, 3);
|
PartUtil.shift(leftArm, -0.5F, 1.5F, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean islookAngleRight(float move) {
|
public static boolean islookAngleRight(float move) {
|
||||||
return MathHelper.sin(move / 20) < 0;
|
return MathHelper.sin(move / 20) < 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,7 @@
|
||||||
package com.minelittlepony.api.model;
|
package com.minelittlepony.api.model;
|
||||||
|
|
||||||
|
import com.minelittlepony.api.config.PonyConfig;
|
||||||
import com.minelittlepony.api.pony.*;
|
import com.minelittlepony.api.pony.*;
|
||||||
import com.minelittlepony.client.IPreviewModel;
|
|
||||||
import com.minelittlepony.client.SkinsProxy;
|
|
||||||
import com.minelittlepony.client.pony.PonyData;
|
|
||||||
import com.minelittlepony.common.util.animation.Interpolator;
|
import com.minelittlepony.common.util.animation.Interpolator;
|
||||||
import com.minelittlepony.util.MathUtil;
|
import com.minelittlepony.util.MathUtil;
|
||||||
|
|
||||||
|
@ -11,8 +9,9 @@ import java.util.*;
|
||||||
|
|
||||||
import net.minecraft.client.render.entity.model.BipedEntityModel.ArmPose;
|
import net.minecraft.client.render.entity.model.BipedEntityModel.ArmPose;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.util.Arm;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.*;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
@ -21,6 +20,11 @@ public class ModelAttributes {
|
||||||
* True if the model is sleeping in a bed.
|
* True if the model is sleeping in a bed.
|
||||||
*/
|
*/
|
||||||
public boolean isSleeping;
|
public boolean isSleeping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the model is lying down comfortably
|
||||||
|
*/
|
||||||
|
public boolean isLyingDown;
|
||||||
/**
|
/**
|
||||||
* True if the model is flying like a pegasus.
|
* True if the model is flying like a pegasus.
|
||||||
*/
|
*/
|
||||||
|
@ -64,6 +68,10 @@ public class ModelAttributes {
|
||||||
* Flag indicating that this model is performing a rainboom (flight).
|
* Flag indicating that this model is performing a rainboom (flight).
|
||||||
*/
|
*/
|
||||||
public boolean isGoingFast;
|
public boolean isGoingFast;
|
||||||
|
/**
|
||||||
|
* Flag indicating that this model should mimic the vanilla horse models.
|
||||||
|
*/
|
||||||
|
public boolean isHorsey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vertical pitch whilst flying.
|
* Vertical pitch whilst flying.
|
||||||
|
@ -105,16 +113,21 @@ public class ModelAttributes {
|
||||||
/**
|
/**
|
||||||
* Contains the skin metadata associated with this model.
|
* Contains the skin metadata associated with this model.
|
||||||
*/
|
*/
|
||||||
public IPonyData metadata = PonyData.NULL;
|
public PonyData metadata = PonyData.NULL;
|
||||||
|
|
||||||
|
public Arm mainArm;
|
||||||
|
public Hand activeHand;
|
||||||
|
public ItemStack heldStack = ItemStack.EMPTY;
|
||||||
|
public int itemUseTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks flying and speed conditions and sets rainboom to true if we're a species with wings and is going faaast.
|
* Checks flying and speed conditions and sets rainboom to true if we're a species with wings and is going faaast.
|
||||||
*/
|
*/
|
||||||
public void checkRainboom(LivingEntity entity, boolean hasWings, float ticks) {
|
public void checkRainboom(LivingEntity entity, PonyModel<?> model, float ticks) {
|
||||||
Vec3d motion = entity.getVelocity();
|
Vec3d motion = entity.getVelocity();
|
||||||
double zMotion = Math.sqrt(motion.x * motion.x + motion.z * motion.z);
|
double zMotion = Math.sqrt(motion.x * motion.x + motion.z * motion.z);
|
||||||
|
|
||||||
isGoingFast = (isFlying && hasWings) || isGliding;
|
isGoingFast = (isFlying && model instanceof WingedPonyModel) || isGliding;
|
||||||
isGoingFast &= zMotion > 0.4F;
|
isGoingFast &= zMotion > 0.4F;
|
||||||
isGoingFast |= entity.isUsingRiptide();
|
isGoingFast |= entity.isUsingRiptide();
|
||||||
isGoingFast |= entity.isFallFlying();
|
isGoingFast |= entity.isFallFlying();
|
||||||
|
@ -129,31 +142,41 @@ public class ModelAttributes {
|
||||||
return (MathHelper.sin(ticks * 0.136f) / 2) + MathUtil.Angles._270_DEG;
|
return (MathHelper.sin(ticks * 0.136f) / 2) + MathUtil.Angles._270_DEG;
|
||||||
}
|
}
|
||||||
if (isFlying) {
|
if (isFlying) {
|
||||||
return MathHelper.sin(ticks * 0.536f) + IPegasus.WINGS_FULL_SPREAD_ANGLE;
|
return MathHelper.sin(ticks * 0.536f) + WingedPonyModel.WINGS_FULL_SPREAD_ANGLE;
|
||||||
}
|
}
|
||||||
return IPegasus.WINGS_RAISED_ANGLE;
|
return WingedPonyModel.WINGS_RAISED_ANGLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateLivingState(LivingEntity entity, IPony pony, Mode mode) {
|
public void updateLivingState(LivingEntity entity, Pony pony, Mode mode) {
|
||||||
visualHeight = entity.getHeight() + 0.125F;
|
visualHeight = entity.getHeight() + 0.125F;
|
||||||
isSitting = PonyPosture.isSitting(entity);
|
isSitting = PonyPosture.isSitting(entity);
|
||||||
isCrouching = !isSitting && mode == Mode.THIRD_PERSON && PonyPosture.isCrouching(pony, entity);
|
isSleeping = entity.isAlive() && entity.isSleeping();;
|
||||||
isSleeping = entity.isAlive() && entity.isSleeping();
|
isLyingDown = isSleeping;
|
||||||
isFlying = mode == Mode.THIRD_PERSON && PonyPosture.isFlying(entity);
|
if (entity instanceof PlayerEntity) {
|
||||||
|
boolean moving = entity.getVelocity().multiply(1, 0, 1).length() == 0 && entity.isSneaking();
|
||||||
|
isLyingDown |= getMainInterpolator().interpolate("lyingDown", moving ? 10 : 0, 200) >= 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
isCrouching = !isLyingDown && !isSitting && mode == Mode.THIRD_PERSON && PonyPosture.isCrouching(pony, entity);
|
||||||
|
isFlying = !isLyingDown && mode == Mode.THIRD_PERSON && PonyPosture.isFlying(entity);
|
||||||
isGliding = entity.isFallFlying();
|
isGliding = entity.isFallFlying();
|
||||||
isSwimming = mode == Mode.THIRD_PERSON && PonyPosture.isSwimming(entity);
|
isSwimming = mode == Mode.THIRD_PERSON && PonyPosture.isSwimming(entity);
|
||||||
isSwimmingRotated = isSwimming;
|
isSwimmingRotated = isSwimming;
|
||||||
isRiptide = entity.isUsingRiptide();
|
isRiptide = entity.isUsingRiptide();
|
||||||
isRidingInteractive = PonyPosture.isRidingAPony(entity);
|
isRidingInteractive = PonyPosture.isRidingAPony(entity);
|
||||||
if (!(entity instanceof IPreviewModel)) {
|
if (!(entity instanceof PreviewModel)) {
|
||||||
interpolatorId = entity.getUuid();
|
interpolatorId = entity.getUuid();
|
||||||
}
|
}
|
||||||
isLeftHanded = entity.getMainArm() == Arm.LEFT;
|
isLeftHanded = entity.getMainArm() == Arm.LEFT;
|
||||||
|
isHorsey = PonyConfig.getInstance().horsieMode.get();
|
||||||
featureSkins = SkinsProxy.instance.getAvailableSkins(entity);
|
featureSkins = SkinsProxy.instance.getAvailableSkins(entity);
|
||||||
|
mainArm = entity.getMainArm();
|
||||||
|
activeHand = entity.getActiveHand();
|
||||||
|
itemUseTime = entity.getItemUseTimeLeft();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Interpolator getMainInterpolator() {
|
public Interpolator getMainInterpolator() {
|
||||||
return metadata.getInterpolator(interpolatorId);
|
return Interpolator.linear(interpolatorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldLiftArm(ArmPose pose, ArmPose complement, float sigma) {
|
public boolean shouldLiftArm(ArmPose pose, ArmPose complement, float sigma) {
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.minelittlepony.api.model;
|
||||||
|
|
||||||
|
import net.minecraft.client.model.ModelPart;
|
||||||
|
import net.minecraft.client.render.entity.model.ModelWithArms;
|
||||||
|
import net.minecraft.client.render.entity.model.BipedEntityModel.ArmPose;
|
||||||
|
import net.minecraft.util.Arm;
|
||||||
|
|
||||||
|
public interface ModelWithHooves extends ModelWithArms {
|
||||||
|
ModelPart getForeLeg(Arm side);
|
||||||
|
|
||||||
|
ModelPart getHindLeg(Arm side);
|
||||||
|
|
||||||
|
ArmPose getArmPoseForSide(Arm side);
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.minelittlepony.client.model;
|
package com.minelittlepony.api.model;
|
||||||
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.item.ArmorItem;
|
import net.minecraft.item.ArmorItem;
|
||||||
|
@ -6,12 +6,11 @@ import net.minecraft.item.ItemStack;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.IModel;
|
import com.minelittlepony.api.pony.PonyData;
|
||||||
import com.minelittlepony.api.model.IModelWrapper;
|
import com.minelittlepony.client.model.PlayerModelKey;
|
||||||
import com.minelittlepony.api.model.armour.*;
|
import com.minelittlepony.client.model.armour.*;
|
||||||
import com.minelittlepony.api.pony.IPonyData;
|
import com.minelittlepony.mson.api.ModelKey;
|
||||||
import com.minelittlepony.client.model.armour.PonyArmourModel;
|
import com.minelittlepony.mson.api.MsonModel;
|
||||||
import com.minelittlepony.mson.api.*;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
@ -19,14 +18,14 @@ import java.util.function.Consumer;
|
||||||
/**
|
/**
|
||||||
* Container class for the various models and their associated piece of armour.
|
* Container class for the various models and their associated piece of armour.
|
||||||
*/
|
*/
|
||||||
public class ModelWrapper<T extends LivingEntity, M extends IModel> implements IModelWrapper {
|
public class Models<T extends LivingEntity, M extends PonyModel<?>> {
|
||||||
@Nullable
|
@Nullable
|
||||||
private final MsonModel.Factory<PonyArmourModel<T>> armorFactory;
|
private final MsonModel.Factory<PonyArmourModel<T>> armorFactory;
|
||||||
private final Map<ModelKey<PonyArmourModel<?>>, PonyArmourModel<T>> armor = new HashMap<>();
|
private final Map<ModelKey<PonyArmourModel<?>>, PonyArmourModel<T>> armor = new HashMap<>();
|
||||||
|
|
||||||
private final M body;
|
private final M body;
|
||||||
|
|
||||||
public ModelWrapper(PlayerModelKey<T, ? super M> playerModelKey, boolean slimArms, @Nullable Consumer<M> initializer) {
|
public Models(PlayerModelKey<T, ? super M> playerModelKey, boolean slimArms, @Nullable Consumer<M> initializer) {
|
||||||
this.armorFactory = playerModelKey.armorFactory();
|
this.armorFactory = playerModelKey.armorFactory();
|
||||||
this.body = playerModelKey.getKey(slimArms).createModel();
|
this.body = playerModelKey.getKey(slimArms).createModel();
|
||||||
if (initializer != null) {
|
if (initializer != null) {
|
||||||
|
@ -34,7 +33,7 @@ public class ModelWrapper<T extends LivingEntity, M extends IModel> implements I
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelWrapper(ModelKey<M> key) {
|
public Models(ModelKey<M> key) {
|
||||||
this.armorFactory = null;
|
this.armorFactory = null;
|
||||||
this.body = key.createModel();
|
this.body = key.createModel();
|
||||||
}
|
}
|
||||||
|
@ -50,8 +49,7 @@ public class ModelWrapper<T extends LivingEntity, M extends IModel> implements I
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Models<T, M> applyMetadata(PonyData meta) {
|
||||||
public ModelWrapper<T, M> applyMetadata(IPonyData meta) {
|
|
||||||
body.setMetadata(meta);
|
body.setMetadata(meta);
|
||||||
armor.values().forEach(a -> a.setMetadata(meta));
|
armor.values().forEach(a -> a.setMetadata(meta));
|
||||||
return this;
|
return this;
|
|
@ -1,66 +1,49 @@
|
||||||
package com.minelittlepony.api.model;
|
package com.minelittlepony.api.model;
|
||||||
|
|
||||||
|
import net.minecraft.client.model.ModelPart;
|
||||||
|
import net.minecraft.client.render.entity.model.*;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
import com.minelittlepony.api.config.PonyConfig;
|
import com.minelittlepony.api.config.PonyConfig;
|
||||||
import com.minelittlepony.api.pony.IPonyData;
|
import com.minelittlepony.api.pony.Pony;
|
||||||
|
import com.minelittlepony.api.pony.PonyData;
|
||||||
import com.minelittlepony.api.pony.meta.*;
|
import com.minelittlepony.api.pony.meta.*;
|
||||||
|
import com.minelittlepony.mson.api.MsonModel;
|
||||||
|
|
||||||
|
public interface PonyModel<T extends LivingEntity> extends MsonModel, ModelWithHooves, ModelWithHat, ModelWithHead {
|
||||||
|
|
||||||
|
void copyAttributes(BipedEntityModel<T> other);
|
||||||
|
|
||||||
|
void updateLivingState(T entity, Pony pony, ModelAttributes.Mode mode);
|
||||||
|
|
||||||
|
ModelPart getBodyPart(BodyPart part);
|
||||||
|
|
||||||
public interface IModel {
|
|
||||||
/**
|
/**
|
||||||
* Applies a transform particular to a certain body part.
|
* Applies a transform particular to a certain body part.
|
||||||
*/
|
*/
|
||||||
void transform(BodyPart part, MatrixStack stack);
|
void transform(BodyPart part, MatrixStack stack);
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the active scaling profile used to lay out this model's parts.
|
|
||||||
*/
|
|
||||||
Size getSize();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the transitive properties of this model.
|
* Gets the transitive properties of this model.
|
||||||
*/
|
*/
|
||||||
ModelAttributes getAttributes();
|
ModelAttributes getAttributes();
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the skin metadata associated with this model.
|
|
||||||
*/
|
|
||||||
default IPonyData getMetadata() {
|
|
||||||
return getAttributes().metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the pony metadata object associated with this model.
|
* Sets the pony metadata object associated with this model.
|
||||||
*/
|
*/
|
||||||
void setMetadata(IPonyData meta);
|
void setMetadata(PonyData meta);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the model is flying.
|
* Gets the active scaling profile used to lay out this model's parts.
|
||||||
*/
|
*/
|
||||||
default boolean isFlying() {
|
default Size getSize() {
|
||||||
return getAttributes().isFlying && canFly();
|
return PonyConfig.getEffectiveSize(getAttributes().metadata.size());
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if this model is riding a boat, horse, or other animals.
|
|
||||||
*
|
|
||||||
* @deprecated User model#getAttributes().isSitting
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
default boolean isRiding() {
|
|
||||||
return getAttributes().isSitting;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default Race getRace() {
|
default Race getRace() {
|
||||||
return PonyConfig.getEffectiveRace(getMetadata().getRace());
|
return PonyConfig.getEffectiveRace(getAttributes().metadata.race());
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if this model is being applied to a race that has wings.
|
|
||||||
*/
|
|
||||||
default boolean canFly() {
|
|
||||||
return getRace().hasWings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,7 +55,6 @@ public interface IModel {
|
||||||
* Gets the step wobble used for various hair bits and animations.
|
* Gets the step wobble used for various hair bits and animations.
|
||||||
*/
|
*/
|
||||||
default float getWobbleAmount() {
|
default float getWobbleAmount() {
|
||||||
|
|
||||||
if (getSwingAmount() <= 0) {
|
if (getSwingAmount() <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -97,6 +79,7 @@ public interface IModel {
|
||||||
* i.e. Used to change wing rendering when using saddlebags.
|
* i.e. Used to change wing rendering when using saddlebags.
|
||||||
*/
|
*/
|
||||||
default boolean isEmbedded(Wearable wearable) {
|
default boolean isEmbedded(Wearable wearable) {
|
||||||
return getMetadata().isWearing(wearable);
|
return getAttributes().metadata.gear().matches(wearable);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,23 +1,20 @@
|
||||||
package com.minelittlepony.client.model;
|
package com.minelittlepony.api.model;
|
||||||
|
|
||||||
import net.minecraft.client.model.ModelPart;
|
import net.minecraft.client.model.ModelPart;
|
||||||
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||||
import net.minecraft.client.render.entity.model.ModelWithArms;
|
import net.minecraft.client.render.entity.model.ModelWithArms;
|
||||||
|
import net.minecraft.client.render.entity.model.BipedEntityModel.ArmPose;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.util.Arm;
|
import net.minecraft.util.Arm;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.BodyPart;
|
import com.minelittlepony.api.pony.Pony;
|
||||||
import com.minelittlepony.api.model.IUnicorn;
|
import com.minelittlepony.api.pony.PonyData;
|
||||||
import com.minelittlepony.api.model.ModelAttributes;
|
|
||||||
import com.minelittlepony.api.pony.IPony;
|
|
||||||
import com.minelittlepony.api.pony.IPonyData;
|
|
||||||
import com.minelittlepony.api.pony.meta.Size;
|
import com.minelittlepony.api.pony.meta.Size;
|
||||||
import com.minelittlepony.mson.api.ModelView;
|
import com.minelittlepony.mson.api.ModelView;
|
||||||
import com.minelittlepony.mson.api.model.BoxBuilder.RenderLayerSetter;
|
import com.minelittlepony.mson.api.model.BoxBuilder.RenderLayerSetter;
|
||||||
|
|
||||||
public interface IPonyMixinModel<T extends LivingEntity, M extends IPonyModel<T>> extends IPonyModel<T>, ModelWithArms {
|
public interface PonyModelMixin<T extends LivingEntity, M extends PonyModel<T>> extends PonyModel<T> {
|
||||||
|
|
||||||
M mixin();
|
M mixin();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -29,7 +26,7 @@ public interface IPonyMixinModel<T extends LivingEntity, M extends IPonyModel<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void updateLivingState(T entity, IPony pony, ModelAttributes.Mode mode) {
|
default void updateLivingState(T entity, Pony pony, ModelAttributes.Mode mode) {
|
||||||
mixin().updateLivingState(entity, pony, mode);
|
mixin().updateLivingState(entity, pony, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +51,7 @@ public interface IPonyMixinModel<T extends LivingEntity, M extends IPonyModel<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void setMetadata(IPonyData meta) {
|
default void setMetadata(PonyData meta) {
|
||||||
mixin().setMetadata(meta);
|
mixin().setMetadata(meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +70,22 @@ public interface IPonyMixinModel<T extends LivingEntity, M extends IPonyModel<T>
|
||||||
return mixin().getRiderYOffset();
|
return mixin().getRiderYOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default ModelPart getForeLeg(Arm side) {
|
||||||
|
return mixin().getForeLeg(side);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default ModelPart getHindLeg(Arm side) {
|
||||||
|
return mixin().getHindLeg(side);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default ArmPose getArmPoseForSide(Arm side) {
|
||||||
|
return mixin().getArmPoseForSide(side);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void setArmAngle(Arm arm, MatrixStack stack) {
|
default void setArmAngle(Arm arm, MatrixStack stack) {
|
||||||
if (mixin() instanceof ModelWithArms) {
|
if (mixin() instanceof ModelWithArms) {
|
||||||
|
@ -90,7 +103,12 @@ public interface IPonyMixinModel<T extends LivingEntity, M extends IPonyModel<T>
|
||||||
return mixin().getBodyPart(part);
|
return mixin().getBodyPart(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Caster<T extends LivingEntity, M extends IPonyModel<T> & IUnicorn, ArmModel> extends IPonyMixinModel<T, M>, IUnicorn {
|
@Override
|
||||||
|
default void setHatVisible(boolean hatVisible) {
|
||||||
|
mixin().setHatVisible(hatVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Caster<T extends LivingEntity, M extends PonyModel<T> & HornedPonyModel<T>, ArmModel> extends PonyModelMixin<T, M>, HornedPonyModel<T> {
|
||||||
@Override
|
@Override
|
||||||
default boolean isCasting() {
|
default boolean isCasting() {
|
||||||
return mixin().isCasting();
|
return mixin().isCasting();
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.minelittlepony.api.model;
|
||||||
|
|
||||||
|
public interface PreviewModel {
|
||||||
|
boolean forceSeapony();
|
||||||
|
|
||||||
|
boolean forceNirik();
|
||||||
|
}
|
|
@ -3,20 +3,18 @@ package com.minelittlepony.api.model;
|
||||||
import net.minecraft.client.render.VertexConsumer;
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
|
||||||
public interface IPart {
|
public interface SubModel {
|
||||||
/**
|
/**
|
||||||
* Sets the model's various rotation angles.
|
* Sets the model's various rotation angles.
|
||||||
* <p>
|
|
||||||
* See {@link AbstractPonyMode.setRotationAndAngle} for an explanation of the various parameters.
|
|
||||||
*/
|
*/
|
||||||
default void setRotationAndAngles(ModelAttributes attributes, float move, float swing, float bodySwing, float ticks) {
|
default void setPartAngles(ModelAttributes attributes, float limbAngle, float limbSpeed, float bodySwing, float animationProgress) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders this model component.
|
* Renders this model component.
|
||||||
*/
|
*/
|
||||||
void renderPart(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha, ModelAttributes attributes);
|
void renderPart(MatrixStack stack, VertexConsumer vertices, int overlay, int light, float red, float green, float blue, float alpha, ModelAttributes attributes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether this part should be rendered.
|
* Sets whether this part should be rendered.
|
|
@ -1,10 +1,12 @@
|
||||||
package com.minelittlepony.api.model;
|
package com.minelittlepony.api.model;
|
||||||
|
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
|
||||||
|
import com.minelittlepony.api.config.PonyConfig;
|
||||||
import com.minelittlepony.api.pony.meta.Wearable;
|
import com.minelittlepony.api.pony.meta.Wearable;
|
||||||
import com.minelittlepony.client.MineLittlePony;
|
|
||||||
import com.minelittlepony.util.MathUtil;
|
import com.minelittlepony.util.MathUtil;
|
||||||
|
|
||||||
public interface IPegasus extends IModel {
|
public interface WingedPonyModel<T extends LivingEntity> extends PonyModel<T> {
|
||||||
public static final float WINGS_HALF_SPREAD_ANGLE = MathUtil.Angles._270_DEG;
|
public static final float WINGS_HALF_SPREAD_ANGLE = MathUtil.Angles._270_DEG;
|
||||||
public static final float WINGS_FULL_SPREAD_ANGLE = MathUtil.Angles._270_DEG + 0.4F;
|
public static final float WINGS_FULL_SPREAD_ANGLE = MathUtil.Angles._270_DEG + 0.4F;
|
||||||
public static final float WINGS_RAISED_ANGLE = 4;
|
public static final float WINGS_RAISED_ANGLE = 4;
|
||||||
|
@ -13,18 +15,20 @@ public interface IPegasus extends IModel {
|
||||||
* Returns true if the wings are spread.
|
* Returns true if the wings are spread.
|
||||||
*/
|
*/
|
||||||
default boolean wingsAreOpen() {
|
default boolean wingsAreOpen() {
|
||||||
return (getAttributes().isSwimming || isFlying() || getAttributes().isCrouching)
|
return (getAttributes().isSwimming || getAttributes().isFlying || getAttributes().isCrouching)
|
||||||
&& (MineLittlePony.getInstance().getConfig().flappyElytras.get() || !getAttributes().isGliding);
|
&& (PonyConfig.getInstance().flappyElytras.get() || !getAttributes().isGliding);
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean isBurdened() {
|
default boolean isBurdened() {
|
||||||
return isWearing(Wearable.SADDLE_BAGS_BOTH) || isWearing(Wearable.SADDLE_BAGS_LEFT) || isWearing(Wearable.SADDLE_BAGS_RIGHT);
|
return isWearing(Wearable.SADDLE_BAGS_BOTH)
|
||||||
|
|| isWearing(Wearable.SADDLE_BAGS_LEFT)
|
||||||
|
|| isWearing(Wearable.SADDLE_BAGS_RIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the wings of this pegasus/flying creature
|
* Gets the wings of this pegasus/flying creature
|
||||||
*/
|
*/
|
||||||
IPart getWings();
|
SubModel getWings();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines angle used to animate wing flaps whilst flying/swimming.
|
* Determines angle used to animate wing flaps whilst flying/swimming.
|
|
@ -1,17 +0,0 @@
|
||||||
package com.minelittlepony.api.model.armour;
|
|
||||||
|
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
|
||||||
|
|
||||||
import com.minelittlepony.client.model.IPonyModel;
|
|
||||||
|
|
||||||
public interface IArmourModel<T extends LivingEntity> {
|
|
||||||
/**
|
|
||||||
* Called to synchronise this armour's angles with that of another.
|
|
||||||
*
|
|
||||||
* @param model The other model to mimic
|
|
||||||
*/
|
|
||||||
boolean poseModel(T entity, float limbAngle, float limbDistance, float age, float headYaw, float headPitch,
|
|
||||||
EquipmentSlot slot, ArmourLayer layer,
|
|
||||||
IPonyModel<T> mainModel);
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
package com.minelittlepony.api.model.armour;
|
|
||||||
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import com.minelittlepony.client.model.armour.DefaultArmourTextureResolver;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A resolver for looking up the texture for a piece of armour.
|
|
||||||
* <p>
|
|
||||||
* This is for modders who want to override the default implementation found in {@link DefaultArmourTextureResolver}.
|
|
||||||
*/
|
|
||||||
public interface IArmourTextureResolver {
|
|
||||||
/**
|
|
||||||
* Gets the armour texture to be used for the given entity, armour piece, slot, and render layer.
|
|
||||||
*/
|
|
||||||
Identifier getTexture(LivingEntity entity, ItemStack itemstack, EquipmentSlot slot, ArmourLayer layer, @Nullable String type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the armour variant for the identified texture.
|
|
||||||
* Either normal for pony-style textures, or legacy for other textures.
|
|
||||||
*/
|
|
||||||
default ArmourVariant getVariant(ArmourLayer layer, Identifier resolvedTexture) {
|
|
||||||
return ArmourVariant.NORMAL;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.minelittlepony.client.model.gear;
|
package com.minelittlepony.api.model.gear;
|
||||||
|
|
||||||
import net.minecraft.client.model.Model;
|
import net.minecraft.client.model.Model;
|
||||||
import net.minecraft.client.model.ModelPart;
|
import net.minecraft.client.model.ModelPart;
|
||||||
|
@ -6,22 +6,24 @@ import net.minecraft.client.render.RenderLayer;
|
||||||
import net.minecraft.client.render.VertexConsumer;
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.gear.IGear;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public abstract class AbstractGear extends Model implements IGear {
|
public abstract class AbstractGearModel extends Model implements Gear {
|
||||||
|
|
||||||
private final List<ModelPart> parts = new ArrayList<>();
|
private final List<ModelPart> parts = new ArrayList<>();
|
||||||
|
|
||||||
public AbstractGear() {
|
private final float stackingHeight;
|
||||||
|
|
||||||
|
public AbstractGearModel(float stackingHeight) {
|
||||||
super(RenderLayer::getEntitySolid);
|
super(RenderLayer::getEntitySolid);
|
||||||
|
this.stackingHeight = stackingHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPart(ModelPart t) {
|
public AbstractGearModel addPart(ModelPart t) {
|
||||||
parts.add(t);
|
parts.add(t);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -35,4 +37,14 @@ public abstract class AbstractGear extends Model implements IGear {
|
||||||
part.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha);
|
part.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStackable() {
|
||||||
|
return stackingHeight > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getStackingHeight() {
|
||||||
|
return stackingHeight;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -7,26 +7,25 @@ import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.BodyPart;
|
import com.minelittlepony.api.model.*;
|
||||||
import com.minelittlepony.api.model.IModel;
|
|
||||||
import com.minelittlepony.api.pony.meta.Wearable;
|
import com.minelittlepony.api.pony.meta.Wearable;
|
||||||
import com.minelittlepony.client.model.IPonyModel;
|
|
||||||
import com.minelittlepony.client.render.entity.feature.GearFeature;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.*;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for an accessory on a pony's body.
|
* Interface for an accessory on a pony's body.
|
||||||
*/
|
*/
|
||||||
public interface IGear {
|
public interface Gear {
|
||||||
|
List<Supplier<Gear>> MOD_GEARS = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a custom gear to be used with the mod.
|
* Registers a custom gear to be used with the mod.
|
||||||
* <p>
|
* <p>
|
||||||
* This would be awesome for creating socks.
|
* This would be awesome for creating socks.
|
||||||
*/
|
*/
|
||||||
static Supplier<IGear> register(Supplier<IGear> gear) {
|
static Supplier<Gear> register(Supplier<Gear> gear) {
|
||||||
GearFeature.addModGear(gear);
|
MOD_GEARS.add(gear);
|
||||||
return gear;
|
return gear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,13 +37,26 @@ public interface IGear {
|
||||||
*
|
*
|
||||||
* @return True to render this wearable
|
* @return True to render this wearable
|
||||||
*/
|
*/
|
||||||
boolean canRender(IModel model, Entity entity);
|
boolean canRender(PonyModel<?> model, Entity entity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the body location that this wearable appears on.
|
* Gets the body location that this wearable appears on.
|
||||||
*/
|
*/
|
||||||
BodyPart getGearLocation();
|
BodyPart getGearLocation();
|
||||||
|
|
||||||
|
default boolean isStackable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The vertical height of this gear when present in a stack.
|
||||||
|
*
|
||||||
|
* Any gear rendered after this one will be shifted to sit on top of it.
|
||||||
|
*/
|
||||||
|
default float getStackingHeight() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the texture to use for this wearable.
|
* Gets the texture to use for this wearable.
|
||||||
*
|
*
|
||||||
|
@ -62,7 +74,7 @@ public interface IGear {
|
||||||
/**
|
/**
|
||||||
* Applies body transformations for this wearable
|
* Applies body transformations for this wearable
|
||||||
*/
|
*/
|
||||||
default <M extends EntityModel<?> & IPonyModel<?>> void transform(M model, MatrixStack matrices) {
|
default <M extends EntityModel<?> & PonyModel<?>> void transform(M model, MatrixStack matrices) {
|
||||||
BodyPart part = getGearLocation();
|
BodyPart part = getGearLocation();
|
||||||
model.transform(part, matrices);
|
model.transform(part, matrices);
|
||||||
model.getBodyPart(part).rotate(matrices);
|
model.getBodyPart(part).rotate(matrices);
|
||||||
|
@ -73,23 +85,10 @@ public interface IGear {
|
||||||
*
|
*
|
||||||
* See {@link AbstractPonyMode.setRotationAndAngle} for an explanation of the various parameters.
|
* See {@link AbstractPonyMode.setRotationAndAngle} for an explanation of the various parameters.
|
||||||
*/
|
*/
|
||||||
default void pose(IModel model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) {
|
default void pose(PonyModel<?> model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) {
|
||||||
setModelAttributes(model, entity);
|
|
||||||
pose(rainboom, interpolatorId, move, swing, bodySwing, ticks);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use pose(model, entity, rainboom, interpolatorId, move, swing, bodySwing, ticks) instead
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
default void setModelAttributes(IModel model, Entity entity) { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use pose(model, entity, rainboom, interpolatorId, move, swing, bodySwing, ticks) instead
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
default void pose(boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) { }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders this model component.
|
* Renders this model component.
|
||||||
*/
|
*/
|
||||||
|
@ -101,7 +100,7 @@ public interface IGear {
|
||||||
* @param <T> The type of entity being rendered.
|
* @param <T> The type of entity being rendered.
|
||||||
* @param <M> The type of the entity's primary model.
|
* @param <M> The type of the entity's primary model.
|
||||||
*/
|
*/
|
||||||
public interface Context<T extends Entity, M extends IModel> {
|
public interface Context<T extends Entity, M extends PonyModel<?>> {
|
||||||
/**
|
/**
|
||||||
* The empty context.
|
* The empty context.
|
||||||
*/
|
*/
|
||||||
|
@ -110,7 +109,7 @@ public interface IGear {
|
||||||
/**
|
/**
|
||||||
* Checks whether the given wearable and gear are able to render for this specific entity and its renderer.
|
* Checks whether the given wearable and gear are able to render for this specific entity and its renderer.
|
||||||
*/
|
*/
|
||||||
default boolean shouldRender(M model, T entity, Wearable wearable, IGear gear) {
|
default boolean shouldRender(M model, T entity, Wearable wearable, Gear gear) {
|
||||||
return gear.canRender(model, entity);
|
return gear.canRender(model, entity);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
package com.minelittlepony.api.model.gear;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for any gear that changes its position based on where it is in the hat stack.
|
|
||||||
*/
|
|
||||||
public interface IStackable {
|
|
||||||
/**
|
|
||||||
* The vertical height of this gear when present in a stack.
|
|
||||||
*
|
|
||||||
* Any gear rendered after this one will be shifted to sit on top of it.
|
|
||||||
*/
|
|
||||||
float getStackingHeight();
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,18 +1,19 @@
|
||||||
package com.minelittlepony.client.model.gear;
|
package com.minelittlepony.api.model.gear;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.BodyPart;
|
import com.minelittlepony.api.model.BodyPart;
|
||||||
import com.minelittlepony.api.model.IModel;
|
import com.minelittlepony.api.model.PonyModel;
|
||||||
import com.minelittlepony.api.pony.meta.Wearable;
|
import com.minelittlepony.api.pony.meta.Wearable;
|
||||||
|
|
||||||
public abstract class AbstractWearableGear extends AbstractGear {
|
public class WearableGear extends AbstractGearModel {
|
||||||
|
|
||||||
protected final Wearable wearable;
|
protected final Wearable wearable;
|
||||||
protected final BodyPart location;
|
protected final BodyPart location;
|
||||||
|
|
||||||
protected AbstractWearableGear(Wearable wearable, BodyPart location) {
|
public WearableGear(Wearable wearable, BodyPart location, float stackingHeight) {
|
||||||
|
super(stackingHeight);
|
||||||
this.wearable = wearable;
|
this.wearable = wearable;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +24,7 @@ public abstract class AbstractWearableGear extends AbstractGear {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canRender(IModel model, Entity entity) {
|
public boolean canRender(PonyModel<?> model, Entity entity) {
|
||||||
return model.isWearing(wearable);
|
return model.isWearing(wearable);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,43 @@
|
||||||
package com.minelittlepony.api.pony;
|
package com.minelittlepony.api.pony;
|
||||||
|
|
||||||
|
import net.minecraft.client.util.DefaultSkinHelper;
|
||||||
|
import net.minecraft.client.util.SkinTextures;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import com.minelittlepony.api.pony.meta.Race;
|
||||||
import java.util.Map;
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
public final class DefaultPonySkinHelper {
|
public final class DefaultPonySkinHelper {
|
||||||
public static final Identifier STEVE = new Identifier("minelittlepony", "textures/entity/player/wide/steve_pony.png");
|
public static final Identifier STEVE = new Identifier("minelittlepony", "textures/entity/player/wide/steve_pony.png");
|
||||||
|
|
||||||
private static final Map<Identifier, Identifier> SKINS = new HashMap<>();
|
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 Identifier getPonySkin(Identifier original) {
|
private static final Map<SkinTextures, SkinTextures> SKINS = new HashMap<>();
|
||||||
return SKINS.computeIfAbsent(original, DefaultPonySkinHelper::computePonySkin);
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Identifier computePonySkin(Identifier original) {
|
public static String getModelType(UUID id) {
|
||||||
return new Identifier("minelittlepony", original.getPath().replace(".png", "_pony.png"));
|
SkinTextures textures = DefaultSkinHelper.getSkinTextures(id);
|
||||||
|
return getModelType(Pony.getManager().getPony(textures.texture(), id).race(), textures.model());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getModelType(Race race, SkinTextures.Model armShape) {
|
||||||
|
if (race.isHuman()) {
|
||||||
|
return armShape.getName();
|
||||||
|
}
|
||||||
|
return (armShape == SkinTextures.Model.SLIM) ? armShape.getName() + race.name().toLowerCase(Locale.ROOT) : race.name().toLowerCase(Locale.ROOT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
package com.minelittlepony.api.pony;
|
|
||||||
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import com.google.common.collect.ComparisonChain;
|
|
||||||
import com.minelittlepony.api.config.PonyConfig;
|
|
||||||
import com.minelittlepony.api.pony.meta.Race;
|
|
||||||
|
|
||||||
public interface IPony extends Comparable<IPony> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the global pony manager instance.
|
|
||||||
*/
|
|
||||||
static IPonyManager getManager() {
|
|
||||||
return IPonyManager.Instance.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets or creates a new pony associated with the provided resource location.
|
|
||||||
* The results of this method should not be cached.
|
|
||||||
*
|
|
||||||
* @deprecated User IPony.getManager().getPony(texture) instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
static IPony forResource(Identifier texture) {
|
|
||||||
return getManager().getPony(texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether this is one of the default ponies assigned to a player without a custom skin.
|
|
||||||
*/
|
|
||||||
boolean defaulted();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether this pony's metadata block has been initialized.
|
|
||||||
*/
|
|
||||||
boolean hasMetadata();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the race associated with this pony.
|
|
||||||
*/
|
|
||||||
default Race race() {
|
|
||||||
return PonyConfig.getEffectiveRace(metadata().getRace());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if and only if this metadata represents a pony that can cast magic.
|
|
||||||
*/
|
|
||||||
default boolean hasMagic() {
|
|
||||||
return race().hasHorn() && metadata().getGlowColor() != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the texture used for rendering this pony.
|
|
||||||
*/
|
|
||||||
Identifier texture();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the metadata associated with this pony's model texture.
|
|
||||||
*/
|
|
||||||
IPonyData metadata();
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default int compareTo(@Nullable IPony o) {
|
|
||||||
return o == this ? 0 : o == null ? 1 : ComparisonChain.start()
|
|
||||||
.compare(texture(), o.texture())
|
|
||||||
.compare(metadata(), o.metadata())
|
|
||||||
.result();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
package com.minelittlepony.api.pony;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import com.google.common.collect.ComparisonChain;
|
|
||||||
import com.minelittlepony.api.pony.meta.*;
|
|
||||||
import com.minelittlepony.common.util.animation.Interpolator;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metadata for a pony.
|
|
||||||
*/
|
|
||||||
public interface IPonyData extends Comparable<IPonyData> {
|
|
||||||
/**
|
|
||||||
* Gets this pony's race.
|
|
||||||
*
|
|
||||||
* This is the actual race value. For the effective race, prefer going through {@link IPony#race}
|
|
||||||
*/
|
|
||||||
Race getRace();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the length of the pony's tail.
|
|
||||||
*/
|
|
||||||
TailLength getTailLength();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the shape of the pony's tail.
|
|
||||||
*/
|
|
||||||
TailShape getTailShape();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the pony's gender (usually female).
|
|
||||||
*/
|
|
||||||
Gender getGender();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current pony size.
|
|
||||||
*/
|
|
||||||
Size getSize();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the magical glow colour for magic-casting races. Returns 0 otherwise.
|
|
||||||
*/
|
|
||||||
int getGlowColor();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an array of wearables that this pony is carrying.
|
|
||||||
*/
|
|
||||||
Wearable[] getGear();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks it this pony is wearing the given accessory.
|
|
||||||
*/
|
|
||||||
boolean isWearing(Wearable wearable);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an interpolator for interpolating values.
|
|
||||||
*/
|
|
||||||
Interpolator getInterpolator(UUID interpolatorId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the trigger pixel values as they appeared in the underlying image.
|
|
||||||
*/
|
|
||||||
Map<String, TriggerPixelType<?>> getTriggerPixels();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default int compareTo(@Nullable IPonyData o) {
|
|
||||||
return o == this ? 0 : o == null ? 1 : ComparisonChain.start()
|
|
||||||
.compare(getRace(), o.getRace())
|
|
||||||
.compare(getTailLength(), o.getTailLength())
|
|
||||||
.compare(getGender(), o.getGender())
|
|
||||||
.compare(getSize().ordinal(), o.getSize().ordinal())
|
|
||||||
.compare(getGlowColor(), o.getGlowColor())
|
|
||||||
.compare(0, Arrays.compare(getGear(), o.getGear()))
|
|
||||||
.result();
|
|
||||||
}
|
|
||||||
}
|
|
73
src/main/java/com/minelittlepony/api/pony/Pony.java
Normal file
73
src/main/java/com/minelittlepony/api/pony/Pony.java
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
package com.minelittlepony.api.pony;
|
||||||
|
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.ComparisonChain;
|
||||||
|
import com.minelittlepony.api.config.PonyConfig;
|
||||||
|
import com.minelittlepony.api.pony.meta.Race;
|
||||||
|
import com.minelittlepony.api.pony.meta.Size;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public record Pony (
|
||||||
|
/**
|
||||||
|
* Gets the texture used for rendering this pony.
|
||||||
|
*/
|
||||||
|
Identifier texture,
|
||||||
|
Supplier<Optional<PonyData>> metadataGetter
|
||||||
|
) implements Comparable<Pony> {
|
||||||
|
/**
|
||||||
|
* Gets the global pony manager instance.
|
||||||
|
*/
|
||||||
|
public static PonyManager getManager() {
|
||||||
|
return PonyManager.Instance.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the metadata associated with this pony's model texture.
|
||||||
|
*/
|
||||||
|
public PonyData metadata() {
|
||||||
|
return metadataGetter().get().orElse(PonyData.NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this pony's metadata block has been initialized.
|
||||||
|
*/
|
||||||
|
public boolean hasMetadata() {
|
||||||
|
return metadataGetter().get().isPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pony immutableCopy() {
|
||||||
|
final Optional<PonyData> metadata = metadataGetter().get();
|
||||||
|
return new Pony(texture(), () -> metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the race associated with this pony.
|
||||||
|
*/
|
||||||
|
public Race race() {
|
||||||
|
return PonyConfig.getEffectiveRace(metadata().race());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Size size() {
|
||||||
|
return PonyConfig.getEffectiveSize(metadata().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if and only if this metadata represents a pony that can cast magic.
|
||||||
|
*/
|
||||||
|
public boolean hasMagic() {
|
||||||
|
return race().hasHorn() && metadata().glowColor() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(@Nullable Pony o) {
|
||||||
|
return o == this ? 0 : o == null ? 1 : ComparisonChain.start()
|
||||||
|
.compare(texture(), o.texture())
|
||||||
|
.compare(metadata(), o.metadata())
|
||||||
|
.result();
|
||||||
|
}
|
||||||
|
}
|
116
src/main/java/com/minelittlepony/api/pony/PonyData.java
Normal file
116
src/main/java/com/minelittlepony/api/pony/PonyData.java
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
package com.minelittlepony.api.pony;
|
||||||
|
|
||||||
|
import net.minecraft.util.Util;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.ComparisonChain;
|
||||||
|
import com.minelittlepony.api.pony.meta.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metadata for a pony.
|
||||||
|
*/
|
||||||
|
public record PonyData (
|
||||||
|
/**
|
||||||
|
* Gets this pony's race.
|
||||||
|
*
|
||||||
|
* This is the actual race value. For the effective race, prefer going through {@link Pony#race}
|
||||||
|
*/
|
||||||
|
Race race,
|
||||||
|
/**
|
||||||
|
* Gets the length of the pony's tail.
|
||||||
|
*/
|
||||||
|
TailLength tailLength,
|
||||||
|
/**
|
||||||
|
* Gets the shape of the pony's tail.
|
||||||
|
*/
|
||||||
|
TailShape tailShape,
|
||||||
|
/**
|
||||||
|
* Get the pony's gender (usually female).
|
||||||
|
*/
|
||||||
|
Gender gender,
|
||||||
|
/**
|
||||||
|
* Gets the current pony size.
|
||||||
|
*/
|
||||||
|
Size size,
|
||||||
|
/**
|
||||||
|
* Gets the magical glow colour for magic-casting races. Returns 0 otherwise.
|
||||||
|
*/
|
||||||
|
int glowColor,
|
||||||
|
/**
|
||||||
|
* Returns an array of wearables that this pony is carrying.
|
||||||
|
*/
|
||||||
|
Flags<Wearable> gear,
|
||||||
|
/**
|
||||||
|
* Indicates whether this pony data corresponds to one of the default/built-in skins
|
||||||
|
* rather than a user-uploaded one.
|
||||||
|
*/
|
||||||
|
boolean noSkin,
|
||||||
|
/**
|
||||||
|
* (Experimental) Priority.
|
||||||
|
* Used to decide which skin to use when dual skin mode is active.
|
||||||
|
* Provides an optional tie-breaker when the client has to decide between displaying
|
||||||
|
* either the HDSkins texture or vanilla texture given both are otherwise acceptable.
|
||||||
|
*
|
||||||
|
* Any time both skins resolve to the same race (eg. on pony-level HUMANS, or if both are ponies)
|
||||||
|
* the skin with the highest priority will be chosen.
|
||||||
|
*
|
||||||
|
* If both have the same priority, HD Skins' texture will always be used (old default).
|
||||||
|
*/
|
||||||
|
int priority,
|
||||||
|
/**
|
||||||
|
* Gets the trigger pixel values as they appeared in the underlying image.
|
||||||
|
*/
|
||||||
|
Map<String, TValue<?>> attributes
|
||||||
|
) implements Comparable<PonyData> {
|
||||||
|
public static final int DEFAULT_MAGIC_COLOR = 0x4444aa;
|
||||||
|
private static final Function<Race, PonyData> OF_RACE = Util.memoize(race -> new PonyData(race, TailLength.FULL, TailShape.STRAIGHT, Gender.MARE, SizePreset.NORMAL, DEFAULT_MAGIC_COLOR, true, 0, Wearable.EMPTY_FLAGS));
|
||||||
|
public static final PonyData NULL = OF_RACE.apply(Race.HUMAN);
|
||||||
|
|
||||||
|
public static PonyData emptyOf(Race race) {
|
||||||
|
return OF_RACE.apply(race);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PonyData(TriggerPixel.Mat image, boolean noSkin) {
|
||||||
|
this(
|
||||||
|
TriggerPixel.RACE.read(image),
|
||||||
|
TriggerPixel.TAIL.read(image),
|
||||||
|
TriggerPixel.TAIL_SHAPE.read(image),
|
||||||
|
TriggerPixel.GENDER.read(image),
|
||||||
|
TriggerPixel.SIZE.read(image),
|
||||||
|
TriggerPixel.GLOW.read(image),
|
||||||
|
noSkin,
|
||||||
|
TriggerPixel.PRIORITY.read(image),
|
||||||
|
TriggerPixel.WEARABLES.read(image)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PonyData(Race race, TailLength tailLength, TailShape tailShape, Gender gender, Size size, int glowColor, boolean noSkin, int priority, Flags<Wearable> wearables) {
|
||||||
|
this(race, tailLength, tailShape, gender, size, glowColor, wearables, noSkin, priority, Util.make(new TreeMap<>(), map -> {
|
||||||
|
map.put("race", race);
|
||||||
|
map.put("tailLength", tailLength);
|
||||||
|
map.put("tailShape", tailShape);
|
||||||
|
map.put("gender", gender);
|
||||||
|
map.put("size", size);
|
||||||
|
map.put("magic", new TValue.Numeric(glowColor));
|
||||||
|
map.put("priority", new TValue.Numeric(priority));
|
||||||
|
map.put("gear", wearables);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(@Nullable PonyData o) {
|
||||||
|
return o == this ? 0 : o == null ? 1 : ComparisonChain.start()
|
||||||
|
.compare(race(), o.race())
|
||||||
|
.compare(tailLength(), o.tailLength())
|
||||||
|
.compare(gender(), o.gender())
|
||||||
|
.compare(size().ordinal(), o.size().ordinal())
|
||||||
|
.compare(glowColor(), o.glowColor())
|
||||||
|
.compare(0, gear().compareTo(o.gear()))
|
||||||
|
.result();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package com.minelittlepony.api.pony;
|
package com.minelittlepony.api.pony;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
@ -10,16 +11,33 @@ import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The PonyManager is responsible for reading and recoding all the pony data associated with an entity of skin.
|
* The PonyManager is responsible for reading and recoding all the pony data associated with the skin of an entity.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface IPonyManager {
|
public interface PonyManager {
|
||||||
/**
|
/**
|
||||||
* Gets a pony representation of the passed in entity.
|
* Gets a pony representation of the passed in entity.
|
||||||
*
|
*
|
||||||
* If the supplied entity is null or can't be determined to be a pony, returns the empty optional.
|
* If the supplied entity is null or can't be determined to be a pony, returns the empty optional.
|
||||||
*/
|
*/
|
||||||
Optional<IPony> getPony(@Nullable Entity entity);
|
default Optional<Pony> getPony(@Nullable Entity entity) {
|
||||||
|
return entity instanceof LivingEntity living ? getPony(living) : Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a pony representation of the passed in entity.
|
||||||
|
*
|
||||||
|
* If the supplied entity is null or can't be determined to be a pony, returns the empty optional.
|
||||||
|
*/
|
||||||
|
Optional<Pony> getPony(LivingEntity entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a random background pony determined by the given uuid.
|
||||||
|
*
|
||||||
|
* Useful for mods that offer customisation, especially ones that have a whole lot of NPCs.
|
||||||
|
*
|
||||||
|
* @param uuid id of a player
|
||||||
|
*/
|
||||||
|
Pony getBackgroundPony(UUID uuid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets or creates a pony for the given player.
|
* Gets or creates a pony for the given player.
|
||||||
|
@ -27,14 +45,7 @@ public interface IPonyManager {
|
||||||
*
|
*
|
||||||
* @param player the player
|
* @param player the player
|
||||||
*/
|
*/
|
||||||
IPony getPony(PlayerEntity player);
|
Pony getPony(PlayerEntity player);
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets or creates a pony for the given skin resource and vanilla model type.
|
|
||||||
*
|
|
||||||
* @param resource A texture resource
|
|
||||||
*/
|
|
||||||
IPony getPony(Identifier resource);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets or creates a pony for the given skin resource and entity id.
|
* Gets or creates a pony for the given skin resource and entity id.
|
||||||
|
@ -46,25 +57,20 @@ public interface IPonyManager {
|
||||||
* @param resource A texture resource
|
* @param resource A texture resource
|
||||||
* @param uuid id of a player
|
* @param uuid id of a player
|
||||||
*/
|
*/
|
||||||
IPony getPony(Identifier resource, UUID uuid);
|
Pony getPony(@Nullable Identifier resource, @Nullable UUID uuid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a random background pony determined by the given uuid.
|
* Gets or creates a pony for the given skin resource and vanilla model type.
|
||||||
*
|
*
|
||||||
* Useful for mods that offer customisation, especially ones that have a whole lot of NPCs.
|
* @param resource A texture resource
|
||||||
*
|
|
||||||
* @param uuid A UUID. Either a user or an entity.
|
|
||||||
*/
|
*/
|
||||||
IPony getBackgroundPony(UUID uuid);
|
default Pony getPony(Identifier resource) {
|
||||||
|
return getPony(resource, null);
|
||||||
/**
|
}
|
||||||
* De-registers a pony from the cache.
|
|
||||||
*/
|
|
||||||
void removePony(Identifier resource);
|
|
||||||
|
|
||||||
interface ForcedPony {}
|
interface ForcedPony {}
|
||||||
|
|
||||||
final class Instance {
|
final class Instance {
|
||||||
public static IPonyManager instance;
|
public static PonyManager instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,25 +1,27 @@
|
||||||
package com.minelittlepony.api.pony;
|
package com.minelittlepony.api.pony;
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.meta.Race;
|
import com.minelittlepony.api.pony.meta.Race;
|
||||||
|
import com.minelittlepony.api.model.PreviewModel;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Material;
|
|
||||||
import net.minecraft.block.StairsBlock;
|
import net.minecraft.block.StairsBlock;
|
||||||
|
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.registry.tag.FluidTags;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
public final class PonyPosture {
|
public final class PonyPosture {
|
||||||
public static Optional<IPony> getMountPony(LivingEntity entity) {
|
public static Optional<Pony> getMountPony(LivingEntity entity) {
|
||||||
return entity.getVehicle() instanceof LivingEntity mount
|
return entity.getVehicle() instanceof LivingEntity mount
|
||||||
? IPony.getManager().getPony(mount)
|
? Pony.getManager().getPony(mount)
|
||||||
: Optional.empty();
|
: Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isCrouching(IPony pony, LivingEntity entity) {
|
public static boolean isCrouching(Pony pony, LivingEntity entity) {
|
||||||
boolean isSneak = entity.isInSneakingPose();
|
boolean isSneak = entity.isInSneakingPose();
|
||||||
boolean isFlying = isFlying(entity);
|
boolean isFlying = isFlying(entity);
|
||||||
boolean isSwimming = isSwimming(entity);
|
boolean isSwimming = isSwimming(entity);
|
||||||
|
@ -27,7 +29,7 @@ public final class PonyPosture {
|
||||||
return !isPerformingRainboom(pony, entity) && !isSwimming && isSneak && !isFlying;
|
return !isPerformingRainboom(pony, entity) && !isSwimming && isSneak && !isFlying;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isPerformingRainboom(IPony pony, LivingEntity entity) {
|
private static boolean isPerformingRainboom(Pony pony, LivingEntity entity) {
|
||||||
Vec3d motion = entity.getVelocity();
|
Vec3d motion = entity.getVelocity();
|
||||||
double zMotion = Math.sqrt(motion.x * motion.x + motion.z * motion.z);
|
double zMotion = Math.sqrt(motion.x * motion.x + motion.z * motion.z);
|
||||||
|
|
||||||
|
@ -73,7 +75,7 @@ public final class PonyPosture {
|
||||||
|
|
||||||
public static boolean isPartiallySubmerged(LivingEntity entity) {
|
public static boolean isPartiallySubmerged(LivingEntity entity) {
|
||||||
return entity.isSubmergedInWater()
|
return entity.isSubmergedInWater()
|
||||||
|| entity.getEntityWorld().getBlockState(entity.getBlockPos()).getMaterial() == Material.WATER;
|
|| entity.getEntityWorld().getBlockState(entity.getBlockPos()).getFluidState().isIn(FluidTags.WATER);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSitting(LivingEntity entity) {
|
public static boolean isSitting(LivingEntity entity) {
|
||||||
|
@ -81,6 +83,43 @@ public final class PonyPosture {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isRidingAPony(LivingEntity entity) {
|
public static boolean isRidingAPony(LivingEntity entity) {
|
||||||
return isSitting(entity) && getMountPony(entity).map(IPony::race).orElse(Race.HUMAN) != Race.HUMAN;
|
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 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())
|
||||||
|
);
|
||||||
|
}).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 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())
|
||||||
|
);
|
||||||
|
}).isPresent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
32
src/main/java/com/minelittlepony/api/pony/SkinsProxy.java
Normal file
32
src/main/java/com/minelittlepony/api/pony/SkinsProxy.java
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package com.minelittlepony.api.pony;
|
||||||
|
|
||||||
|
import com.mojang.authlib.GameProfile;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||||
|
import net.minecraft.client.texture.PlayerSkinProvider;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy handler for getting player skin data from HDSkins
|
||||||
|
*/
|
||||||
|
public class SkinsProxy {
|
||||||
|
public static SkinsProxy instance = new SkinsProxy();
|
||||||
|
|
||||||
|
public Identifier getSkinTexture(GameProfile profile) {
|
||||||
|
PlayerSkinProvider skins = MinecraftClient.getInstance().getSkinProvider();
|
||||||
|
return skins.getSkinTextures(profile).texture();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Identifier> getSkin(Identifier skinTypeId, AbstractClientPlayerEntity player) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Identifier> getAvailableSkins(Entity entity) {
|
||||||
|
return Set.of();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,24 +0,0 @@
|
||||||
package com.minelittlepony.api.pony;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public class TriggerPixelSet<T extends Enum<T> & TriggerPixelType<T>> extends TriggerPixelValue<boolean[]> {
|
|
||||||
|
|
||||||
private final T def;
|
|
||||||
|
|
||||||
public TriggerPixelSet(int color, T def, boolean[] value) {
|
|
||||||
super(color, value);
|
|
||||||
this.def = def;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<TriggerPixelType<T>> getOptions() {
|
|
||||||
return def.getOptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(Object o) {
|
|
||||||
return o.getClass() == def.getClass() && getValue()[((Enum<?>)o).ordinal()];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
package com.minelittlepony.api.pony;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for enums that can be parsed from an image trigger pixel value.
|
|
||||||
*/
|
|
||||||
public interface TriggerPixelType<T> {
|
|
||||||
/**
|
|
||||||
* Gets the pixel colour matching this enum value.
|
|
||||||
*/
|
|
||||||
int getColorCode();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the pixel colour matching this enum value, adjusted to fill all three channels.
|
|
||||||
*/
|
|
||||||
default int getChannelAdjustedColorCode() {
|
|
||||||
return getColorCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a string representation of this value.
|
|
||||||
*/
|
|
||||||
default String name() {
|
|
||||||
return "[Numeric " + getHexValue() + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
default String getHexValue() {
|
|
||||||
return toHex(getColorCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of possible values this trigger pixel can accept.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
default <Option extends TriggerPixelType<T>> List<Option> getOptions() {
|
|
||||||
if (this instanceof Enum) {
|
|
||||||
// cast is required because gradle's compiler is more strict
|
|
||||||
return (List<Option>)List.of(getClass().getEnumConstants());
|
|
||||||
}
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean matches(Object o) {
|
|
||||||
return equals(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the enum value corresponding to the given enum type and pixel value.
|
|
||||||
* If none are found, the first parameter is returned as the default.
|
|
||||||
*
|
|
||||||
* @param type Return type and default value.
|
|
||||||
* @param pixelValue The pixel colour to search for.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
static <T extends TriggerPixelType<T>> T getByTriggerPixel(T type, int pixelValue) {
|
|
||||||
return (T)type.getOptions().stream()
|
|
||||||
.filter(i -> i.getColorCode() == pixelValue)
|
|
||||||
.findFirst()
|
|
||||||
.orElse(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static TriggerPixelType<?> of(int color) {
|
|
||||||
return () -> color;
|
|
||||||
}
|
|
||||||
|
|
||||||
static String toHex(int color) {
|
|
||||||
String v = Integer.toHexString(color).toUpperCase();
|
|
||||||
while (v.length() < 6) {
|
|
||||||
v = "0" + v;
|
|
||||||
}
|
|
||||||
return "#" + v;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
package com.minelittlepony.api.pony;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class TriggerPixelValue<T> implements TriggerPixelType<T> {
|
|
||||||
|
|
||||||
private final int color;
|
|
||||||
private final T value;
|
|
||||||
|
|
||||||
public TriggerPixelValue(int color, T value) {
|
|
||||||
this.color = color;
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public String name() {
|
|
||||||
return value instanceof TriggerPixelType ? ((TriggerPixelType<T>)value).name() : TriggerPixelType.super.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public <Option extends TriggerPixelType<T>> List<Option> getOptions() {
|
|
||||||
return value instanceof TriggerPixelType ? ((TriggerPixelType<T>)value).getOptions() : TriggerPixelType.super.getOptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getColorCode() {
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
return super.equals(o)
|
|
||||||
|| (o instanceof TriggerPixelValue && Objects.equals(((TriggerPixelValue<?>)o).getValue(), getValue()))
|
|
||||||
|| Objects.equals(o, getValue());
|
|
||||||
}
|
|
||||||
}
|
|
59
src/main/java/com/minelittlepony/api/pony/meta/Flags.java
Normal file
59
src/main/java/com/minelittlepony/api/pony/meta/Flags.java
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
package com.minelittlepony.api.pony.meta;
|
||||||
|
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public record Flags<T extends Enum<T> & TValue<T>> (
|
||||||
|
T def,
|
||||||
|
Set<T> values,
|
||||||
|
int colorCode
|
||||||
|
) implements Comparable<Flags<T>>, TValue<T> {
|
||||||
|
|
||||||
|
public static <T extends Enum<T> & TValue<T>> Flags<T> of(T def) {
|
||||||
|
return new Flags<>(def, Set.<T>of(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T> & TValue<T>> Flags<T> of(T def, int colorCode, Set<T> values) {
|
||||||
|
return new Flags<>(def, values, colorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T> & TValue<T>> Flags<T> read(T def, PacketByteBuf buffer) {
|
||||||
|
int length = buffer.readVarInt();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Set<T> values = EnumSet.noneOf((Class<T>)def.getClass());
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T[] all = (T[])def.getClass().getEnumConstants();
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
values.add(all[buffer.readInt()]);
|
||||||
|
}
|
||||||
|
return new Flags<>(def, values, buffer.readInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(PacketByteBuf buffer) {
|
||||||
|
buffer.writeCollection(values, (buf, value) -> buf.writeInt(value.ordinal()));
|
||||||
|
buffer.writeInt(colorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "[Flags " + values + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TValue<T>> getOptions() {
|
||||||
|
return def.getOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public boolean matches(TValue<?> o) {
|
||||||
|
return o.getClass() == def.getClass() && values.contains((T)o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Flags<T> other) {
|
||||||
|
return Integer.compare(colorCode(), other.colorCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
package com.minelittlepony.api.pony.meta;
|
package com.minelittlepony.api.pony.meta;
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.TriggerPixelType;
|
public enum Gender implements TValue<Gender> {
|
||||||
|
|
||||||
public enum Gender implements TriggerPixelType<Gender> {
|
|
||||||
MARE(0),
|
MARE(0),
|
||||||
STALLION(0xffffff),
|
STALLION(0xffffff),
|
||||||
ABOMONATION(0x888888);
|
ABOMONATION(0x888888);
|
||||||
|
@ -14,7 +12,7 @@ public enum Gender implements TriggerPixelType<Gender> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getColorCode() {
|
public int colorCode() {
|
||||||
return triggerValue;
|
return triggerValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
package com.minelittlepony.api.pony.meta;
|
package com.minelittlepony.api.pony.meta;
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.TriggerPixelType;
|
public enum Race implements TValue<Race> {
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public enum Race implements TriggerPixelType<Race> {
|
|
||||||
HUMAN (0x000000, false, false),
|
HUMAN (0x000000, false, false),
|
||||||
EARTH (0xf9b131, false, false),
|
EARTH (0xf9b131, false, false),
|
||||||
PEGASUS (0x88caf0, true, false),
|
PEGASUS (0x88caf0, true, false),
|
||||||
|
@ -20,16 +15,13 @@ public enum Race implements TriggerPixelType<Race> {
|
||||||
BATPONY (0xeeeeee, true, false),
|
BATPONY (0xeeeeee, true, false),
|
||||||
SEAPONY (0x3655dd, false, true);
|
SEAPONY (0x3655dd, false, true);
|
||||||
|
|
||||||
private boolean wings;
|
private final boolean wings;
|
||||||
private boolean horn;
|
private final boolean horn;
|
||||||
|
|
||||||
private int triggerPixel;
|
private final int colorCode;
|
||||||
|
|
||||||
public static final List<Race> REGISTRY = Arrays.asList(values());
|
|
||||||
|
|
||||||
Race(int triggerPixel, boolean wings, boolean horn) {
|
|
||||||
this.triggerPixel = triggerPixel;
|
|
||||||
|
|
||||||
|
Race(int colorCode, boolean wings, boolean horn) {
|
||||||
|
this.colorCode = colorCode;
|
||||||
this.wings = wings;
|
this.wings = wings;
|
||||||
this.horn = horn;
|
this.horn = horn;
|
||||||
}
|
}
|
||||||
|
@ -70,14 +62,7 @@ public enum Race implements TriggerPixelType<Race> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getColorCode() {
|
public int colorCode() {
|
||||||
return triggerPixel;
|
return colorCode;
|
||||||
}
|
|
||||||
|
|
||||||
public String getModelId(boolean isSlim) {
|
|
||||||
if (isHuman()) {
|
|
||||||
return isSlim ? "slim" : "default";
|
|
||||||
}
|
|
||||||
return isSlim ? "slim" + name().toLowerCase() : name().toLowerCase();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
package com.minelittlepony.api.pony.meta;
|
package com.minelittlepony.api.pony.meta;
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.TriggerPixelType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the different model sizes that are possible.
|
* Represents the different model sizes that are possible.
|
||||||
*
|
*
|
||||||
* For a list of possible presets, look at {@link Sizes}.
|
* For a list of possible presets, look at {@link SizePreset}.
|
||||||
* This interface exists for servers so they can work with this information even though they might not have access to the client config.
|
* This interface exists for servers so they can work with this information even though they might not have access to the client config.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public interface Size extends TriggerPixelType<Size> {
|
public interface Size extends TValue<Size> {
|
||||||
/**
|
/**
|
||||||
* The Enum index of this size. May be used on the client to convert to an instance of Sizes or use {@link Sizes#of}
|
* The Enum index of this size. May be used on the client to convert to an instance of Sizes or use {@link SizePreset#of}
|
||||||
*
|
*
|
||||||
* Made to be compatible with the enum variant.
|
* Made to be compatible with the enum variant.
|
||||||
*/
|
*/
|
||||||
|
@ -27,20 +25,25 @@ public interface Size extends TriggerPixelType<Size> {
|
||||||
/**
|
/**
|
||||||
* A scale factor that controls the size of the shadow that appears under the entity.
|
* A scale factor that controls the size of the shadow that appears under the entity.
|
||||||
*/
|
*/
|
||||||
float getShadowSize();
|
float shadowSize();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The global scale factor applied to all physical dimensions.
|
* The global scale factor applied to all physical dimensions.
|
||||||
*/
|
*/
|
||||||
float getScaleFactor();
|
float scaleFactor();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A scale factor used to alter the vertical eye position.
|
* A scale factor used to alter the vertical eye position.
|
||||||
*/
|
*/
|
||||||
float getEyeHeightFactor();
|
float eyeHeightFactor();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A scale factor used to alter the camera's distance.
|
* A scale factor used to alter the camera's distance.
|
||||||
*/
|
*/
|
||||||
float getEyeDistanceFactor();
|
float eyeDistanceFactor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The trigger pixel colour corresponding to this size.
|
||||||
|
*/
|
||||||
|
int colorCode();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import com.minelittlepony.api.config.PonyConfig;
|
||||||
*
|
*
|
||||||
* For spooky things at a distance, use {@link Size} instead.
|
* For spooky things at a distance, use {@link Size} instead.
|
||||||
*/
|
*/
|
||||||
public enum Sizes implements Size {
|
public enum SizePreset implements Size {
|
||||||
TALL (0x534b76, 0.45f, 1.1F, 1.15F),
|
TALL (0x534b76, 0.45f, 1.1F, 1.15F),
|
||||||
BULKY (0xce3254, 0.5f, 1, 1.05F),
|
BULKY (0xce3254, 0.5f, 1, 1.05F),
|
||||||
LANKY (0x3254ce, 0.45F, 0.85F, 0.9F),
|
LANKY (0x3254ce, 0.45F, 0.85F, 0.9F),
|
||||||
|
@ -18,15 +18,12 @@ public enum Sizes implements Size {
|
||||||
FOAL (0xffbe53, 0.25f, 0.6F, 0.5F),
|
FOAL (0xffbe53, 0.25f, 0.6F, 0.5F),
|
||||||
UNSET (0x000000, 1, 1, 1);
|
UNSET (0x000000, 1, 1, 1);
|
||||||
|
|
||||||
public static final Sizes[] REGISTRY = values();
|
private final int triggerValue;
|
||||||
|
private final float shadowSize;
|
||||||
|
private final float scale;
|
||||||
|
private final float camera;
|
||||||
|
|
||||||
private int triggerValue;
|
SizePreset(int pixel, float shadowSz, float scaleF, float cameraF) {
|
||||||
|
|
||||||
private float shadowSize;
|
|
||||||
private float scale;
|
|
||||||
private float camera;
|
|
||||||
|
|
||||||
Sizes(int pixel, float shadowSz, float scaleF, float cameraF) {
|
|
||||||
triggerValue = pixel;
|
triggerValue = pixel;
|
||||||
shadowSize = shadowSz;
|
shadowSize = shadowSz;
|
||||||
scale = scaleF;
|
scale = scaleF;
|
||||||
|
@ -34,17 +31,22 @@ public enum Sizes implements Size {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getShadowSize() {
|
public int colorCode() {
|
||||||
|
return triggerValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float shadowSize() {
|
||||||
return shadowSize * PonyConfig.getInstance().getGlobalScaleFactor();
|
return shadowSize * PonyConfig.getInstance().getGlobalScaleFactor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getScaleFactor() {
|
public float scaleFactor() {
|
||||||
return scale * PonyConfig.getInstance().getGlobalScaleFactor();
|
return scale * PonyConfig.getInstance().getGlobalScaleFactor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getEyeHeightFactor() {
|
public float eyeHeightFactor() {
|
||||||
if (!PonyConfig.getInstance().fillycam.get()) {
|
if (!PonyConfig.getInstance().fillycam.get()) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -52,26 +54,7 @@ public enum Sizes implements Size {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getEyeDistanceFactor() {
|
public float eyeDistanceFactor() {
|
||||||
if (!PonyConfig.getInstance().fillycam.get()) {
|
return eyeHeightFactor();
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return camera * PonyConfig.getInstance().getGlobalScaleFactor();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getColorCode() {
|
|
||||||
return triggerValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Sizes of(Size size) {
|
|
||||||
if (size instanceof Sizes) {
|
|
||||||
return (Sizes)size;
|
|
||||||
}
|
|
||||||
int i = size.ordinal();
|
|
||||||
if (i < 0 || i >= REGISTRY.length) {
|
|
||||||
return UNSET;
|
|
||||||
}
|
|
||||||
return REGISTRY[i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
66
src/main/java/com/minelittlepony/api/pony/meta/TValue.java
Normal file
66
src/main/java/com/minelittlepony/api/pony/meta/TValue.java
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
package com.minelittlepony.api.pony.meta;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for enums that can be parsed from an image trigger pixel value.
|
||||||
|
*/
|
||||||
|
public interface TValue<T> {
|
||||||
|
/**
|
||||||
|
* Gets the pixel colour matching this enum value.
|
||||||
|
*/
|
||||||
|
int colorCode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the pixel colour matching this enum value, adjusted to fill all three channels.
|
||||||
|
*/
|
||||||
|
default int getChannelAdjustedColorCode() {
|
||||||
|
return colorCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a string representation of this value.
|
||||||
|
*/
|
||||||
|
String name();
|
||||||
|
|
||||||
|
default String getHexValue() {
|
||||||
|
return toHex(colorCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of possible values this trigger pixel can accept.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
default List<TValue<T>> getOptions() {
|
||||||
|
if (this instanceof Enum) {
|
||||||
|
// cast is required because gradle's compiler is more strict
|
||||||
|
return Arrays.asList(getClass().getEnumConstants());
|
||||||
|
}
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean matches(TValue<?> o) {
|
||||||
|
return o != null && colorCode() == o.colorCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
static String toHex(int color) {
|
||||||
|
String v = Integer.toHexString(color).toUpperCase();
|
||||||
|
while (v.length() < 6) {
|
||||||
|
v = "0" + v;
|
||||||
|
}
|
||||||
|
return "#" + v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Numeric(int colorCode) implements TValue<Integer> {
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "[Numeric " + getHexValue() + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TValue<Integer>> getOptions() {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
package com.minelittlepony.api.pony.meta;
|
package com.minelittlepony.api.pony.meta;
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.TriggerPixelType;
|
public enum TailLength implements TValue<TailLength> {
|
||||||
|
|
||||||
public enum TailLength implements TriggerPixelType<TailLength> {
|
|
||||||
STUB (0x425844),
|
STUB (0x425844),
|
||||||
QUARTER (0xd19fe4),
|
QUARTER (0xd19fe4),
|
||||||
HALF (0x534b76),
|
HALF (0x534b76),
|
||||||
|
@ -16,7 +14,7 @@ public enum TailLength implements TriggerPixelType<TailLength> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getColorCode() {
|
public int colorCode() {
|
||||||
return triggerValue;
|
return triggerValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package com.minelittlepony.api.pony.meta;
|
package com.minelittlepony.api.pony.meta;
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.TriggerPixelType;
|
public enum TailShape implements TValue<TailShape> {
|
||||||
|
|
||||||
public enum TailShape implements TriggerPixelType<TailShape> {
|
|
||||||
STRAIGHT(0),
|
STRAIGHT(0),
|
||||||
BUMPY (0xfc539f),
|
BUMPY (0xfc539f),
|
||||||
SWIRLY (0x3eff22),
|
SWIRLY (0x3eff22),
|
||||||
|
@ -15,7 +13,7 @@ public enum TailShape implements TriggerPixelType<TailShape> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getColorCode() {
|
public int colorCode() {
|
||||||
return triggerValue;
|
return triggerValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,115 +1,92 @@
|
||||||
package com.minelittlepony.api.pony.meta;
|
package com.minelittlepony.api.pony.meta;
|
||||||
|
|
||||||
import net.minecraft.client.texture.NativeImage;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
import net.minecraft.util.math.ColorHelper;
|
||||||
|
|
||||||
|
import org.joml.Vector2i;
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.TriggerPixelSet;
|
|
||||||
import com.minelittlepony.api.pony.TriggerPixelType;
|
|
||||||
import com.minelittlepony.api.pony.TriggerPixelValue;
|
|
||||||
import com.minelittlepony.common.util.Color;
|
import com.minelittlepony.common.util.Color;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Individual trigger pixels for a pony skin.
|
* Individual trigger pixels for a pony skin.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
public interface TriggerPixel<T> {
|
||||||
public enum TriggerPixel {
|
Vector2i MAX_COORDS = new Vector2i();
|
||||||
RACE(Race.HUMAN, Channel.ALL, 0, 0),
|
|
||||||
TAIL(TailLength.FULL, Channel.ALL, 1, 0),
|
|
||||||
GENDER(Gender.MARE, Channel.ALL, 2, 0),
|
|
||||||
SIZE(Sizes.NORMAL, Channel.ALL, 3, 0),
|
|
||||||
GLOW(null, Channel.RAW, 0, 1),
|
|
||||||
WEARABLES(Wearable.NONE, Channel.RAW, 1, 1),
|
|
||||||
TAIL_SHAPE(TailShape.STRAIGHT, Channel.ALL, 2, 1);
|
|
||||||
|
|
||||||
private int x;
|
TriggerPixel<Race> RACE = ofOptions(0, 0, Race.HUMAN, Race.values());
|
||||||
private int y;
|
TriggerPixel<TailLength> TAIL = ofOptions(1, 0, TailLength.FULL, TailLength.values());
|
||||||
|
TriggerPixel<Gender> GENDER = ofOptions(2, 0, Gender.MARE, Gender.values());
|
||||||
|
TriggerPixel<TailShape> TAIL_SHAPE = ofOptions(2, 1, TailShape.STRAIGHT, TailShape.values());
|
||||||
|
TriggerPixel<Size> SIZE = ofOptions(3, 0, SizePreset.NORMAL, SizePreset.values());
|
||||||
|
TriggerPixel<Integer> GLOW = ofColor(0, 1);
|
||||||
|
TriggerPixel<Flags<Wearable>> WEARABLES = ofFlags(1, 1, Wearable.EMPTY_FLAGS, Wearable.values());
|
||||||
|
TriggerPixel<Integer> PRIORITY = ofColor(2, 2);
|
||||||
|
|
||||||
private Channel channel;
|
static <T extends TValue<T>> TriggerPixel<T> ofOptions(int x, int y, T def, T[] options) {
|
||||||
|
MAX_COORDS.x = Math.max(MAX_COORDS.x, x);
|
||||||
|
MAX_COORDS.y = Math.max(MAX_COORDS.y, y);
|
||||||
|
Int2ObjectOpenHashMap<T> lookup = buildLookup(options);
|
||||||
|
return image -> {
|
||||||
|
int color = Color.abgrToArgb(image.getColor(x, y));
|
||||||
|
|
||||||
TriggerPixelType<?> def;
|
if (ColorHelper.Argb.getAlpha(color) < 255) {
|
||||||
|
return (T)def;
|
||||||
private static final TriggerPixel[] VALUES = values();
|
}
|
||||||
private static final int MAX_READ_X = Arrays.stream(VALUES).mapToInt(i -> i.x).max().getAsInt();
|
return lookup.getOrDefault(color & 0x00FFFFFF, def);
|
||||||
private static final int MAX_READ_Y = Arrays.stream(VALUES).mapToInt(i -> i.y).max().getAsInt();
|
};
|
||||||
|
|
||||||
TriggerPixel(TriggerPixelType<?> def, Channel channel, int x, int y) {
|
|
||||||
this.def = def;
|
|
||||||
this.channel = channel;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static TriggerPixel<Integer> ofColor(int x, int y) {
|
||||||
* Reads this trigger pixel's value and returns the raw colour.
|
MAX_COORDS.x = Math.max(MAX_COORDS.x, x);
|
||||||
*
|
MAX_COORDS.y = Math.max(MAX_COORDS.y, y);
|
||||||
* @param image Image to read
|
return image -> Color.abgrToArgb(image.getColor(x, y));
|
||||||
*/
|
|
||||||
public int readColor(NativeImage image) {
|
|
||||||
return channel.readValue(x, y, image);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static <T extends Enum<T> & TValue<T>> TriggerPixel<Flags<T>> ofFlags(int x, int y, Flags<T> def, T[] options) {
|
||||||
* Reads this trigger pixel's value and parses it to an Enum instance.
|
MAX_COORDS.x = Math.max(MAX_COORDS.x, x);
|
||||||
*
|
MAX_COORDS.y = Math.max(MAX_COORDS.y, y);
|
||||||
* @param image Image to read
|
Int2ObjectOpenHashMap<T> lookup = buildLookup(options);
|
||||||
*/
|
var flagReader = new Object() {
|
||||||
public <T extends TriggerPixelType<T>> TriggerPixelValue<T> readValue(NativeImage image) {
|
boolean readFlag(int color, Set<T> values) {
|
||||||
int color = readColor(image);
|
T value = lookup.get(color);
|
||||||
|
return value != null && values.add(value);
|
||||||
if (Channel.ALPHA.readValue(x, y, image) < 255) {
|
}
|
||||||
return new TriggerPixelValue<>(color, (T)def);
|
};
|
||||||
|
return image -> {
|
||||||
|
int color = Color.abgrToArgb(image.getColor(x, y));
|
||||||
|
if (ColorHelper.Argb.getAlpha(color) < 255) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Set<T> values = EnumSet.noneOf((Class<T>)def.def().getClass());
|
||||||
|
if (flagReader.readFlag(ColorHelper.Argb.getRed(color), values)
|
||||||
|
| flagReader.readFlag(ColorHelper.Argb.getGreen(color), values)
|
||||||
|
| flagReader.readFlag(ColorHelper.Argb.getBlue(color), values)) {
|
||||||
|
return new Flags<>(def.def(), values, color & 0x00FFFFFF);
|
||||||
|
}
|
||||||
|
return def;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TriggerPixelValue<>(color, TriggerPixelType.getByTriggerPixel((T)def, color));
|
static <T extends TValue<T>> Int2ObjectOpenHashMap<T> buildLookup(T[] options) {
|
||||||
|
Int2ObjectOpenHashMap<T> lookup = new Int2ObjectOpenHashMap<>();
|
||||||
|
for (int i = 0; i < options.length; i++) {
|
||||||
|
lookup.put(options[i].colorCode(), options[i]);
|
||||||
|
}
|
||||||
|
return lookup;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends Enum<T> & TriggerPixelType<T>> TriggerPixelSet<T> readFlags(NativeImage image) {
|
|
||||||
boolean[] out = new boolean[def.getClass().getEnumConstants().length];
|
T read(Mat image);
|
||||||
readFlags(out, image);
|
|
||||||
return new TriggerPixelSet<>(readColor(image), (T)def, out);
|
static boolean isTriggerPixelCoord(int x, int y) {
|
||||||
|
return x <= MAX_COORDS.x && y <= MAX_COORDS.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends Enum<T> & TriggerPixelType<T>> void readFlags(boolean[] out, NativeImage image) {
|
interface Mat {
|
||||||
readFlag(out, Channel.RED, image);
|
int getColor(int x, int y);
|
||||||
readFlag(out, Channel.GREEN, image);
|
|
||||||
readFlag(out, Channel.BLUE, image);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends Enum<T> & TriggerPixelType<T>> void readFlag(boolean[] out, Channel channel, NativeImage image) {
|
|
||||||
|
|
||||||
if (Channel.ALPHA.readValue(x, y, image) < 255) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
T value = TriggerPixelType.getByTriggerPixel((T)def, channel.readValue(x, y, image));
|
|
||||||
|
|
||||||
out[value.ordinal()] |= value != def;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isTriggerPixelCoord(int x, int y) {
|
|
||||||
return x <= MAX_READ_X && y <= MAX_READ_Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Channel {
|
|
||||||
RAW (0xFFFFFFFF, 0),
|
|
||||||
ALL (0x00FFFFFF, 0),
|
|
||||||
ALPHA(0x000000FF, 24),
|
|
||||||
RED (0x000000FF, 0),
|
|
||||||
GREEN(0x000000FF, 8),
|
|
||||||
BLUE (0x000000FF, 16);
|
|
||||||
|
|
||||||
private int mask;
|
|
||||||
private int offset;
|
|
||||||
|
|
||||||
Channel(int mask, int offset) {
|
|
||||||
this.mask = mask;
|
|
||||||
this.offset = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int readValue(int x, int y, NativeImage image) {
|
|
||||||
return (Color.abgrToArgb(image.getColor(x, y)) >> offset) & mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,31 @@
|
||||||
package com.minelittlepony.api.pony.meta;
|
package com.minelittlepony.api.pony.meta;
|
||||||
|
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.ColorHelper;
|
||||||
import com.minelittlepony.api.pony.TriggerPixelType;
|
|
||||||
import com.minelittlepony.client.model.gear.SaddleBags;
|
|
||||||
import com.minelittlepony.common.util.Color;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public enum Wearable implements TriggerPixelType<Wearable> {
|
public enum Wearable implements TValue<Wearable> {
|
||||||
NONE (0x00, null),
|
NONE (0x00, null),
|
||||||
CROWN (0x16, new Identifier("minelittlepony", "textures/models/crown.png")),
|
CROWN (0x16, new Identifier("minelittlepony", "textures/models/crown.png")),
|
||||||
MUFFIN (0x32, new Identifier("minelittlepony", "textures/models/muffin.png")),
|
MUFFIN (0x32, new Identifier("minelittlepony", "textures/models/muffin.png")),
|
||||||
HAT (0x64, new Identifier("textures/entity/witch.png")),
|
HAT (0x64, new Identifier("textures/entity/witch.png")),
|
||||||
ANTLERS (0x96, new Identifier("minelittlepony", "textures/models/antlers.png")),
|
ANTLERS (0x96, new Identifier("minelittlepony", "textures/models/antlers.png")),
|
||||||
SADDLE_BAGS_LEFT (0xC6, SaddleBags.TEXTURE),
|
SADDLE_BAGS_LEFT (0xC6, new Identifier("minelittlepony", "textures/models/saddlebags.png")),
|
||||||
SADDLE_BAGS_RIGHT (0xC7, SaddleBags.TEXTURE),
|
SADDLE_BAGS_RIGHT (0xC7, new Identifier("minelittlepony", "textures/models/saddlebags.png")),
|
||||||
SADDLE_BAGS_BOTH (0xC8, SaddleBags.TEXTURE),
|
SADDLE_BAGS_BOTH (0xC8, new Identifier("minelittlepony", "textures/models/saddlebags.png")),
|
||||||
STETSON (0xFA, new Identifier("minelittlepony", "textures/models/stetson.png"));
|
STETSON (0xFA, new Identifier("minelittlepony", "textures/models/stetson.png"));
|
||||||
|
|
||||||
private int triggerValue;
|
private int triggerValue;
|
||||||
|
|
||||||
private final Identifier id;
|
private final Identifier id;
|
||||||
|
|
||||||
private final Identifier texture;
|
private final Identifier texture;
|
||||||
|
|
||||||
public static final List<Wearable> VALUES = Arrays.stream(values()).toList();
|
public static final Map<Identifier, Wearable> REGISTRY = Arrays.stream(values()).collect(Collectors.toMap(Wearable::getId, Function.identity()));
|
||||||
public static final Map<Identifier, Wearable> REGISTRY = VALUES.stream().collect(Collectors.toMap(Wearable::getId, Function.identity()));
|
|
||||||
|
public static final Flags<Wearable> EMPTY_FLAGS = Flags.of(NONE);
|
||||||
|
|
||||||
Wearable(int pixel, Identifier texture) {
|
Wearable(int pixel, Identifier texture) {
|
||||||
triggerValue = pixel;
|
triggerValue = pixel;
|
||||||
|
@ -45,7 +42,7 @@ public enum Wearable implements TriggerPixelType<Wearable> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getColorCode() {
|
public int colorCode() {
|
||||||
return triggerValue;
|
return triggerValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,22 +52,6 @@ public enum Wearable implements TriggerPixelType<Wearable> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getChannelAdjustedColorCode() {
|
public int getChannelAdjustedColorCode() {
|
||||||
return triggerValue == 0 ? 0 : Color.argbToHex(255, triggerValue, triggerValue, triggerValue);
|
return triggerValue == 0 ? 0 : ColorHelper.Argb.getArgb(255, triggerValue, triggerValue, triggerValue);
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean[] flags(Wearable[] wears) {
|
|
||||||
boolean[] flags = new boolean[VALUES.size()];
|
|
||||||
for (int i = 0; i < wears.length; i++) {
|
|
||||||
flags[wears[i].ordinal()] = true;
|
|
||||||
}
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Wearable[] flags(boolean[] flags) {
|
|
||||||
List<Wearable> wears = new ArrayList<>();
|
|
||||||
for (int i = 0; i < VALUES.size(); i++) {
|
|
||||||
if (flags[i]) wears.add(VALUES.get(i));
|
|
||||||
}
|
|
||||||
return wears.toArray(new Wearable[0]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,255 +0,0 @@
|
||||||
package com.minelittlepony.api.pony.network;
|
|
||||||
|
|
||||||
import net.minecraft.network.PacketByteBuf;
|
|
||||||
import net.minecraft.util.Util;
|
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
|
||||||
import com.google.common.base.Suppliers;
|
|
||||||
import com.minelittlepony.api.pony.IPonyData;
|
|
||||||
import com.minelittlepony.api.pony.TriggerPixelType;
|
|
||||||
import com.minelittlepony.api.pony.meta.*;
|
|
||||||
import com.minelittlepony.common.util.animation.Interpolator;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public class MsgPonyData implements IPonyData {
|
|
||||||
private static final short API_IDENTIFIER = (short) 0xABCD;
|
|
||||||
// API version - increment this number before any time any data is added/removed/moved in the data stream
|
|
||||||
private static final byte API_VERSION = 2;
|
|
||||||
|
|
||||||
private final Race race;
|
|
||||||
private final TailLength tailLength;
|
|
||||||
private final TailShape tailShape;
|
|
||||||
private final Gender gender;
|
|
||||||
private final Size size;
|
|
||||||
private final int glowColor;
|
|
||||||
|
|
||||||
private final boolean noSkin;
|
|
||||||
|
|
||||||
private final int wearableColor;
|
|
||||||
private final boolean[] wearables;
|
|
||||||
|
|
||||||
private final Supplier<Map<String, TriggerPixelType<?>>> triggerPixels = Suppliers.memoize(() -> Util.make(new TreeMap<>(), this::initTriggerPixels));
|
|
||||||
private void initTriggerPixels(Map<String, TriggerPixelType<?>> map) {
|
|
||||||
map.put("race", race);
|
|
||||||
map.put("tailLength", tailLength);
|
|
||||||
map.put("tailShape", tailShape);
|
|
||||||
map.put("gender", gender);
|
|
||||||
map.put("size", size);
|
|
||||||
map.put("magic", TriggerPixelType.of(glowColor));
|
|
||||||
map.put("gear", TriggerPixelType.of(wearableColor));
|
|
||||||
}
|
|
||||||
|
|
||||||
public MsgPonyData(PacketByteBuf buffer) {
|
|
||||||
short data = buffer.readShort();
|
|
||||||
if (data != API_IDENTIFIER || buffer.readByte() != API_VERSION) {
|
|
||||||
race = null;
|
|
||||||
tailLength = null;
|
|
||||||
tailShape = null;
|
|
||||||
gender = null;
|
|
||||||
size = null;
|
|
||||||
glowColor = 0;
|
|
||||||
noSkin = true;
|
|
||||||
wearables = null;
|
|
||||||
wearableColor = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
race = buffer.readEnumConstant(Race.class);
|
|
||||||
tailLength = buffer.readEnumConstant(TailLength.class);
|
|
||||||
tailShape = buffer.readEnumConstant(TailShape.class);
|
|
||||||
gender = buffer.readEnumConstant(Gender.class);
|
|
||||||
size = new MsgSize(buffer);
|
|
||||||
glowColor = buffer.readInt();
|
|
||||||
noSkin = buffer.readBoolean();
|
|
||||||
Wearable[] gear = new Wearable[buffer.readInt()];
|
|
||||||
Wearable[] all = Wearable.values();
|
|
||||||
for (int i = 0; i < gear.length; i++) {
|
|
||||||
gear[i] = all[buffer.readInt()];
|
|
||||||
}
|
|
||||||
wearables = Wearable.flags(gear);
|
|
||||||
wearableColor = buffer.readInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MsgPonyData(IPonyData data, boolean noSkin) {
|
|
||||||
race = data.getRace();
|
|
||||||
tailLength = data.getTailLength();
|
|
||||||
tailShape = data.getTailShape();
|
|
||||||
gender = data.getGender();
|
|
||||||
size = data.getSize();
|
|
||||||
glowColor = data.getGlowColor();
|
|
||||||
wearables = Wearable.flags(data.getGear());
|
|
||||||
wearableColor = data.getTriggerPixels().get("gear").getColorCode();
|
|
||||||
this.noSkin = noSkin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PacketByteBuf toBuffer(PacketByteBuf buffer) {
|
|
||||||
buffer.writeShort(API_IDENTIFIER);
|
|
||||||
buffer.writeByte(API_VERSION);
|
|
||||||
buffer.writeEnumConstant(race);
|
|
||||||
buffer.writeEnumConstant(tailLength);
|
|
||||||
buffer.writeEnumConstant(tailShape);
|
|
||||||
buffer.writeEnumConstant(gender);
|
|
||||||
new MsgSize(size).toBuffer(buffer);
|
|
||||||
buffer.writeInt(glowColor);
|
|
||||||
buffer.writeBoolean(noSkin);
|
|
||||||
|
|
||||||
Wearable[] gear = getGear();
|
|
||||||
buffer.writeInt(gear.length);
|
|
||||||
for (int i = 0; i < gear.length; i++) {
|
|
||||||
buffer.writeInt(gear[i].ordinal());
|
|
||||||
}
|
|
||||||
buffer.writeInt(wearableColor);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isNoSkin() {
|
|
||||||
return noSkin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Race getRace() {
|
|
||||||
return race;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TailLength getTailLength() {
|
|
||||||
return tailLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TailShape getTailShape() {
|
|
||||||
return tailShape;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Gender getGender() {
|
|
||||||
return gender;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Size getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getGlowColor() {
|
|
||||||
return glowColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Wearable[] getGear() {
|
|
||||||
return Wearable.flags(wearables);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isWearing(Wearable wearable) {
|
|
||||||
return wearables[wearable.ordinal()];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Interpolator getInterpolator(UUID interpolatorId) {
|
|
||||||
return Interpolator.linear(interpolatorId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, TriggerPixelType<?>> getTriggerPixels() {
|
|
||||||
return triggerPixels.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return MoreObjects.toStringHelper(this)
|
|
||||||
.add("race", race)
|
|
||||||
.add("tailLength", tailLength)
|
|
||||||
.add("tailShape", tailShape)
|
|
||||||
.add("gender", gender)
|
|
||||||
.add("size", size)
|
|
||||||
.add("wearables", getGear())
|
|
||||||
.add("glowColor", TriggerPixelType.toHex(glowColor))
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class MsgSize implements Size {
|
|
||||||
|
|
||||||
private final int ordinal;
|
|
||||||
private final String name;
|
|
||||||
private final float shadow;
|
|
||||||
private final float scale;
|
|
||||||
private final float eyeHeight;
|
|
||||||
private final float eyeDistance;
|
|
||||||
private final int triggerPixel;
|
|
||||||
|
|
||||||
MsgSize(Size size) {
|
|
||||||
ordinal = size.ordinal();
|
|
||||||
name = size.name();
|
|
||||||
shadow = size.getShadowSize();
|
|
||||||
scale = size.getScaleFactor();
|
|
||||||
eyeHeight = size.getEyeHeightFactor();
|
|
||||||
eyeDistance = size.getEyeDistanceFactor();
|
|
||||||
triggerPixel = size.getColorCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
MsgSize(PacketByteBuf buffer) {
|
|
||||||
ordinal = buffer.readInt();
|
|
||||||
name = buffer.readString(32767);
|
|
||||||
shadow = buffer.readFloat();
|
|
||||||
scale = buffer.readFloat();
|
|
||||||
eyeHeight = buffer.readFloat();
|
|
||||||
eyeDistance = buffer.readFloat();
|
|
||||||
triggerPixel = buffer.readInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toBuffer(PacketByteBuf buffer) {
|
|
||||||
buffer.writeInt(ordinal);
|
|
||||||
buffer.writeString(name);
|
|
||||||
buffer.writeFloat(shadow);
|
|
||||||
buffer.writeFloat(scale);
|
|
||||||
buffer.writeFloat(eyeHeight);
|
|
||||||
buffer.writeFloat(eyeDistance);
|
|
||||||
buffer.writeFloat(triggerPixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int ordinal() {
|
|
||||||
return ordinal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String name() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getShadowSize() {
|
|
||||||
return shadow;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getScaleFactor() {
|
|
||||||
return scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getEyeHeightFactor() {
|
|
||||||
return eyeHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getEyeDistanceFactor() {
|
|
||||||
return eyeDistance;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getColorCode() {
|
|
||||||
return triggerPixel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,8 @@ import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.util.hit.HitResult;
|
import net.minecraft.util.hit.HitResult;
|
||||||
import net.minecraft.util.math.*;
|
import net.minecraft.util.math.*;
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.IPony;
|
import com.minelittlepony.api.config.PonyConfig;
|
||||||
|
import com.minelittlepony.api.pony.Pony;
|
||||||
import com.minelittlepony.common.util.settings.Setting;
|
import com.minelittlepony.common.util.settings.Setting;
|
||||||
|
|
||||||
public class HorseCam {
|
public class HorseCam {
|
||||||
|
@ -31,7 +32,7 @@ public class HorseCam {
|
||||||
*/
|
*/
|
||||||
public static float transformCameraAngle(float pitch) {
|
public static float transformCameraAngle(float pitch) {
|
||||||
|
|
||||||
if (!MineLittlePony.getInstance().getConfig().fillycam.get()) {
|
if (!PonyConfig.getInstance().fillycam.get()) {
|
||||||
return pitch;
|
return pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,10 +49,10 @@ public class HorseCam {
|
||||||
return pitch;
|
return pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPony pony = IPony.getManager().getPony(player);
|
Pony pony = Pony.getManager().getPony(player);
|
||||||
|
|
||||||
if (!pony.race().isHuman()) {
|
if (!pony.race().isHuman()) {
|
||||||
Setting<Boolean> fillyCam = MineLittlePony.getInstance().getConfig().fillycam;
|
Setting<Boolean> fillyCam = PonyConfig.getInstance().fillycam;
|
||||||
|
|
||||||
fillyCam.set(false);
|
fillyCam.set(false);
|
||||||
final float vanillaHeight = player.getEyeHeight(player.getPose());
|
final float vanillaHeight = player.getEyeHeight(player.getPose());
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
package com.minelittlepony.client;
|
|
||||||
|
|
||||||
public interface IPreviewModel {
|
|
||||||
|
|
||||||
}
|
|
|
@ -13,7 +13,6 @@ import static com.minelittlepony.common.event.SkinFilterCallback.copy;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class LegacySkinConverter implements SkinFilterCallback {
|
class LegacySkinConverter implements SkinFilterCallback {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processImage(NativeImage image, boolean legacy) {
|
public void processImage(NativeImage image, boolean legacy) {
|
||||||
if (legacy) {
|
if (legacy) {
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
package com.minelittlepony.client;
|
package com.minelittlepony.client;
|
||||||
|
|
||||||
import com.minelittlepony.api.config.PonyConfig;
|
import com.minelittlepony.api.config.PonyConfig;
|
||||||
import com.minelittlepony.api.pony.network.fabric.Channel;
|
import com.minelittlepony.api.events.Channel;
|
||||||
import com.minelittlepony.client.model.ModelType;
|
import com.minelittlepony.client.model.ModelType;
|
||||||
import com.minelittlepony.client.pony.PonyManager;
|
import com.minelittlepony.client.model.armour.ArmourTextureResolver;
|
||||||
import com.minelittlepony.client.pony.VariatedTextureSupplier;
|
import com.minelittlepony.client.render.MobRenderers;
|
||||||
import com.minelittlepony.client.render.PonyRenderDispatcher;
|
import com.minelittlepony.client.render.PonyRenderDispatcher;
|
||||||
import com.minelittlepony.client.settings.ClientPonyConfig;
|
|
||||||
import com.minelittlepony.common.client.gui.VisibilityMode;
|
import com.minelittlepony.common.client.gui.VisibilityMode;
|
||||||
import com.minelittlepony.common.client.gui.element.Button;
|
import com.minelittlepony.common.client.gui.element.Button;
|
||||||
import com.minelittlepony.common.client.gui.sprite.TextureSprite;
|
import com.minelittlepony.common.client.gui.sprite.TextureSprite;
|
||||||
|
@ -15,6 +14,8 @@ import com.minelittlepony.common.event.ScreenInitCallback;
|
||||||
import com.minelittlepony.common.event.SkinFilterCallback;
|
import com.minelittlepony.common.event.SkinFilterCallback;
|
||||||
import com.minelittlepony.common.util.GamePaths;
|
import com.minelittlepony.common.util.GamePaths;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||||
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||||
|
@ -25,6 +26,7 @@ import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.gui.screen.TitleScreen;
|
import net.minecraft.client.gui.screen.TitleScreen;
|
||||||
import net.minecraft.client.option.KeyBinding;
|
import net.minecraft.client.option.KeyBinding;
|
||||||
import net.minecraft.client.util.InputUtil;
|
import net.minecraft.client.util.InputUtil;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.resource.ResourceType;
|
import net.minecraft.resource.ResourceType;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
@ -40,14 +42,13 @@ public class MineLittlePony implements ClientModInitializer {
|
||||||
|
|
||||||
public static final Logger logger = LogManager.getLogger("MineLittlePony");
|
public static final Logger logger = LogManager.getLogger("MineLittlePony");
|
||||||
|
|
||||||
private final PonyRenderDispatcher renderManager = PonyRenderDispatcher.getInstance();
|
private PonyManagerImpl ponyManager;
|
||||||
|
|
||||||
private ClientPonyConfig config;
|
|
||||||
private PonyManager ponyManager;
|
|
||||||
private VariatedTextureSupplier variatedTextures;
|
private VariatedTextureSupplier variatedTextures;
|
||||||
|
|
||||||
private final KeyBinding keyBinding = new KeyBinding("key.minelittlepony.settings", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_F9, "key.categories.misc");
|
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 hasHdSkins;
|
private boolean hasHdSkins;
|
||||||
private boolean hasModMenu;
|
private boolean hasModMenu;
|
||||||
|
|
||||||
|
@ -67,8 +68,8 @@ public class MineLittlePony implements ClientModInitializer {
|
||||||
hasHdSkins = FabricLoader.getInstance().isModLoaded("hdskins");
|
hasHdSkins = FabricLoader.getInstance().isModLoaded("hdskins");
|
||||||
hasModMenu = FabricLoader.getInstance().isModLoaded("modmenu");
|
hasModMenu = FabricLoader.getInstance().isModLoaded("modmenu");
|
||||||
|
|
||||||
config = new ClientPonyConfig(GamePaths.getConfigDirectory().resolve("minelp.json"));
|
PonyConfig config = new ClientPonyConfig(GamePaths.getConfigDirectory().resolve("minelp.json"));
|
||||||
ponyManager = new PonyManager(config);
|
ponyManager = new PonyManagerImpl(config);
|
||||||
variatedTextures = new VariatedTextureSupplier();
|
variatedTextures = new VariatedTextureSupplier();
|
||||||
|
|
||||||
KeyBindingHelper.registerKeyBinding(keyBinding);
|
KeyBindingHelper.registerKeyBinding(keyBinding);
|
||||||
|
@ -82,7 +83,9 @@ public class MineLittlePony implements ClientModInitializer {
|
||||||
// general events
|
// general events
|
||||||
ClientReadyCallback.Handler.register();
|
ClientReadyCallback.Handler.register();
|
||||||
ClientTickEvents.END_CLIENT_TICK.register(this::onTick);
|
ClientTickEvents.END_CLIENT_TICK.register(this::onTick);
|
||||||
ClientReadyCallback.EVENT.register(this::onClientReady);
|
ClientReadyCallback.EVENT.register(client -> {
|
||||||
|
renderDispatcher.initialise(client.getEntityRenderDispatcher(), false);
|
||||||
|
});
|
||||||
ScreenInitCallback.EVENT.register(this::onScreenInit);
|
ScreenInitCallback.EVENT.register(this::onScreenInit);
|
||||||
|
|
||||||
config.load();
|
config.load();
|
||||||
|
@ -93,10 +96,6 @@ public class MineLittlePony implements ClientModInitializer {
|
||||||
FabricLoader.getInstance().getEntrypoints("minelittlepony", ClientModInitializer.class).forEach(ClientModInitializer::onInitializeClient);
|
FabricLoader.getInstance().getEntrypoints("minelittlepony", ClientModInitializer.class).forEach(ClientModInitializer::onInitializeClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onClientReady(MinecraftClient client) {
|
|
||||||
renderManager.initialise(client.getEntityRenderDispatcher());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onTick(MinecraftClient client) {
|
private void onTick(MinecraftClient client) {
|
||||||
|
|
||||||
boolean inGame = client.world != null && client.player != null && client.currentScreen == null;
|
boolean inGame = client.world != null && client.player != null && client.currentScreen == null;
|
||||||
|
@ -107,13 +106,13 @@ public class MineLittlePony implements ClientModInitializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mainMenu || inGame) && keyBinding.isPressed()) {
|
if ((mainMenu || inGame) && keyBinding.isPressed()) {
|
||||||
client.setScreen(new GuiPonySettings(client.currentScreen));
|
client.setScreen(new PonySettingsScreen(client.currentScreen));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onScreenInit(Screen screen, ScreenInitCallback.ButtonList buttons) {
|
private void onScreenInit(Screen screen, ScreenInitCallback.ButtonList buttons) {
|
||||||
if (screen instanceof TitleScreen) {
|
if (screen instanceof TitleScreen) {
|
||||||
VisibilityMode mode = config.horseButton.get();
|
VisibilityMode mode = ClientPonyConfig.getInstance().horseButton.get();
|
||||||
boolean show = mode == VisibilityMode.ON || (mode == VisibilityMode.AUTO
|
boolean show = mode == VisibilityMode.ON || (mode == VisibilityMode.AUTO
|
||||||
&& !(hasHdSkins || hasModMenu
|
&& !(hasHdSkins || hasModMenu
|
||||||
));
|
));
|
||||||
|
@ -121,7 +120,7 @@ public class MineLittlePony implements ClientModInitializer {
|
||||||
if (show) {
|
if (show) {
|
||||||
int y = hasHdSkins ? 75 : 50;
|
int y = hasHdSkins ? 75 : 50;
|
||||||
Button button = buttons.addButton(new Button(screen.width - 50, screen.height - y, 20, 20))
|
Button button = buttons.addButton(new Button(screen.width - 50, screen.height - y, 20, 20))
|
||||||
.onClick(sender -> MinecraftClient.getInstance().setScreen(new GuiPonySettings(screen)));
|
.onClick(sender -> MinecraftClient.getInstance().setScreen(new PonySettingsScreen(screen)));
|
||||||
button.getStyle()
|
button.getStyle()
|
||||||
.setIcon(new TextureSprite()
|
.setIcon(new TextureSprite()
|
||||||
.setPosition(2, 2)
|
.setPosition(2, 2)
|
||||||
|
@ -134,19 +133,36 @@ public class MineLittlePony implements ClientModInitializer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public PonyManagerImpl getManager() {
|
||||||
* Gets the global MineLP client configuration.
|
|
||||||
*/
|
|
||||||
public PonyConfig getConfig() {
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PonyManager getManager() {
|
|
||||||
return ponyManager;
|
return ponyManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public VariatedTextureSupplier getVariatedTextures() {
|
public VariatedTextureSupplier getVariatedTextures() {
|
||||||
return variatedTextures;
|
return variatedTextures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the static pony render manager responsible for all entity renderers.
|
||||||
|
*/
|
||||||
|
public PonyRenderDispatcher getRenderDispatcher() {
|
||||||
|
return renderDispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class ClientPonyConfig extends PonyConfig {
|
||||||
|
public ClientPonyConfig(Path path) {
|
||||||
|
super(path);
|
||||||
|
MobRenderers.REGISTRY.values().forEach(r -> value("entities", r.name, true));
|
||||||
|
disablePonifiedArmour.onChanged(t -> ArmourTextureResolver.INSTANCE.invalidate());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save() {
|
||||||
|
super.save();
|
||||||
|
PlayerEntity player = MinecraftClient.getInstance().player;
|
||||||
|
if (player != null) {
|
||||||
|
player.calculateDimensions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.minelittlepony.client;
|
package com.minelittlepony.client;
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.IPony;
|
import com.minelittlepony.api.pony.Pony;
|
||||||
import com.minelittlepony.api.pony.PonyPosture;
|
import com.minelittlepony.api.pony.PonyPosture;
|
||||||
import com.minelittlepony.client.transform.PonyTransformation;
|
import com.minelittlepony.client.transform.PonyTransformation;
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@ public class PonyBounds {
|
||||||
return PonyPosture.getMountPony(entity).map(ridingPony -> {
|
return PonyPosture.getMountPony(entity).map(ridingPony -> {
|
||||||
LivingEntity vehicle = (LivingEntity)entity.getVehicle();
|
LivingEntity vehicle = (LivingEntity)entity.getVehicle();
|
||||||
|
|
||||||
Vec3d offset = PonyTransformation.forSize(ridingPony.metadata().getSize()).getRiderOffset();
|
Vec3d offset = PonyTransformation.forSize(ridingPony.size()).getRiderOffset();
|
||||||
float scale = ridingPony.metadata().getSize().getScaleFactor();
|
float scale = ridingPony.metadata().size().scaleFactor();
|
||||||
|
|
||||||
return getAbsoluteRidingOffset(vehicle).add(
|
return getAbsoluteRidingOffset(vehicle).add(
|
||||||
0,
|
0,
|
||||||
|
@ -31,7 +31,7 @@ public class PonyBounds {
|
||||||
float delta = MinecraftClient.getInstance().getTickDelta();
|
float delta = MinecraftClient.getInstance().getTickDelta();
|
||||||
|
|
||||||
Entity vehicle = entity.getVehicle();
|
Entity vehicle = entity.getVehicle();
|
||||||
double vehicleOffset = vehicle == null ? 0 : vehicle.getHeight() - vehicle.getMountedHeightOffset();
|
double vehicleOffset = vehicle == null ? 0 : vehicle.getHeight();
|
||||||
|
|
||||||
return new Vec3d(
|
return new Vec3d(
|
||||||
MathHelper.lerp(delta, entity.prevX, entity.getX()),
|
MathHelper.lerp(delta, entity.prevX, entity.getX()),
|
||||||
|
@ -40,8 +40,8 @@ public class PonyBounds {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Box getBoundingBox(IPony pony, LivingEntity entity) {
|
public static Box getBoundingBox(Pony pony, LivingEntity entity) {
|
||||||
final float scale = pony.metadata().getSize().getScaleFactor() + 0.1F;
|
final float scale = pony.size().scaleFactor() + 0.1F;
|
||||||
final float width = entity.getWidth() * scale;
|
final float width = entity.getWidth() * scale;
|
||||||
final float height = entity.getHeight() * scale;
|
final float height = entity.getHeight() * scale;
|
||||||
|
|
||||||
|
|
87
src/main/java/com/minelittlepony/client/PonyDataLoader.java
Normal file
87
src/main/java/com/minelittlepony/client/PonyDataLoader.java
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
package com.minelittlepony.client;
|
||||||
|
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.resource.metadata.ResourceMetadataReader;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
import com.google.gson.*;
|
||||||
|
import com.minelittlepony.api.pony.PonyData;
|
||||||
|
import com.minelittlepony.client.util.render.NativeUtil;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
class PonyDataLoader {
|
||||||
|
static final Supplier<Optional<PonyData>> NULL = loaded(PonyData.NULL);
|
||||||
|
private static final ResourceMetadataReader<PonyData> SERIALIZER = new ResourceMetadataReader<PonyData>() {
|
||||||
|
private static final Gson GSON = new GsonBuilder()
|
||||||
|
.excludeFieldsWithoutExposeAnnotation()
|
||||||
|
.create();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKey() {
|
||||||
|
return "pony";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PonyData fromJson(JsonObject json) {
|
||||||
|
return GSON.fromJson(json, PonyData.class);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the given resource into a new IPonyData.
|
||||||
|
* This may either come from an attached json file or the image itself.
|
||||||
|
*/
|
||||||
|
public static Supplier<Optional<PonyData>> parse(@Nullable Identifier identifier, boolean noSkin) {
|
||||||
|
if (identifier == null) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MinecraftClient.getInstance().getResourceManager().getResource(identifier).flatMap(res -> {
|
||||||
|
try {
|
||||||
|
return res.getMetadata().decode(SERIALIZER);
|
||||||
|
} catch (IOException e) {
|
||||||
|
MineLittlePony.logger.warn("Unable to read {} metadata", identifier, e);
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}).map(PonyDataLoader::loaded).orElseGet(() -> {
|
||||||
|
return load(callback -> {
|
||||||
|
NativeUtil.parseImage(identifier, image -> {
|
||||||
|
callback.accept(new PonyData(image, noSkin));
|
||||||
|
}, e -> {
|
||||||
|
MineLittlePony.logger.fatal("Unable to read {} metadata", identifier, e);
|
||||||
|
callback.accept(PonyData.NULL);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> Supplier<Optional<T>> loaded(T t) {
|
||||||
|
final Optional<T> value = Optional.of(t);
|
||||||
|
return () -> value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> Supplier<Optional<T>> load(Consumer<Consumer<T>> factory) {
|
||||||
|
return new Supplier<Optional<T>>() {
|
||||||
|
Optional<T> value = Optional.empty();
|
||||||
|
boolean loadRequested;
|
||||||
|
@Override
|
||||||
|
public Optional<T> get() {
|
||||||
|
synchronized (this) {
|
||||||
|
if (!loadRequested) {
|
||||||
|
loadRequested = true;
|
||||||
|
factory.accept(value -> {
|
||||||
|
this.value = Optional.ofNullable(value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
123
src/main/java/com/minelittlepony/client/PonyManagerImpl.java
Normal file
123
src/main/java/com/minelittlepony/client/PonyManagerImpl.java
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
package com.minelittlepony.client;
|
||||||
|
|
||||||
|
import com.google.common.cache.*;
|
||||||
|
import com.minelittlepony.api.config.PonyConfig;
|
||||||
|
import com.minelittlepony.api.config.PonyLevel;
|
||||||
|
import com.minelittlepony.api.pony.*;
|
||||||
|
import com.minelittlepony.client.render.blockentity.skull.PonySkullRenderer;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||||
|
import net.minecraft.client.util.DefaultSkinHelper;
|
||||||
|
import net.minecraft.resource.ResourceManager;
|
||||||
|
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.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceReloadListener {
|
||||||
|
private static final Identifier ID = new Identifier("minelittlepony", "background_ponies");
|
||||||
|
|
||||||
|
private final PonyConfig config;
|
||||||
|
|
||||||
|
private final LoadingCache<Identifier, Pony> defaultedPoniesCache = CacheBuilder.newBuilder()
|
||||||
|
.expireAfterAccess(30, TimeUnit.SECONDS)
|
||||||
|
.build(CacheLoader.from(resource -> new Pony(resource, PonyDataLoader.parse(resource, true))));
|
||||||
|
|
||||||
|
private final LoadingCache<Identifier, Pony> poniesCache = CacheBuilder.newBuilder()
|
||||||
|
.expireAfterAccess(30, TimeUnit.SECONDS)
|
||||||
|
.build(CacheLoader.from(resource -> new Pony(resource, PonyDataLoader.parse(resource, false))));
|
||||||
|
|
||||||
|
public PonyManagerImpl(PonyConfig config) {
|
||||||
|
this.config = config;
|
||||||
|
Instance.instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Pony loadPony(Identifier resource, boolean defaulted) {
|
||||||
|
try {
|
||||||
|
return (defaulted ? defaultedPoniesCache : poniesCache).get(resource);
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
return new Pony(resource, PonyDataLoader.NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pony getPony(PlayerEntity player) {
|
||||||
|
return getPony(getSkin(player), player instanceof ForcedPony ? null : player.getGameProfile() == null ? player.getUuid() : player.getGameProfile().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Pony> getPony(LivingEntity entity) {
|
||||||
|
if (entity instanceof PlayerEntity player) {
|
||||||
|
return Optional.of(getPony(player));
|
||||||
|
}
|
||||||
|
Identifier skin = getSkin(entity);
|
||||||
|
return skin == null ? Optional.empty() : Optional.of(getPony(skin, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pony getPony(@Nullable Identifier resource, @Nullable UUID uuid) {
|
||||||
|
if (resource == null) {
|
||||||
|
return uuid == null ? loadPony(DefaultSkinHelper.getTexture(), true) : getBackgroundPony(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
Pony pony = loadPony(resource, false);
|
||||||
|
|
||||||
|
if (uuid != null && PonyConfig.getInstance().ponyLevel.get() == PonyLevel.PONIES && pony.metadata().race().isHuman()) {
|
||||||
|
return getBackgroundPony(uuid);
|
||||||
|
}
|
||||||
|
return pony;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pony getBackgroundPony(@Nullable UUID uuid) {
|
||||||
|
if (config.ponyLevel.get() == PonyLevel.PONIES) {
|
||||||
|
return loadPony(MineLittlePony.getInstance().getVariatedTextures().get(VariatedTextureSupplier.BACKGROUND_PONIES_POOL, uuid).orElse(DefaultSkinHelper.getSkinTextures(uuid).texture()), true);
|
||||||
|
}
|
||||||
|
return loadPony(DefaultSkinHelper.getSkinTextures(uuid).texture(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Identifier getSkin(LivingEntity entity) {
|
||||||
|
if (entity instanceof PlayerEntity player) {
|
||||||
|
if (player.getGameProfile() != null && player instanceof AbstractClientPlayerEntity clientPlayer) {
|
||||||
|
return clientPlayer.getSkinTextures().texture();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (MineLittlePony.getInstance().getRenderDispatcher().getPonyRenderer(entity) != null) {
|
||||||
|
return MinecraftClient.getInstance().getEntityRenderDispatcher().getRenderer(entity).getTexture(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePony(Identifier resource) {
|
||||||
|
poniesCache.invalidate(resource);
|
||||||
|
defaultedPoniesCache.invalidate(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearCache() {
|
||||||
|
MineLittlePony.logger.info("Flushed {} cached ponies.", poniesCache.size());
|
||||||
|
poniesCache.invalidateAll();
|
||||||
|
defaultedPoniesCache.invalidateAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload(ResourceManager var1) {
|
||||||
|
clearCache();
|
||||||
|
PonySkullRenderer.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Identifier getFabricId() {
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,12 @@
|
||||||
package com.minelittlepony.client;
|
package com.minelittlepony.client;
|
||||||
|
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
|
||||||
import net.minecraft.text.*;
|
import net.minecraft.text.*;
|
||||||
|
|
||||||
|
import com.minelittlepony.api.config.PonyConfig;
|
||||||
import com.minelittlepony.client.render.MobRenderers;
|
import com.minelittlepony.client.render.MobRenderers;
|
||||||
import com.minelittlepony.client.settings.ClientPonyConfig;
|
|
||||||
import com.minelittlepony.common.client.gui.GameGui;
|
import com.minelittlepony.common.client.gui.GameGui;
|
||||||
import com.minelittlepony.common.client.gui.ScrollContainer;
|
import com.minelittlepony.common.client.gui.ScrollContainer;
|
||||||
import com.minelittlepony.common.client.gui.Tooltip;
|
import com.minelittlepony.common.client.gui.Tooltip;
|
||||||
|
@ -23,7 +24,7 @@ import org.jetbrains.annotations.Nullable;
|
||||||
* In-Game options menu.
|
* In-Game options menu.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class GuiPonySettings extends GameGui {
|
public class PonySettingsScreen extends GameGui {
|
||||||
private static final String OPTIONS_PREFIX = "minelp.options.";
|
private static final String OPTIONS_PREFIX = "minelp.options.";
|
||||||
private static final String PONY_LEVEL = OPTIONS_PREFIX + "ponylevel";
|
private static final String PONY_LEVEL = OPTIONS_PREFIX + "ponylevel";
|
||||||
private static final String MOB_PREFIX = "minelp.mobs.";
|
private static final String MOB_PREFIX = "minelp.mobs.";
|
||||||
|
@ -34,17 +35,22 @@ public class GuiPonySettings extends GameGui {
|
||||||
public static final Text SCALE_SHOW = Text.translatable("minelp.debug.scale.sa");
|
public static final Text SCALE_SHOW = Text.translatable("minelp.debug.scale.sa");
|
||||||
public static final Text SCALE_MIN = Text.translatable("minelp.debug.scale.min");
|
public static final Text SCALE_MIN = Text.translatable("minelp.debug.scale.min");
|
||||||
|
|
||||||
private ClientPonyConfig config;
|
public static HorseButtonFactory buttonFactory = (screen, parent, row, RIGHT, content) -> {
|
||||||
|
content.addButton(new Button(RIGHT, row += 20, 150, 20))
|
||||||
|
.setEnabled(false)
|
||||||
|
.getStyle()
|
||||||
|
.setTooltip(Tooltip.of("minelp.options.skins.hdskins.disabled", 200))
|
||||||
|
.setText("minelp.options.skins.hdskins.open");
|
||||||
|
};
|
||||||
|
|
||||||
|
private final PonyConfig config = PonyConfig.getInstance();
|
||||||
|
|
||||||
private final ScrollContainer content = new ScrollContainer();
|
private final ScrollContainer content = new ScrollContainer();
|
||||||
|
|
||||||
private final boolean hiddenOptions;
|
private final boolean hiddenOptions;
|
||||||
|
|
||||||
public GuiPonySettings(@Nullable Screen parent) {
|
public PonySettingsScreen(@Nullable Screen parent) {
|
||||||
super(Text.literal(OPTIONS_PREFIX + "title"), parent);
|
super(Text.literal(OPTIONS_PREFIX + "title"), parent);
|
||||||
|
|
||||||
config = (ClientPonyConfig)MineLittlePony.getInstance().getConfig();
|
|
||||||
|
|
||||||
content.margin.top = 30;
|
content.margin.top = 30;
|
||||||
content.margin.bottom = 30;
|
content.margin.bottom = 30;
|
||||||
content.getContentPadding().top = 10;
|
content.getContentPadding().top = 10;
|
||||||
|
@ -113,7 +119,12 @@ public class GuiPonySettings extends GameGui {
|
||||||
boolean enabled = i != config.fillycam || allowCameraChange;
|
boolean enabled = i != config.fillycam || allowCameraChange;
|
||||||
Button button = content
|
Button button = content
|
||||||
.addButton(new Toggle(LEFT, row += 20, ((Setting<Boolean>)i).get()))
|
.addButton(new Toggle(LEFT, row += 20, ((Setting<Boolean>)i).get()))
|
||||||
.onChange((Setting<Boolean>)i)
|
.onChange(i == config.horsieMode ? (v -> {
|
||||||
|
v = ((Setting<Boolean>)i).set(v);
|
||||||
|
|
||||||
|
MineLittlePony.getInstance().getRenderDispatcher().initialise(MinecraftClient.getInstance().getEntityRenderDispatcher(), true);
|
||||||
|
return v;
|
||||||
|
}) : (Setting<Boolean>)i)
|
||||||
.setEnabled(enabled);
|
.setEnabled(enabled);
|
||||||
button.getStyle().setText(OPTIONS_PREFIX + i.name().toLowerCase());
|
button.getStyle().setText(OPTIONS_PREFIX + i.name().toLowerCase());
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
|
@ -153,7 +164,7 @@ public class GuiPonySettings extends GameGui {
|
||||||
row += 15;
|
row += 15;
|
||||||
|
|
||||||
content.addButton(new Label(RIGHT, row)).getStyle().setText("minelp.options.skins");
|
content.addButton(new Label(RIGHT, row)).getStyle().setText("minelp.options.skins");
|
||||||
SkinsProxy.instance.renderOption(this, parent, row, RIGHT, content);
|
buttonFactory.renderOption(this, parent, row, RIGHT, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Text describeCurrentScale(AbstractSlider<Float> sender) {
|
public Text describeCurrentScale(AbstractSlider<Float> sender) {
|
||||||
|
@ -182,14 +193,17 @@ public class GuiPonySettings extends GameGui {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(MatrixStack matrices, int mouseX, int mouseY, float partialTicks) {
|
public void render(DrawContext context, int mouseX, int mouseY, float tickDelta) {
|
||||||
renderBackground(matrices);
|
super.render(context, mouseX, mouseY, tickDelta);
|
||||||
super.render(matrices, mouseX, mouseY, partialTicks);
|
content.render(context, mouseX, mouseY, tickDelta);
|
||||||
content.render(matrices, mouseX, mouseY, partialTicks);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removed() {
|
public void removed() {
|
||||||
config.save();
|
config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface HorseButtonFactory {
|
||||||
|
void renderOption(Screen screen, @Nullable Screen parent, int row, int RIGHT, ScrollContainer content);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,68 +0,0 @@
|
||||||
package com.minelittlepony.client;
|
|
||||||
|
|
||||||
import com.minelittlepony.common.client.gui.ScrollContainer;
|
|
||||||
import com.minelittlepony.common.client.gui.Tooltip;
|
|
||||||
import com.minelittlepony.common.client.gui.element.Button;
|
|
||||||
import com.mojang.authlib.GameProfile;
|
|
||||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
|
||||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
|
||||||
import net.minecraft.client.texture.PlayerSkinProvider;
|
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public class SkinsProxy {
|
|
||||||
|
|
||||||
public static SkinsProxy instance = new SkinsProxy();
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public Identifier getSkinTexture(GameProfile profile) {
|
|
||||||
PlayerSkinProvider skins = MinecraftClient.getInstance().getSkinProvider();
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
MinecraftProfileTexture texture = skins.getTextures(profile).get(MinecraftProfileTexture.Type.SKIN);
|
|
||||||
|
|
||||||
if (texture == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return skins.loadSkin(texture, MinecraftProfileTexture.Type.SKIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void renderOption(Screen screen, @Nullable Screen parent, int row, int RIGHT, ScrollContainer content) {
|
|
||||||
content.addButton(new Button(RIGHT, row += 20, 150, 20))
|
|
||||||
.setEnabled(false)
|
|
||||||
.getStyle()
|
|
||||||
.setTooltip(Tooltip.of("minelp.options.skins.hdskins.disabled", 200))
|
|
||||||
.setText("minelp.options.skins.hdskins.open");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<Identifier> getSkin(Identifier skinTypeId, AbstractClientPlayerEntity player) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Identifier> getAvailableSkins(Entity entity) {
|
|
||||||
return Set.of();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.minelittlepony.client.pony;
|
package com.minelittlepony.client;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
|
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
@ -6,13 +6,14 @@ import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.resource.ResourceManager;
|
import net.minecraft.resource.ResourceManager;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
import com.minelittlepony.client.MineLittlePony;
|
|
||||||
import com.minelittlepony.util.MathUtil;
|
import com.minelittlepony.util.MathUtil;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class VariatedTextureSupplier implements SimpleSynchronousResourceReloadListener {
|
public class VariatedTextureSupplier implements SimpleSynchronousResourceReloadListener {
|
||||||
private static final Identifier ID = new Identifier("minelittlepony", "variated_textures");
|
private static final Identifier ID = new Identifier("minelittlepony", "variated_textures");
|
||||||
|
public static final Identifier BACKGROUND_PONIES_POOL = new Identifier("minelittlepony", "textures/entity/pony");
|
||||||
|
public static final Identifier BACKGROUND_ZOMPONIES_POOL = new Identifier("minelittlepony", "textures/entity/zompony");
|
||||||
|
|
||||||
private final Map<Identifier, SkinList> entries = new HashMap<>();
|
private final Map<Identifier, SkinList> entries = new HashMap<>();
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.minelittlepony.client.compat.hdskins;
|
||||||
|
|
||||||
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
|
||||||
|
import com.minelittlepony.api.model.PreviewModel;
|
||||||
|
import com.minelittlepony.api.pony.*;
|
||||||
|
import com.minelittlepony.hdskins.client.gui.player.*;
|
||||||
|
import com.minelittlepony.hdskins.client.gui.player.skins.PlayerSkins;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy model used for the skin uploading screen.
|
||||||
|
*/
|
||||||
|
class DummyPony extends DummyPlayer implements PreviewModel, PonyManager.ForcedPony {
|
||||||
|
|
||||||
|
public DummyPony(ClientWorld world, PlayerSkins<?> textures) {
|
||||||
|
super(world, textures);
|
||||||
|
setUuid(UUID.randomUUID()); // uuid must be random so animations aren't linked between the two previews
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean forceSeapony() {
|
||||||
|
return getTextures().getPosture().getActiveSkinType() == MineLPHDSkins.seaponySkinType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean forceNirik() {
|
||||||
|
return getTextures().getPosture().getActiveSkinType() == MineLPHDSkins.nirikSkinType;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package com.minelittlepony.client.compat.hdskins;
|
||||||
|
|
||||||
|
import com.minelittlepony.client.PonySettingsScreen;
|
||||||
|
import com.minelittlepony.client.MineLittlePony;
|
||||||
|
import com.minelittlepony.common.client.gui.dimension.Bounds;
|
||||||
|
import com.minelittlepony.common.client.gui.element.Button;
|
||||||
|
import com.minelittlepony.common.client.gui.sprite.TextureSprite;
|
||||||
|
import com.minelittlepony.hdskins.client.gui.DualCarouselWidget;
|
||||||
|
import com.minelittlepony.hdskins.client.gui.GuiSkins;
|
||||||
|
import com.minelittlepony.hdskins.server.SkinServerList;
|
||||||
|
import com.minelittlepony.hdskins.profile.SkinType;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
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"
|
||||||
|
};
|
||||||
|
|
||||||
|
public GuiSkinsMineLP(Screen parent, SkinServerList servers) {
|
||||||
|
super(parent, servers);
|
||||||
|
chooser.addSkinChangedEventListener(type -> {
|
||||||
|
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");
|
||||||
|
if (type == SkinType.SKIN) {
|
||||||
|
MineLittlePony.getInstance().getManager().removePony(location);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initServerPreviewButtons(Bounds area) {
|
||||||
|
if (!(parent instanceof PonySettingsScreen)) {
|
||||||
|
addButton(new Button(area.right() - 20, area.bottom() + 5, 20, 20))
|
||||||
|
.onClick(sender -> client.setScreen(new PonySettingsScreen(this)))
|
||||||
|
.getStyle()
|
||||||
|
.setIcon(new TextureSprite()
|
||||||
|
.setPosition(2, 2)
|
||||||
|
.setTexture(new Identifier("minelittlepony", "textures/gui/pony.png"))
|
||||||
|
.setTextureSize(16, 16)
|
||||||
|
.setSize(16, 16))
|
||||||
|
.setTooltip("minelp.options.title", 0, 10);
|
||||||
|
super.initServerPreviewButtons(new Bounds(area.top, area.left, area.width - 25, area.height));
|
||||||
|
} else {
|
||||||
|
super.initServerPreviewButtons(area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DualCarouselWidget createPreviewer() {
|
||||||
|
return new PonifiedDualCarouselWidget(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Identifier getBackground() {
|
||||||
|
int i = (int)Math.floor(Math.random() * PANORAMAS.length);
|
||||||
|
|
||||||
|
return new Identifier(PANORAMAS[i]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.minelittlepony.client.compat.hdskins;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
import com.minelittlepony.api.pony.*;
|
||||||
|
import com.minelittlepony.api.pony.meta.TValue;
|
||||||
|
import com.minelittlepony.common.client.gui.ITextContext;
|
||||||
|
import com.minelittlepony.common.client.gui.dimension.Bounds;
|
||||||
|
import com.minelittlepony.hdskins.client.gui.Carousel;
|
||||||
|
import com.minelittlepony.hdskins.client.gui.player.DummyPlayer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
class LegendOverlayWidget implements Carousel.Element, ITextContext {
|
||||||
|
private static final Bounds LEGEND_BLOCK_BOUNDS = new Bounds(0, 0, 10, 10);
|
||||||
|
|
||||||
|
private final Bounds frame;
|
||||||
|
|
||||||
|
public LegendOverlayWidget(Bounds frame) {
|
||||||
|
this.frame = frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(DummyPlayer player, DrawContext context, int mouseX, int mouseY) {
|
||||||
|
PonyData data = Pony.getManager().getPony(player).metadata();
|
||||||
|
int[] index = new int[1];
|
||||||
|
data.attributes().forEach((key, value) -> {
|
||||||
|
context.getMatrices().push();
|
||||||
|
int i = index[0]++;
|
||||||
|
int x = frame.left;
|
||||||
|
int y = frame.top + (i * 10 + 20);
|
||||||
|
context.getMatrices().translate(x, y, 1);
|
||||||
|
drawLegendBlock(context, 0, 0, 0, mouseX - x, mouseY - y, key, value);
|
||||||
|
context.getMatrices().pop();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawLegendBlock(DrawContext context, int index, int x, int y, int mouseX, int mouseY, String key, TValue<?> value) {
|
||||||
|
context.fill(0, 0, LEGEND_BLOCK_BOUNDS.width, LEGEND_BLOCK_BOUNDS.height, 0xFF003333);
|
||||||
|
context.fill(1, 1, LEGEND_BLOCK_BOUNDS.width - 1, LEGEND_BLOCK_BOUNDS.height - 1, value.colorCode() | 0xFF000000);
|
||||||
|
|
||||||
|
char symbol = value.name().charAt(0);
|
||||||
|
if (symbol == '[') {
|
||||||
|
symbol = key.charAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.drawTextWithShadow(getFont(), Text.literal(String.valueOf(symbol).toUpperCase()), 2, 1, 0xFFFFFFFF);
|
||||||
|
|
||||||
|
if (LEGEND_BLOCK_BOUNDS.contains(mouseX, mouseY)) {
|
||||||
|
List<Text> lines = value.getOptions().stream().map(option -> {
|
||||||
|
boolean selected = value.matches(option);
|
||||||
|
return Text.literal((selected ? "* " : " ") + option.name()).styled(s -> {
|
||||||
|
int color = option.getChannelAdjustedColorCode();
|
||||||
|
return (color == 0 ? s : s.withColor(color)).withItalic(selected);
|
||||||
|
});
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
lines.add(0, Text.of(key.toUpperCase() + ": " + value.getHexValue()));
|
||||||
|
if (lines.size() == 1) {
|
||||||
|
lines.add(Text.literal(value.name()).styled(s -> {
|
||||||
|
int color = value.getChannelAdjustedColorCode();
|
||||||
|
return color == 0 ? s : s.withColor(value.colorCode());
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
context.drawTooltip(getFont(), lines, 2, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +1,17 @@
|
||||||
package com.minelittlepony.client.hdskins;
|
package com.minelittlepony.client.compat.hdskins;
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.IPony;
|
import com.minelittlepony.api.config.PonyConfig;
|
||||||
import com.minelittlepony.api.pony.IPonyData;
|
import com.minelittlepony.api.config.PonyLevel;
|
||||||
import com.minelittlepony.api.pony.meta.Race;
|
import com.minelittlepony.api.pony.*;
|
||||||
import com.minelittlepony.api.pony.meta.Wearable;
|
import com.minelittlepony.api.pony.meta.Wearable;
|
||||||
import com.minelittlepony.client.MineLittlePony;
|
|
||||||
import com.minelittlepony.client.SkinsProxy;
|
|
||||||
import com.minelittlepony.common.client.gui.ScrollContainer;
|
import com.minelittlepony.common.client.gui.ScrollContainer;
|
||||||
import com.minelittlepony.common.client.gui.element.Button;
|
import com.minelittlepony.common.client.gui.element.Button;
|
||||||
import com.minelittlepony.common.event.ClientReadyCallback;
|
import com.minelittlepony.common.event.ClientReadyCallback;
|
||||||
import com.minelittlepony.hdskins.client.*;
|
import com.minelittlepony.hdskins.client.*;
|
||||||
import com.minelittlepony.hdskins.client.dummy.DummyPlayer;
|
|
||||||
import com.minelittlepony.hdskins.client.dummy.PlayerSkins.PlayerSkin;
|
|
||||||
import com.minelittlepony.hdskins.client.gui.GuiSkins;
|
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.minelittlepony.hdskins.profile.SkinType;
|
||||||
|
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
|
@ -29,8 +28,7 @@ import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
import com.minelittlepony.client.pony.PonyManager;
|
import com.minelittlepony.client.*;
|
||||||
import com.minelittlepony.client.render.entity.PlayerSeaponyRenderer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All the interactions with HD Skins.
|
* All the interactions with HD Skins.
|
||||||
|
@ -38,15 +36,18 @@ import com.minelittlepony.client.render.entity.PlayerSeaponyRenderer;
|
||||||
public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
|
public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
|
||||||
|
|
||||||
static SkinType seaponySkinType;
|
static SkinType seaponySkinType;
|
||||||
|
static SkinType nirikSkinType;
|
||||||
|
|
||||||
static final Map<SkinType, Wearable> wearableTypes = new HashMap<>();
|
static final Map<SkinType, Wearable> wearableTypes = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitializeClient() {
|
public void onInitializeClient() {
|
||||||
SkinsProxy.instance = this;
|
SkinsProxy.instance = this;
|
||||||
|
PonySettingsScreen.buttonFactory = this::renderOption;
|
||||||
|
|
||||||
seaponySkinType = SkinType.register(PlayerSeaponyRenderer.SKIN_TYPE_ID, Items.COD_BUCKET.getDefaultStack());
|
seaponySkinType = SkinType.register(DefaultPonySkinHelper.SEAPONY_SKIN_TYPE_ID, Items.COD_BUCKET.getDefaultStack());
|
||||||
Wearable.VALUES.forEach(wearable -> {
|
nirikSkinType = SkinType.register(DefaultPonySkinHelper.NIRIK_SKIN_TYPE_ID, Items.LAVA_BUCKET.getDefaultStack());
|
||||||
|
Wearable.REGISTRY.values().forEach(wearable -> {
|
||||||
if (wearable != Wearable.NONE) {
|
if (wearable != Wearable.NONE) {
|
||||||
wearableTypes.put(SkinType.register(wearable.getId(), Items.BUNDLE.getDefaultStack()), wearable);
|
wearableTypes.put(SkinType.register(wearable.getId(), Items.BUNDLE.getDefaultStack()), wearable);
|
||||||
}
|
}
|
||||||
|
@ -54,16 +55,34 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
|
||||||
|
|
||||||
ClientReadyCallback.EVENT.register(client -> {
|
ClientReadyCallback.EVENT.register(client -> {
|
||||||
// Clear ponies when skins are cleared
|
// Clear ponies when skins are cleared
|
||||||
PonyManager ponyManager = (PonyManager) MineLittlePony.getInstance().getManager();
|
SkinCacheClearCallback.EVENT.register(MineLittlePony.getInstance().getManager()::clearCache);
|
||||||
SkinCacheClearCallback.EVENT.register(ponyManager::clearCache);
|
|
||||||
|
|
||||||
// Ponify the skins GUI.
|
// Ponify the skins GUI.
|
||||||
GuiSkins.setSkinsGui(GuiSkinsMineLP::new);
|
GuiSkins.setSkinsGui(GuiSkinsMineLP::new);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
HDSkins.getInstance().getSkinPrioritySorter().addSelector((skinType, playerSkins) -> {
|
||||||
|
if (skinType == SkinType.SKIN && PonyConfig.getInstance().mixedHumanSkins.get()) {
|
||||||
|
Optional<Pony> hdPony = getPony(playerSkins.hd());
|
||||||
|
Optional<Pony> vanillaPony = getPony(playerSkins.vanilla());
|
||||||
|
|
||||||
|
if (hdPony.isPresent() && vanillaPony.isPresent()
|
||||||
|
&& vanillaPony.get().metadata().priority() > hdPony.get().metadata().priority()
|
||||||
|
&& (PonyConfig.getInstance().ponyLevel.get() == PonyLevel.HUMANS || vanillaPony.get().metadata().race().isHuman() == hdPony.get().metadata().race().isHuman())) {
|
||||||
|
return playerSkins.vanilla();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return playerSkins.combined();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
static Optional<Pony> getPony(PlayerSkinLayers.Layer layer) {
|
||||||
public void renderOption(Screen screen, @Nullable Screen parent, int row, int RIGHT, ScrollContainer content) {
|
return layer
|
||||||
|
.getSkin(SkinType.SKIN)
|
||||||
|
.map(Pony.getManager()::getPony);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderOption(Screen screen, @Nullable Screen parent, int row, int RIGHT, ScrollContainer content) {
|
||||||
content.addButton(new Button(RIGHT, row += 20, 150, 20))
|
content.addButton(new Button(RIGHT, row += 20, 150, 20))
|
||||||
.onClick(button -> MinecraftClient.getInstance().setScreen(
|
.onClick(button -> MinecraftClient.getInstance().setScreen(
|
||||||
parent instanceof GuiSkins ? parent : GuiSkins.create(screen, HDSkins.getInstance().getSkinServerList())
|
parent instanceof GuiSkins ? parent : GuiSkins.create(screen, HDSkins.getInstance().getSkinServerList())
|
||||||
|
@ -84,10 +103,11 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity instanceof AbstractClientPlayerEntity player) {
|
if (entity instanceof AbstractClientPlayerEntity player) {
|
||||||
PlayerSkins skins = PlayerSkins.of(player);
|
return PlayerSkins.of(player)
|
||||||
if (skins != null) {
|
.map(PlayerSkins::layers)
|
||||||
return skins.getProvidedSkinTypes();
|
.map(PlayerSkinLayers::combined)
|
||||||
}
|
.map(PlayerSkinLayers.Layer::getProvidedSkinTypes)
|
||||||
|
.orElseGet(Set::of);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Set.of();
|
return Set.of();
|
||||||
|
@ -103,10 +123,10 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
|
||||||
|
|
||||||
PlayerSkin main = dummy.getTextures().get(SkinType.SKIN);
|
PlayerSkin main = dummy.getTextures().get(SkinType.SKIN);
|
||||||
Wearable wearable = Wearable.REGISTRY.getOrDefault(type.getId(), Wearable.NONE);
|
Wearable wearable = Wearable.REGISTRY.getOrDefault(type.getId(), Wearable.NONE);
|
||||||
IPonyData metadata = IPony.getManager().getPony(main.getId()).metadata();
|
PonyData metadata = Pony.getManager().getPony(main.getId()).metadata();
|
||||||
if (wearable != Wearable.NONE && metadata.isWearing(wearable)) {
|
if (wearable != Wearable.NONE && metadata.gear().matches(wearable)) {
|
||||||
|
|
||||||
if (wearable.isSaddlebags() && metadata.getRace().supportsLegacySaddlebags()) {
|
if (wearable.isSaddlebags() && metadata.race().supportsLegacySaddlebags()) {
|
||||||
return Optional.of(main.getId());
|
return Optional.of(main.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,18 +134,17 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Optional.of(player).map(PlayerSkins::of).map(skins -> skins.getSkin(type));
|
return Optional.of(player).flatMap(PlayerSkins::of)
|
||||||
|
.map(PlayerSkins::layers)
|
||||||
|
.map(PlayerSkinLayers::combined).flatMap(skins -> skins.getSkin(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Identifier getSkinTexture(GameProfile profile) {
|
public Identifier getSkinTexture(GameProfile profile) {
|
||||||
|
return HDSkins.getInstance().getProfileRepository()
|
||||||
Identifier skin = HDSkins.getInstance().getProfileRepository().getTextures(profile).get(SkinType.SKIN);
|
.load(profile)
|
||||||
|
.getNow(ProvidedSkins.EMPTY)
|
||||||
if (skin != null) {
|
.getSkin(SkinType.SKIN)
|
||||||
return skin;
|
.orElseGet(() -> super.getSkinTexture(profile));
|
||||||
}
|
|
||||||
|
|
||||||
return super.getSkinTexture(profile);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.minelittlepony.client.compat.hdskins;
|
||||||
|
|
||||||
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
import com.minelittlepony.api.pony.meta.*;
|
||||||
|
import com.minelittlepony.client.render.entity.SeaponyRenderer;
|
||||||
|
import com.minelittlepony.hdskins.client.gui.DualCarouselWidget;
|
||||||
|
import com.minelittlepony.hdskins.client.gui.GuiSkins;
|
||||||
|
import com.minelittlepony.hdskins.client.gui.player.DummyPlayer;
|
||||||
|
import com.minelittlepony.hdskins.client.gui.player.skins.PlayerSkins;
|
||||||
|
import com.minelittlepony.hdskins.client.resources.NativeImageFilters;
|
||||||
|
import com.minelittlepony.hdskins.client.resources.TextureLoader;
|
||||||
|
import com.minelittlepony.hdskins.profile.SkinType;
|
||||||
|
|
||||||
|
class PonifiedDualCarouselWidget extends DualCarouselWidget {
|
||||||
|
|
||||||
|
public PonifiedDualCarouselWidget(GuiSkins screen) {
|
||||||
|
super(screen);
|
||||||
|
local.addElement(new LegendOverlayWidget(local.bounds));
|
||||||
|
remote.addElement(new LegendOverlayWidget(remote.bounds));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DummyPlayer createEntity(ClientWorld world, PlayerSkins<?> textures) {
|
||||||
|
return new DummyPony(world, textures);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Identifier getDefaultSkin(SkinType type, String modelVariant) {
|
||||||
|
if (type == MineLPHDSkins.seaponySkinType) {
|
||||||
|
return NativeImageFilters.GREYSCALE.load(SeaponyRenderer.SEAPONY, SeaponyRenderer.SEAPONY, getExclusion());
|
||||||
|
}
|
||||||
|
if (type == MineLPHDSkins.nirikSkinType) {
|
||||||
|
return super.getDefaultSkin(SkinType.SKIN, modelVariant);
|
||||||
|
}
|
||||||
|
|
||||||
|
Wearable wearable = MineLPHDSkins.wearableTypes.getOrDefault(type, Wearable.NONE);
|
||||||
|
|
||||||
|
if (wearable != Wearable.NONE) {
|
||||||
|
return NativeImageFilters.GREYSCALE.load(wearable.getDefaultTexture(), wearable.getDefaultTexture(), getExclusion());
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.getDefaultSkin(type, modelVariant);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TextureLoader.Exclusion getExclusion() {
|
||||||
|
return TriggerPixel::isTriggerPixelCoord;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
package com.minelittlepony.client.modmenu;
|
package com.minelittlepony.client.compat.modmenu;
|
||||||
|
|
||||||
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
|
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
|
||||||
import com.terraformersmc.modmenu.api.ModMenuApi;
|
import com.terraformersmc.modmenu.api.ModMenuApi;
|
||||||
|
|
||||||
import com.minelittlepony.client.GuiPonySettings;
|
import com.minelittlepony.client.PonySettingsScreen;
|
||||||
|
|
||||||
public class MineLPModMenuFactory implements ModMenuApi {
|
public class MineLPModMenuFactory implements ModMenuApi {
|
||||||
@Override
|
@Override
|
||||||
public ConfigScreenFactory<?> getModConfigScreenFactory() {
|
public ConfigScreenFactory<?> getModConfigScreenFactory() {
|
||||||
return GuiPonySettings::new;
|
return PonySettingsScreen::new;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,44 +0,0 @@
|
||||||
package com.minelittlepony.client.hdskins;
|
|
||||||
|
|
||||||
import net.minecraft.client.world.ClientWorld;
|
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.IPony;
|
|
||||||
import com.minelittlepony.api.pony.IPonyManager;
|
|
||||||
import com.minelittlepony.client.IPreviewModel;
|
|
||||||
import com.minelittlepony.client.render.EquineRenderManager;
|
|
||||||
import com.minelittlepony.hdskins.client.dummy.*;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dummy model used for the skin uploading screen.
|
|
||||||
*/
|
|
||||||
class DummyPony extends DummyPlayer implements IPreviewModel, IPonyManager.ForcedPony, EquineRenderManager.RegistrationHandler {
|
|
||||||
|
|
||||||
public DummyPony(ClientWorld world, PlayerSkins<?> textures) {
|
|
||||||
super(world, textures);
|
|
||||||
setUuid(UUID.randomUUID()); // uuid must be random so animations aren't linked between the two previews
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldUpdateRegistration(IPony pony) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSubmergedInWater() {
|
|
||||||
return getTextures().getPosture().getActiveSkinType() == MineLPHDSkins.seaponySkinType || super.isSubmergedInWater();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getModel() {
|
|
||||||
if (getTextures().getPosture().getActiveSkinType() == MineLPHDSkins.seaponySkinType) {
|
|
||||||
return getTextures().usesThinSkin() ? "slimseapony" : "seapony";
|
|
||||||
}
|
|
||||||
return IPony.getManager()
|
|
||||||
.getPony(this)
|
|
||||||
.metadata()
|
|
||||||
.getRace()
|
|
||||||
.getModelId(getTextures().usesThinSkin());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
package com.minelittlepony.client.hdskins;
|
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.IPony;
|
|
||||||
import com.minelittlepony.client.GuiPonySettings;
|
|
||||||
import com.minelittlepony.client.MineLittlePony;
|
|
||||||
import com.minelittlepony.common.client.gui.element.Button;
|
|
||||||
import com.minelittlepony.common.client.gui.sprite.TextureSprite;
|
|
||||||
import com.minelittlepony.hdskins.client.dummy.PlayerPreview;
|
|
||||||
import com.minelittlepony.hdskins.client.gui.GuiSkins;
|
|
||||||
import com.minelittlepony.hdskins.server.SkinServerList;
|
|
||||||
import com.minelittlepony.hdskins.profile.SkinType;
|
|
||||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
|
||||||
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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"
|
|
||||||
};
|
|
||||||
|
|
||||||
public GuiSkinsMineLP(Screen parent, SkinServerList servers) {
|
|
||||||
super(parent, servers);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init() {
|
|
||||||
super.init();
|
|
||||||
|
|
||||||
if (!(parent instanceof GuiPonySettings)) {
|
|
||||||
addButton(new Button(width - 25, height - 90, 20, 20))
|
|
||||||
.onClick(sender -> client.setScreen(new GuiPonySettings(this)))
|
|
||||||
.getStyle()
|
|
||||||
.setIcon(new TextureSprite()
|
|
||||||
.setPosition(2, 2)
|
|
||||||
.setTexture(new Identifier("minelittlepony", "textures/gui/pony.png"))
|
|
||||||
.setTextureSize(16, 16)
|
|
||||||
.setSize(16, 16))
|
|
||||||
.setTooltip("minelp.options.title", 0, 10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
|
||||||
if (modifiers == (GLFW.GLFW_MOD_ALT | GLFW.GLFW_MOD_CONTROL) && keyCode == GLFW.GLFW_KEY_R) {
|
|
||||||
client.reloadResources();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.keyPressed(keyCode, scanCode, modifiers);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PlayerPreview createPreviewer() {
|
|
||||||
return new PonyPreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Identifier getBackground() {
|
|
||||||
int i = (int)Math.floor(Math.random() * PANORAMAS.length);
|
|
||||||
|
|
||||||
return new Identifier(PANORAMAS[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSetLocalSkin(SkinType type) {
|
|
||||||
super.onSetLocalSkin(type);
|
|
||||||
|
|
||||||
MineLittlePony.logger.debug("Invalidating old local skin, checking updated local skin");
|
|
||||||
if (type == SkinType.SKIN) {
|
|
||||||
previewer.getLocal().ifPresent(local -> IPony.getManager().removePony(local.getTextures().get(SkinType.SKIN).getId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSetRemoteSkin(SkinType type, Identifier location, MinecraftProfileTexture profileTexture) {
|
|
||||||
super.onSetRemoteSkin(type, location, profileTexture);
|
|
||||||
|
|
||||||
MineLittlePony.logger.debug("Invalidating old remote skin, checking updated remote skin");
|
|
||||||
if (type == SkinType.SKIN) {
|
|
||||||
IPony.getManager().removePony(location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,113 +0,0 @@
|
||||||
package com.minelittlepony.client.hdskins;
|
|
||||||
|
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
|
||||||
import net.minecraft.client.world.ClientWorld;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.*;
|
|
||||||
import com.minelittlepony.api.pony.meta.TriggerPixel;
|
|
||||||
import com.minelittlepony.api.pony.meta.Wearable;
|
|
||||||
import com.minelittlepony.client.render.entity.SeaponyRenderer;
|
|
||||||
import com.minelittlepony.common.client.gui.dimension.Bounds;
|
|
||||||
import com.minelittlepony.hdskins.client.dummy.*;
|
|
||||||
import com.minelittlepony.hdskins.client.resources.DefaultSkinGenerator;
|
|
||||||
import com.minelittlepony.hdskins.client.resources.TextureLoader;
|
|
||||||
import com.minelittlepony.hdskins.profile.SkinType;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
class PonyPreview extends PlayerPreview {
|
|
||||||
@Override
|
|
||||||
protected DummyPlayer createEntity(ClientWorld world, PlayerSkins<?> textures) {
|
|
||||||
return new DummyPony(world, textures);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Identifier getDefaultSkin(SkinType type, boolean slim) {
|
|
||||||
if (type == MineLPHDSkins.seaponySkinType) {
|
|
||||||
return DefaultSkinGenerator.generateGreyScale(SeaponyRenderer.TEXTURE, SeaponyRenderer.TEXTURE, getExclusion());
|
|
||||||
}
|
|
||||||
|
|
||||||
Wearable wearable = MineLPHDSkins.wearableTypes.getOrDefault(type, Wearable.NONE);
|
|
||||||
|
|
||||||
if (wearable != Wearable.NONE) {
|
|
||||||
return DefaultSkinGenerator.generateGreyScale(wearable.getDefaultTexture(), wearable.getDefaultTexture(), getExclusion());
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.getDefaultSkin(type, slim);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected TextureLoader.Exclusion getExclusion() {
|
|
||||||
return TriggerPixel::isTriggerPixelCoord;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderWorldAndPlayer(Optional<DummyPlayer> thePlayer,
|
|
||||||
Bounds frame,
|
|
||||||
int horizon, int mouseX, int mouseY, int ticks, float partialTick, float scale,
|
|
||||||
MatrixStack matrices, @Nullable Consumer<DummyPlayer> postAction) {
|
|
||||||
super.renderWorldAndPlayer(thePlayer, frame, horizon, mouseX, mouseY, ticks, partialTick, scale, matrices, postAction);
|
|
||||||
thePlayer.ifPresent(p -> {
|
|
||||||
IPonyData data = IPony.getManager().getPony(p).metadata();
|
|
||||||
int[] index = new int[1];
|
|
||||||
data.getTriggerPixels().forEach((key, value) -> {
|
|
||||||
drawLegendBlock(matrices, index[0]++, frame.left, frame.top, mouseX, mouseY, key, value);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void drawLegendBlock(MatrixStack matrices, int index, int x, int y, int mouseX, int mouseY, String key, TriggerPixelType<?> value) {
|
|
||||||
int size = 10;
|
|
||||||
int yPos = y + index * size + 20;
|
|
||||||
fill(matrices,
|
|
||||||
x, yPos,
|
|
||||||
x + size, yPos + size,
|
|
||||||
0xFF003333
|
|
||||||
);
|
|
||||||
fill(matrices,
|
|
||||||
x + 1, yPos + 1,
|
|
||||||
x - 1 + size, yPos - 1 + size,
|
|
||||||
value.getColorCode() | 0xFF000000
|
|
||||||
);
|
|
||||||
|
|
||||||
char symbol = value.name().charAt(0);
|
|
||||||
if (symbol == '[') {
|
|
||||||
symbol = key.charAt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
minecraft.textRenderer.drawWithShadow(matrices,
|
|
||||||
Text.of(String.valueOf(symbol).toUpperCase()),
|
|
||||||
x + 2,
|
|
||||||
yPos + 1,
|
|
||||||
0xFFFFFFFF
|
|
||||||
);
|
|
||||||
|
|
||||||
if (mouseX > x && mouseX < (x + size) && mouseY > yPos && mouseY < (yPos + size)) {
|
|
||||||
|
|
||||||
List<Text> lines = value.getOptions().stream().map(option -> {
|
|
||||||
boolean selected = value.matches(option);
|
|
||||||
return Text.literal((selected ? "* " : " ") + option.name()).styled(s -> {
|
|
||||||
int color = option.getChannelAdjustedColorCode();
|
|
||||||
return (color == 0 ? s : s.withColor(color)).withItalic(selected);
|
|
||||||
});
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
|
|
||||||
lines.add(0, Text.of(key.toUpperCase() + ": " + value.getHexValue()));
|
|
||||||
if (lines.size() == 1) {
|
|
||||||
lines.add(Text.literal(value.name()).styled(s -> {
|
|
||||||
int color = value.getChannelAdjustedColorCode();
|
|
||||||
return color == 0 ? s : s.withColor(value.getColorCode());
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
minecraft.currentScreen.renderTooltip(matrices, lines, mouseX, mouseY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +1,12 @@
|
||||||
package com.minelittlepony.client.mixin;
|
package com.minelittlepony.client.mixin;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityDimensions;
|
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
@Mixin(Entity.class)
|
@Mixin(Entity.class)
|
||||||
public interface IResizeable {
|
public interface IResizeable {
|
||||||
@Accessor("dimensions")
|
@Accessor
|
||||||
EntityDimensions getCurrentSize();
|
void setStandingEyeHeight(float height);
|
||||||
|
|
||||||
@Accessor("dimensions")
|
|
||||||
void setCurrentSize(EntityDimensions size);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.IPony;
|
import com.minelittlepony.api.pony.Pony;
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.render.Camera;
|
import net.minecraft.client.render.Camera;
|
||||||
|
@ -18,10 +18,10 @@ abstract class MixinCamera {
|
||||||
private void redirectCameraDistance(double initial, CallbackInfoReturnable<Double> info) {
|
private void redirectCameraDistance(double initial, CallbackInfoReturnable<Double> info) {
|
||||||
double value = info.getReturnValueD();
|
double value = info.getReturnValueD();
|
||||||
|
|
||||||
IPony pony = IPony.getManager().getPony(MinecraftClient.getInstance().player);
|
Pony pony = Pony.getManager().getPony(MinecraftClient.getInstance().player);
|
||||||
|
|
||||||
if (!pony.race().isHuman()) {
|
if (!pony.race().isHuman()) {
|
||||||
value *= pony.metadata().getSize().getEyeDistanceFactor();
|
value *= pony.size().eyeDistanceFactor();
|
||||||
}
|
}
|
||||||
|
|
||||||
info.setReturnValue(value);
|
info.setReturnValue(value);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package com.minelittlepony.client.mixin;
|
package com.minelittlepony.client.mixin;
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.IPony;
|
import com.minelittlepony.api.pony.Pony;
|
||||||
import com.minelittlepony.client.pony.Pony;
|
|
||||||
import com.minelittlepony.client.render.EquineRenderManager;
|
import com.minelittlepony.client.render.EquineRenderManager;
|
||||||
|
|
||||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||||
|
@ -10,7 +9,6 @@ import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityDimensions;
|
import net.minecraft.entity.EntityDimensions;
|
||||||
import net.minecraft.entity.EntityPose;
|
import net.minecraft.entity.EntityPose;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
@ -21,8 +19,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity implements EquineRenderManager.RegistrationHandler {
|
abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity implements EquineRenderManager.RegistrationHandler {
|
||||||
public MixinClientPlayerEntity() { super(null, null); }
|
public MixinClientPlayerEntity() { super(null, null); }
|
||||||
|
|
||||||
@Nullable
|
private final EquineRenderManager.SyncedPony syncedPony = new EquineRenderManager.SyncedPony();
|
||||||
private IPony pony;
|
|
||||||
|
|
||||||
@Inject(method = "startRiding(Lnet/minecraft/entity/Entity;Z)Z", at = @At("RETURN"))
|
@Inject(method = "startRiding(Lnet/minecraft/entity/Entity;Z)Z", at = @At("RETURN"))
|
||||||
private void onStartRiding(Entity entity, boolean bl, CallbackInfoReturnable<Boolean> info) {
|
private void onStartRiding(Entity entity, boolean bl, CallbackInfoReturnable<Boolean> info) {
|
||||||
|
@ -35,30 +32,24 @@ abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity implem
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldUpdateRegistration(IPony pony) {
|
public EquineRenderManager.SyncedPony getSyncedPony() {
|
||||||
if (this.pony != pony && (this.pony == null || this.pony.metadata().compareTo(pony.metadata()) != 0)) {
|
return syncedPony;
|
||||||
this.pony = Pony.snapshot(pony);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getActiveEyeHeight(EntityPose pose, EntityDimensions dimensions) {
|
public float getActiveEyeHeight(EntityPose pose, EntityDimensions dimensions) {
|
||||||
float value = super.getActiveEyeHeight(pose, dimensions);
|
float value = super.getActiveEyeHeight(pose, dimensions);
|
||||||
|
|
||||||
IPony pony = IPony.getManager().getPony(this);
|
Pony pony = Pony.getManager().getPony(this);
|
||||||
|
|
||||||
if (!pony.race().isHuman()) {
|
if (!pony.race().isHuman()) {
|
||||||
float factor = pony.metadata().getSize().getEyeHeightFactor();
|
float factor = pony.size().eyeHeightFactor();
|
||||||
if (factor != 1) {
|
if (factor != 1) {
|
||||||
value *= factor;
|
value *= factor;
|
||||||
|
|
||||||
if (hasVehicle()) {
|
if (hasVehicle()) {
|
||||||
value += getVehicle().getEyeHeight(getVehicle().getPose());
|
value += getVehicle().getHeight();
|
||||||
value -= getVehicle().getMountedHeightOffset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.max(value, 0.1F);
|
return Math.max(value, 0.1F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package com.minelittlepony.client.mixin;
|
package com.minelittlepony.client.mixin;
|
||||||
|
|
||||||
|
import com.minelittlepony.api.config.PonyConfig;
|
||||||
import com.minelittlepony.api.config.PonyLevel;
|
import com.minelittlepony.api.config.PonyLevel;
|
||||||
import com.minelittlepony.api.pony.DefaultPonySkinHelper;
|
import com.minelittlepony.api.pony.DefaultPonySkinHelper;
|
||||||
import com.minelittlepony.api.pony.IPony;
|
|
||||||
import com.minelittlepony.client.MineLittlePony;
|
|
||||||
|
|
||||||
import net.minecraft.client.util.DefaultSkinHelper;
|
import net.minecraft.client.util.DefaultSkinHelper;
|
||||||
|
import net.minecraft.client.util.SkinTextures;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
@ -20,29 +21,17 @@ abstract class MixinDefaultSkinHelper {
|
||||||
at = @At("RETURN"),
|
at = @At("RETURN"),
|
||||||
cancellable = true)
|
cancellable = true)
|
||||||
private static void onGetTexture(CallbackInfoReturnable<Identifier> cir) {
|
private static void onGetTexture(CallbackInfoReturnable<Identifier> cir) {
|
||||||
if (MineLittlePony.getInstance().getConfig().ponyLevel.get() == PonyLevel.PONIES) {
|
if (PonyConfig.getInstance().ponyLevel.get() == PonyLevel.PONIES) {
|
||||||
cir.setReturnValue(DefaultPonySkinHelper.getPonySkin(cir.getReturnValue()));
|
cir.setReturnValue(DefaultPonySkinHelper.STEVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "getTexture(Ljava/util/UUID;)Lnet/minecraft/util/Identifier;",
|
@Inject(method = "getSkinTextures(Ljava/util/UUID;)Lnet/minecraft/client/util/SkinTextures;",
|
||||||
at = @At("RETURN"),
|
at = @At("RETURN"),
|
||||||
cancellable = true)
|
cancellable = true)
|
||||||
private static void onGetTexture(UUID uuid, CallbackInfoReturnable<Identifier> cir) {
|
private static void onGetTexture(UUID uuid, CallbackInfoReturnable<SkinTextures> cir) {
|
||||||
if (MineLittlePony.getInstance().getConfig().ponyLevel.get() == PonyLevel.PONIES) {
|
if (PonyConfig.getInstance().ponyLevel.get() == PonyLevel.PONIES) {
|
||||||
cir.setReturnValue(DefaultPonySkinHelper.getPonySkin(cir.getReturnValue()));
|
cir.setReturnValue(DefaultPonySkinHelper.getTextures(cir.getReturnValue()));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject(method = "getModel(Ljava/util/UUID;)Ljava/lang/String;",
|
|
||||||
at = @At("RETURN"),
|
|
||||||
cancellable = true)
|
|
||||||
private static void onGetModel(UUID uuid, CallbackInfoReturnable<String> cir) {
|
|
||||||
if (MineLittlePony.getInstance().getConfig().ponyLevel.get() == PonyLevel.PONIES) {
|
|
||||||
cir.setReturnValue(IPony.getManager()
|
|
||||||
.getPony(DefaultSkinHelper.getTexture(uuid), uuid)
|
|
||||||
.race()
|
|
||||||
.getModelId("slim".equalsIgnoreCase(cir.getReturnValue())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
package com.minelittlepony.client.mixin;
|
|
||||||
|
|
||||||
import com.minelittlepony.api.pony.IPony;
|
|
||||||
import com.minelittlepony.client.IPreviewModel;
|
|
||||||
|
|
||||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
|
||||||
import net.minecraft.client.render.entity.EntityRenderDispatcher;
|
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
|
||||||
|
|
||||||
@Mixin(EntityRenderDispatcher.class)
|
|
||||||
abstract class MixinEntityRenderDispatcher {
|
|
||||||
@Redirect(
|
|
||||||
method = "getRenderer(Lnet/minecraft/entity/Entity;)Lnet/minecraft/client/render/entity/EntityRenderer;",
|
|
||||||
at = @At(
|
|
||||||
value = "INVOKE",
|
|
||||||
target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;getModel()Ljava/lang/String;"))
|
|
||||||
private String getPlayerModel(AbstractClientPlayerEntity player, Entity entity) {
|
|
||||||
if (player instanceof IPreviewModel) {
|
|
||||||
return player.getModel();
|
|
||||||
}
|
|
||||||
return IPony.getManager()
|
|
||||||
.getPony(player)
|
|
||||||
.race()
|
|
||||||
.getModelId(player.getModel().contains("slim"));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,7 +4,7 @@ import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
import com.minelittlepony.client.render.PonyRenderDispatcher;
|
import com.minelittlepony.client.MineLittlePony;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
@ -42,6 +42,6 @@ abstract class MixinHeldItemRenderer {
|
||||||
VertexConsumerProvider renderContext,
|
VertexConsumerProvider renderContext,
|
||||||
@Nullable World world,
|
@Nullable World world,
|
||||||
int lightUv, int overlayUv, int posLong) {
|
int lightUv, int overlayUv, int posLong) {
|
||||||
PonyRenderDispatcher.getInstance().getMagicRenderer().renderItemInFirstPerson(target, entity, item, transform, left, stack, renderContext, world, lightUv, posLong);
|
MineLittlePony.getInstance().getRenderDispatcher().getMagicRenderer().renderItem(target, entity, item, transform, left, stack, renderContext, world, lightUv, posLong);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package com.minelittlepony.client.model;
|
package com.minelittlepony.client.model;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.*;
|
import com.minelittlepony.api.model.*;
|
||||||
import com.minelittlepony.api.model.fabric.PonyModelPrepareCallback;
|
import com.minelittlepony.api.events.PonyModelPrepareCallback;
|
||||||
import com.minelittlepony.api.pony.meta.Sizes;
|
import com.minelittlepony.api.pony.meta.SizePreset;
|
||||||
import com.minelittlepony.client.transform.PonyTransformation;
|
import com.minelittlepony.client.transform.PonyTransformation;
|
||||||
import com.minelittlepony.client.util.render.RenderList;
|
import com.minelittlepony.client.util.render.RenderList;
|
||||||
import com.minelittlepony.util.MathUtil;
|
import com.minelittlepony.util.MathUtil;
|
||||||
|
import com.minelittlepony.util.MathUtil.Angles;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -15,7 +16,7 @@ import net.minecraft.client.model.ModelPart;
|
||||||
import net.minecraft.client.render.VertexConsumer;
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.util.Arm;
|
import net.minecraft.util.*;
|
||||||
import net.minecraft.util.math.*;
|
import net.minecraft.util.math.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,7 +50,7 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
|
|
||||||
protected final RenderList mainRenderList;
|
protected final RenderList mainRenderList;
|
||||||
|
|
||||||
private final List<IPart> parts = new ArrayList<>();
|
private final List<SubModel> parts = new ArrayList<>();
|
||||||
|
|
||||||
public AbstractPonyModel(ModelPart tree) {
|
public AbstractPonyModel(ModelPart tree) {
|
||||||
super(tree);
|
super(tree);
|
||||||
|
@ -65,18 +66,18 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
.add(withStage(BodyPart.HEAD, helmetRenderList = RenderList.of(hat)));
|
.add(withStage(BodyPart.HEAD, helmetRenderList = RenderList.of(hat)));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <P extends IPart> P addPart(P part) {
|
protected <P extends SubModel> P addPart(P part) {
|
||||||
parts.add(part);
|
parts.add(part);
|
||||||
return part;
|
return part;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected RenderList forPart(Supplier<IPart> part) {
|
protected RenderList forPart(Supplier<SubModel> part) {
|
||||||
return (stack, vertices, overlayUv, lightUv, red, green, blue, alpha) -> {
|
return (stack, vertices, overlayUv, lightUv, red, green, blue, alpha) -> {
|
||||||
part.get().renderPart(stack, vertices, overlayUv, lightUv, red, green, blue, alpha, attributes);
|
part.get().renderPart(stack, vertices, overlayUv, lightUv, red, green, blue, alpha, attributes);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected RenderList forPart(IPart part) {
|
protected RenderList forPart(SubModel part) {
|
||||||
return (stack, vertices, overlayUv, lightUv, red, green, blue, alpha) -> {
|
return (stack, vertices, overlayUv, lightUv, red, green, blue, alpha) -> {
|
||||||
part.renderPart(stack, vertices, overlayUv, lightUv, red, green, blue, alpha, attributes);
|
part.renderPart(stack, vertices, overlayUv, lightUv, red, green, blue, alpha, attributes);
|
||||||
};
|
};
|
||||||
|
@ -101,11 +102,11 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final void setAngles(T entity, float limbAngle, float limbSpeed, float animationProgress, float headYaw, float headPitch) {
|
public final void setAngles(T entity, float limbAngle, float limbSpeed, float animationProgress, float headYaw, float headPitch) {
|
||||||
attributes.checkRainboom(entity, canFly(), animationProgress);
|
attributes.checkRainboom(entity, this, animationProgress);
|
||||||
PonyModelPrepareCallback.EVENT.invoker().onPonyModelPrepared(entity, this, ModelAttributes.Mode.OTHER);
|
PonyModelPrepareCallback.EVENT.invoker().onPonyModelPrepared(entity, this, ModelAttributes.Mode.OTHER);
|
||||||
super.setAngles(entity, limbAngle, limbSpeed, animationProgress, headYaw, headPitch);
|
super.setAngles(entity, limbAngle, limbSpeed, animationProgress, headYaw, headPitch);
|
||||||
|
|
||||||
head.setPivot(head.getDefaultTransform().pivotX, head.getDefaultTransform().pivotY, head.getDefaultTransform().pivotZ);
|
resetPivot(head, neck, leftArm, rightArm, leftLeg, rightLeg);
|
||||||
|
|
||||||
setModelAngles(entity, limbAngle, limbSpeed, animationProgress, headYaw, headPitch);
|
setModelAngles(entity, limbAngle, limbSpeed, animationProgress, headYaw, headPitch);
|
||||||
|
|
||||||
|
@ -118,11 +119,10 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setModelAngles(T entity, float limbAngle, float limbSpeed, float animationProgress, float headYaw, float headPitch) {
|
protected void setModelAngles(T entity, float limbAngle, float limbSpeed, float animationProgress, float headYaw, float headPitch) {
|
||||||
|
float pitch = attributes.motionPitch * MathHelper.RADIANS_PER_DEGREE;
|
||||||
float pitch = (float)Math.toRadians(attributes.motionPitch);
|
|
||||||
head.setAngles(
|
head.setAngles(
|
||||||
MathHelper.clamp(attributes.isSleeping ? 0.1f : headPitch / 57.29578F, -1.25f - pitch, 0.5f - pitch),
|
MathHelper.clamp(attributes.isSleeping ? 0.1f : headPitch / 57.29578F, -1.25f - pitch, 0.5f - pitch),
|
||||||
attributes.isSleeping ? (Math.abs(entity.getUuid().getMostSignificantBits()) % 2.8F) - 1.9F : headYaw / 57.29578F,
|
attributes.isSleeping ? (Math.signum(MathHelper.wrapDegrees(headYaw)) * 1.3F) : headYaw * MathHelper.RADIANS_PER_DEGREE,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -148,10 +148,7 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
} else {
|
} else {
|
||||||
adjustBody(0, ORIGIN);
|
adjustBody(0, ORIGIN);
|
||||||
|
|
||||||
rightLeg.pivotY = FRONT_LEGS_Y;
|
if (!attributes.isLyingDown) {
|
||||||
leftLeg.pivotY = FRONT_LEGS_Y;
|
|
||||||
|
|
||||||
if (!attributes.isSleeping) {
|
|
||||||
animateBreathing(animationProgress);
|
animateBreathing(animationProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,11 +158,17 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attributes.isSleeping) {
|
if (attributes.isLyingDown) {
|
||||||
ponySleep();
|
ponySleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
parts.forEach(part -> part.setRotationAndAngles(attributes, limbAngle, limbSpeed, wobbleAmount, animationProgress));
|
if (attributes.isHorsey) {
|
||||||
|
head.pivotY -= 3;
|
||||||
|
head.pivotZ -= 2;
|
||||||
|
head.pitch = 0.5F;
|
||||||
|
}
|
||||||
|
|
||||||
|
parts.forEach(part -> part.setPartAngles(attributes, limbAngle, limbSpeed, wobbleAmount, animationProgress));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHeadRotation(float animationProgress, float yaw, float pitch) {
|
public void setHeadRotation(float animationProgress, float yaw, float pitch) {
|
||||||
|
@ -183,9 +186,6 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
|
|
||||||
rightArm.pitch -= LEG_SNEAKING_PITCH_ADJUSTMENT;
|
rightArm.pitch -= LEG_SNEAKING_PITCH_ADJUSTMENT;
|
||||||
leftArm.pitch -= LEG_SNEAKING_PITCH_ADJUSTMENT;
|
leftArm.pitch -= LEG_SNEAKING_PITCH_ADJUSTMENT;
|
||||||
|
|
||||||
leftLeg.pivotY = FRONT_LEGS_Y;
|
|
||||||
rightLeg.pivotY = FRONT_LEGS_Y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void ponySleep() {
|
protected void ponySleep() {
|
||||||
|
@ -196,7 +196,6 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
leftLeg.pitch = MathUtil.Angles._90_DEG;
|
leftLeg.pitch = MathUtil.Angles._90_DEG;
|
||||||
|
|
||||||
HEAD_SLEEPING.set(head);
|
HEAD_SLEEPING.set(head);
|
||||||
head.pivotZ = sneaking ? -1 : 1;
|
|
||||||
|
|
||||||
FONT_LEGS_SLEEPING.add(rightArm);
|
FONT_LEGS_SLEEPING.add(rightArm);
|
||||||
FONT_LEGS_SLEEPING.add(leftArm);
|
FONT_LEGS_SLEEPING.add(leftArm);
|
||||||
|
@ -275,6 +274,9 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
leftArm.pivotZ = 2 - sin;
|
leftArm.pivotZ = 2 - sin;
|
||||||
|
|
||||||
float legRPX = attributes.getMainInterpolator().interpolate("legOffset", cos - getLegOutset() - 0.001F, 2);
|
float legRPX = attributes.getMainInterpolator().interpolate("legOffset", cos - getLegOutset() - 0.001F, 2);
|
||||||
|
if (attributes.isHorsey) {
|
||||||
|
legRPX += 2;
|
||||||
|
}
|
||||||
|
|
||||||
rightArm.pivotX = -legRPX;
|
rightArm.pivotX = -legRPX;
|
||||||
rightLeg.pivotX = -legRPX;
|
rightLeg.pivotX = -legRPX;
|
||||||
|
@ -285,8 +287,12 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
rightArm.yaw += body.yaw;
|
rightArm.yaw += body.yaw;
|
||||||
leftArm.yaw += body.yaw;
|
leftArm.yaw += body.yaw;
|
||||||
|
|
||||||
rightArm.pivotY = leftArm.pivotY = 8;
|
if (attributes.isHorsey) {
|
||||||
rightLeg.pivotZ = leftLeg.pivotZ = 11;
|
rightArm.pivotZ = leftArm.pivotZ = -1;
|
||||||
|
rightArm.pivotY = leftArm.pivotY = 6;
|
||||||
|
rightLeg.pivotZ = leftLeg.pivotZ = 19;
|
||||||
|
rightLeg.pivotY = leftLeg.pivotY = 6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -333,7 +339,7 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float getLegOutset() {
|
protected float getLegOutset() {
|
||||||
if (attributes.isSleeping) {
|
if (attributes.isLyingDown) {
|
||||||
return 3.6f;
|
return 3.6f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,6 +366,7 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
case NECK: return neck;
|
case NECK: return neck;
|
||||||
case TAIL:
|
case TAIL:
|
||||||
case LEGS:
|
case LEGS:
|
||||||
|
case BACK:
|
||||||
case BODY: return body;
|
case BODY: return body;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,13 +387,14 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
|
|
||||||
if (attributes.shouldLiftArm(pose, complement, sigma)) {
|
if (attributes.shouldLiftArm(pose, complement, sigma)) {
|
||||||
float swag = 1;
|
float swag = 1;
|
||||||
if (!isFlying() && both) {
|
if (!getAttributes().isFlying && both) {
|
||||||
swag -= (float)Math.pow(limbSpeed, 2);
|
swag -= (float)Math.pow(limbSpeed, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
float mult = 1 - swag/2;
|
float mult = 1 - swag/2;
|
||||||
arm.pitch = arm.pitch * mult - (MathHelper.PI / 10) * swag;
|
arm.pitch = arm.pitch * mult - (MathHelper.PI / 10) * swag;
|
||||||
arm.roll = -sigma * (MathHelper.PI / 15);
|
arm.roll = -sigma * (MathHelper.PI / 15);
|
||||||
|
arm.roll += 0.3F * -limbSpeed * sigma;
|
||||||
|
|
||||||
if (attributes.isCrouching) {
|
if (attributes.isCrouching) {
|
||||||
arm.pivotX -= sigma * 2;
|
arm.pivotX -= sigma * 2;
|
||||||
|
@ -400,6 +408,7 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
case BLOCK:
|
case BLOCK:
|
||||||
arm.pitch = (arm.pitch / 2 - 0.9424779F) - 0.3F;
|
arm.pitch = (arm.pitch / 2 - 0.9424779F) - 0.3F;
|
||||||
arm.yaw = sigma * MathHelper.PI / 9;
|
arm.yaw = sigma * MathHelper.PI / 9;
|
||||||
|
arm.roll += 0.3F * -limbSpeed * sigma;
|
||||||
if (complement == pose) {
|
if (complement == pose) {
|
||||||
arm.yaw -= sigma * MathHelper.PI / 18;
|
arm.yaw -= sigma * MathHelper.PI / 18;
|
||||||
}
|
}
|
||||||
|
@ -423,9 +432,12 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
|
|
||||||
arm.pitch = -0.8F;
|
arm.pitch = -0.8F;
|
||||||
arm.yaw = head.yaw + 0.06F;
|
arm.yaw = head.yaw + 0.06F;
|
||||||
|
arm.roll += 0.3F * -limbSpeed * sigma;
|
||||||
break;
|
break;
|
||||||
case THROW_SPEAR:
|
case THROW_SPEAR:
|
||||||
arm.pitch = MathUtil.Angles._90_DEG * 2;
|
arm.pitch = MathUtil.Angles._90_DEG * 2;
|
||||||
|
arm.roll += (0.3F * -limbSpeed + 0.6F) * sigma;
|
||||||
|
arm.pivotY ++;
|
||||||
break;
|
break;
|
||||||
case SPYGLASS:
|
case SPYGLASS:
|
||||||
float addedPitch = sneaking ? -0.2617994F : 0;
|
float addedPitch = sneaking ? -0.2617994F : 0;
|
||||||
|
@ -438,13 +450,24 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
arm.pivotX -= 6 * sigma;
|
arm.pivotX -= 6 * sigma;
|
||||||
arm.pivotZ -= 2;
|
arm.pivotZ -= 2;
|
||||||
}
|
}
|
||||||
if (getSize() == Sizes.TALL) {
|
if (getSize() == SizePreset.TALL) {
|
||||||
arm.pivotY += 1;
|
arm.pivotY += 1;
|
||||||
}
|
}
|
||||||
if (getSize() == Sizes.FOAL) {
|
if (getSize() == SizePreset.FOAL) {
|
||||||
arm.pivotY -= 2;
|
arm.pivotY -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case TOOT_HORN:
|
||||||
|
arm.pitch = MathHelper.clamp(head.pitch, -0.55f, 1.2f) - 1.7835298f;
|
||||||
|
arm.yaw = head.yaw - 0.1235988f * sigma;
|
||||||
|
arm.pivotY += 3;
|
||||||
|
arm.roll += 0.3F * -limbSpeed * sigma;
|
||||||
|
break;
|
||||||
|
case BRUSH:
|
||||||
|
arm.pitch = arm.pitch * 0.5f - 0.62831855f;
|
||||||
|
arm.yaw = 0;
|
||||||
|
arm.roll += 0.3F * -limbSpeed * sigma;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -467,7 +490,7 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
* @param entity The entity we are being called for.
|
* @param entity The entity we are being called for.
|
||||||
*/
|
*/
|
||||||
protected void swingItem(T entity) {
|
protected void swingItem(T entity) {
|
||||||
if (getSwingAmount() > 0 && !attributes.isSleeping) {
|
if (getSwingAmount() > 0 && !attributes.isLyingDown) {
|
||||||
Arm mainSide = getPreferredArm(entity);
|
Arm mainSide = getPreferredArm(entity);
|
||||||
|
|
||||||
swingArm(getArm(mainSide));
|
swingArm(getArm(mainSide));
|
||||||
|
@ -517,7 +540,14 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
|
|
||||||
protected void adjustBody(float pitch, Pivot pivot) {
|
protected void adjustBody(float pitch, Pivot pivot) {
|
||||||
adjustBodyComponents(pitch, pivot);
|
adjustBodyComponents(pitch, pivot);
|
||||||
|
if (!attributes.isHorsey) {
|
||||||
neck.setPivot(NECK_X + pitch, pivot.y(), pivot.z());
|
neck.setPivot(NECK_X + pitch, pivot.y(), pivot.z());
|
||||||
|
rightLeg.pivotY = FRONT_LEGS_Y;
|
||||||
|
leftLeg.pivotY = FRONT_LEGS_Y;
|
||||||
|
} else {
|
||||||
|
neck.setPivot(NECK_X + pitch, pivot.y() - 1, pivot.z() - 2);
|
||||||
|
neck.pitch = Angles._30_DEG;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void adjustBodyComponents(float pitch, Pivot pivot) {
|
protected void adjustBodyComponents(float pitch, Pivot pivot) {
|
||||||
|
@ -528,7 +558,7 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getRiderYOffset() {
|
public float getRiderYOffset() {
|
||||||
switch ((Sizes)getSize()) {
|
switch ((SizePreset)getSize()) {
|
||||||
case NORMAL: return 0.4F;
|
case NORMAL: return 0.4F;
|
||||||
case FOAL:
|
case FOAL:
|
||||||
case TALL:
|
case TALL:
|
||||||
|
@ -541,16 +571,77 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
|
||||||
public void setVisible(boolean visible) {
|
public void setVisible(boolean visible) {
|
||||||
super.setVisible(visible);
|
super.setVisible(visible);
|
||||||
neck.visible = visible;
|
neck.visible = visible;
|
||||||
|
hat.visible &= !attributes.isHorsey;
|
||||||
parts.forEach(part -> part.setVisible(visible, attributes));
|
parts.forEach(part -> part.setVisible(visible, attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void setArmAngle(Arm arm, MatrixStack matrices) {
|
||||||
|
super.setArmAngle(arm, matrices);
|
||||||
|
positionheldItem(arm, matrices);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void positionheldItem(Arm arm, MatrixStack matrices) {
|
||||||
|
float left = arm == Arm.LEFT ? -1 : 1;
|
||||||
|
|
||||||
|
UseAction action = getAttributes().heldStack.getUseAction();
|
||||||
|
|
||||||
|
if (action == UseAction.SPYGLASS && getAttributes().itemUseTime > 0) {
|
||||||
|
|
||||||
|
Arm main = getAttributes().mainArm;
|
||||||
|
if (getAttributes().activeHand == Hand.OFF_HAND) {
|
||||||
|
main = main.getOpposite();
|
||||||
|
}
|
||||||
|
if (main == arm) {
|
||||||
|
matrices.translate(left * -0.05F, 0.5F, 0.2F);
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(-60));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getAttributes().isRidingInteractive) {
|
||||||
|
matrices.translate(left / 10, -0.2F, -0.5F);
|
||||||
|
}
|
||||||
|
|
||||||
|
matrices.translate(-left * 0.1F, 0.45F, 0);
|
||||||
|
|
||||||
|
if (getAttributes().heldStack.getUseAction() == UseAction.BLOCK && getAttributes().itemUseTime == 0) {
|
||||||
|
matrices.translate(left * 0.02F, -0.25F, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void transform(BodyPart part, MatrixStack stack) {
|
public void transform(BodyPart part, MatrixStack stack) {
|
||||||
|
|
||||||
|
if (attributes.isHorsey) {
|
||||||
|
stack.translate(0, 0.1F, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (attributes.isSleeping || attributes.isRiptide) {
|
if (attributes.isSleeping || attributes.isRiptide) {
|
||||||
stack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
|
stack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
|
||||||
stack.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180));
|
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) {
|
||||||
|
if (part == BodyPart.BODY) {
|
||||||
|
stack.scale(1.5F, 1, 1.5F);
|
||||||
|
}
|
||||||
|
|
||||||
|
neck.visible = head.visible;
|
||||||
|
} else {
|
||||||
|
neck.hidden = !head.visible;
|
||||||
|
}
|
||||||
|
|
||||||
PonyTransformation.forSize(getSize()).transform(this, part, stack);
|
PonyTransformation.forSize(getSize()).transform(this, part, stack);
|
||||||
|
|
||||||
|
attributes.isCrouching = crouching;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,12 @@ import net.minecraft.util.Hand;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.ModelAttributes;
|
import com.minelittlepony.api.events.PonyModelPrepareCallback;
|
||||||
import com.minelittlepony.api.model.fabric.PonyModelPrepareCallback;
|
import com.minelittlepony.api.model.*;
|
||||||
import com.minelittlepony.api.pony.IPony;
|
import com.minelittlepony.api.pony.Pony;
|
||||||
import com.minelittlepony.api.pony.IPonyData;
|
import com.minelittlepony.api.pony.PonyData;
|
||||||
import com.minelittlepony.api.pony.meta.Size;
|
import com.minelittlepony.api.pony.meta.Size;
|
||||||
import com.minelittlepony.api.pony.meta.Sizes;
|
import com.minelittlepony.api.pony.meta.SizePreset;
|
||||||
import com.minelittlepony.mson.api.model.biped.MsonPlayer;
|
import com.minelittlepony.mson.api.model.biped.MsonPlayer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,7 +23,7 @@ import com.minelittlepony.mson.api.model.biped.MsonPlayer;
|
||||||
*
|
*
|
||||||
* Modders can extend this class to make their own pony models if they wish.
|
* Modders can extend this class to make their own pony models if they wish.
|
||||||
*/
|
*/
|
||||||
public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer<T> implements IPonyModel<T>, ModelWithHat {
|
public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer<T> implements PonyModel<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The model attributes.
|
* The model attributes.
|
||||||
|
@ -47,11 +47,11 @@ public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLivingState(T entity, IPony pony, ModelAttributes.Mode mode) {
|
public void updateLivingState(T entity, Pony pony, ModelAttributes.Mode mode) {
|
||||||
child = entity.isBaby();
|
child = entity.isBaby();
|
||||||
attributes.updateLivingState(entity, pony, mode);
|
attributes.updateLivingState(entity, pony, mode);
|
||||||
PonyModelPrepareCallback.EVENT.invoker().onPonyModelPrepared(entity, this, mode);
|
PonyModelPrepareCallback.EVENT.invoker().onPonyModelPrepared(entity, this, mode);
|
||||||
sneaking = attributes.isCrouching;
|
sneaking = attributes.isCrouching && !attributes.isLyingDown;
|
||||||
riding = attributes.isSitting;
|
riding = attributes.isSitting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,35 +60,6 @@ public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer
|
||||||
copyStateTo(other);
|
copyStateTo(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public final ModelAttributes getAttributes() {
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Size getSize() {
|
|
||||||
return child ? Sizes.FOAL : getMetadata().getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setMetadata(IPonyData meta) {
|
|
||||||
attributes.metadata = meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getSwingAmount() {
|
|
||||||
return handSwingProgress;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ModelPart getArm(Arm side) {
|
|
||||||
return super.getArm(side);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArmPose getArmPoseForSide(Arm side) {
|
|
||||||
return side == Arm.RIGHT ? rightArmPose : leftArmPose;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies this model's attributes into the passed model.
|
* Copies this model's attributes into the passed model.
|
||||||
*/
|
*/
|
||||||
|
@ -101,11 +72,56 @@ public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ModelAttributes getAttributes() {
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Size getSize() {
|
||||||
|
return child ? SizePreset.FOAL : PonyModel.super.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMetadata(PonyData meta) {
|
||||||
|
attributes.metadata = meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getSwingAmount() {
|
||||||
|
return handSwingProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart getForeLeg(Arm side) {
|
||||||
|
return getArm(side);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart getHindLeg(Arm side) {
|
||||||
|
return side == Arm.LEFT ? leftLeg : rightLeg;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArmPose getArmPoseForSide(Arm side) {
|
||||||
|
return side == Arm.RIGHT ? rightArmPose : leftArmPose;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setHatVisible(boolean visible) {
|
public void setHatVisible(boolean visible) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void resetPivot(ModelPart part) {
|
||||||
|
part.setPivot(part.getDefaultTransform().pivotX, part.getDefaultTransform().pivotY, part.getDefaultTransform().pivotZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resetPivot(ModelPart...parts) {
|
||||||
|
for (ModelPart part : parts) {
|
||||||
|
resetPivot(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public interface PosingCallback<T extends LivingEntity> {
|
public interface PosingCallback<T extends LivingEntity> {
|
||||||
void poseModel(ClientPonyModel<T> model, float move, float swing, float ticks, T entity);
|
void poseModel(ClientPonyModel<T> model, float move, float swing, float ticks, T entity);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
package com.minelittlepony.client.model;
|
|
||||||
|
|
||||||
import net.minecraft.client.model.ModelPart;
|
|
||||||
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
|
||||||
|
|
||||||
import com.minelittlepony.api.model.BodyPart;
|
|
||||||
import com.minelittlepony.api.model.ICapitated;
|
|
||||||
import com.minelittlepony.api.model.IModel;
|
|
||||||
import com.minelittlepony.api.model.ModelAttributes;
|
|
||||||
import com.minelittlepony.api.pony.IPony;
|
|
||||||
import com.minelittlepony.mson.api.MsonModel;
|
|
||||||
|
|
||||||
public interface IPonyModel<T extends LivingEntity> extends IModel, ICapitated<ModelPart>, MsonModel {
|
|
||||||
|
|
||||||
void copyAttributes(BipedEntityModel<T> other);
|
|
||||||
|
|
||||||
void updateLivingState(T entity, IPony pony, ModelAttributes.Mode mode);
|
|
||||||
|
|
||||||
ModelPart getBodyPart(BodyPart part);
|
|
||||||
}
|
|
106
src/main/java/com/minelittlepony/client/model/ModelKeyImpl.java
Normal file
106
src/main/java/com/minelittlepony/client/model/ModelKeyImpl.java
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
package com.minelittlepony.client.model;
|
||||||
|
|
||||||
|
import net.minecraft.client.model.Model;
|
||||||
|
import net.minecraft.client.model.ModelPart;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.Util;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.minelittlepony.api.config.PonyConfig;
|
||||||
|
import com.minelittlepony.mson.api.*;
|
||||||
|
import com.minelittlepony.mson.api.MsonModel.Factory;
|
||||||
|
import com.minelittlepony.mson.api.model.traversal.PartSkeleton;
|
||||||
|
import com.minelittlepony.mson.api.model.traversal.SkeletonisedModel;
|
||||||
|
import com.minelittlepony.mson.api.parser.FileContent;
|
||||||
|
import com.minelittlepony.mson.api.parser.locals.LocalBlock;
|
||||||
|
import com.minelittlepony.mson.impl.model.RootContext;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
final class ModelKeyImpl<M extends Model> implements ModelKey<M>, LocalBlock {
|
||||||
|
|
||||||
|
private final Map<String, Incomplete<Float>> horseModeValues = Util.make(new HashMap<>(), map -> {
|
||||||
|
map.put("head_elongation", Incomplete.completed(-1F));
|
||||||
|
map.put("neck_dilate_z", Incomplete.completed(1.5F));
|
||||||
|
map.put("neck_dilate_y", Incomplete.completed(3F));
|
||||||
|
map.put("global_ear_shortening", Incomplete.completed(-0.5F));
|
||||||
|
});
|
||||||
|
|
||||||
|
private final ModelKey<M> key;
|
||||||
|
private final MsonModel.Factory<M> constr;
|
||||||
|
|
||||||
|
ModelKeyImpl(Identifier id, MsonModel.Factory<M> constr) {
|
||||||
|
this.key = Mson.getInstance().registerModel(id, constr);
|
||||||
|
this.constr = constr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Identifier getId() {
|
||||||
|
return key.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public <V extends M> V createModel() {
|
||||||
|
return (V)createModel(constr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <V extends M> V createModel(Factory<V> factory) {
|
||||||
|
Preconditions.checkNotNull(factory, "Factory should not be null");
|
||||||
|
|
||||||
|
return getModelData().map(content -> {
|
||||||
|
|
||||||
|
ModelContext ctx = getModelContext(content);
|
||||||
|
|
||||||
|
ModelPart root = ctx.toTree();
|
||||||
|
V t = factory.create(root);
|
||||||
|
|
||||||
|
if (t instanceof SkeletonisedModel) {
|
||||||
|
((SkeletonisedModel)t).setSkeleton(content.getSkeleton()
|
||||||
|
.map(s -> PartSkeleton.of(root, s))
|
||||||
|
.orElseGet(() -> PartSkeleton.of(root)));
|
||||||
|
}
|
||||||
|
if (t instanceof MsonModel) {
|
||||||
|
if (ctx instanceof RootContext) {
|
||||||
|
((RootContext)ctx).setModel(t);
|
||||||
|
}
|
||||||
|
((MsonModel)t).init(ctx);
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
})
|
||||||
|
.orElseThrow(() -> new IllegalStateException("Model file for " + getId() + " was not loaded!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<ModelPart> createTree() {
|
||||||
|
return getModelData().map(this::getModelContext).map(ModelContext::toTree);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModelContext getModelContext(FileContent<?> content) {
|
||||||
|
if (PonyConfig.getInstance().horsieMode.get()) {
|
||||||
|
return content.createContext(null, null, content.getLocals().extendWith(getId(), Optional.of(this), Optional.empty()).bake());
|
||||||
|
}
|
||||||
|
return content.createContext(null, null, content.getLocals().bake());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<FileContent<?>> getModelData() {
|
||||||
|
return key.getModelData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> appendKeys(Set<String> output) {
|
||||||
|
output.addAll(horseModeValues.keySet());
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<CompletableFuture<Incomplete<Float>>> get(String name) {
|
||||||
|
if (horseModeValues.containsKey(name)) {
|
||||||
|
return Optional.of(CompletableFuture.completedFuture(horseModeValues.get(name)));
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,16 +8,15 @@ import net.minecraft.entity.mob.VexEntity;
|
||||||
import net.minecraft.entity.passive.*;
|
import net.minecraft.entity.passive.*;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.IModel;
|
import com.minelittlepony.api.model.BodyPart;
|
||||||
import com.minelittlepony.api.model.gear.IGear;
|
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.Race;
|
||||||
import com.minelittlepony.api.pony.meta.Wearable;
|
import com.minelittlepony.api.pony.meta.Wearable;
|
||||||
import com.minelittlepony.client.model.armour.PonyArmourModel;
|
import com.minelittlepony.client.model.armour.PonyArmourModel;
|
||||||
import com.minelittlepony.client.model.entity.*;
|
import com.minelittlepony.client.model.entity.*;
|
||||||
import com.minelittlepony.client.model.entity.race.*;
|
import com.minelittlepony.client.model.entity.race.*;
|
||||||
import com.minelittlepony.client.model.gear.*;
|
import com.minelittlepony.client.model.gear.*;
|
||||||
import com.minelittlepony.client.render.entity.PlayerPonyRenderer;
|
|
||||||
import com.minelittlepony.client.render.entity.PlayerSeaponyRenderer;
|
|
||||||
import com.minelittlepony.mson.api.ModelKey;
|
import com.minelittlepony.mson.api.ModelKey;
|
||||||
import com.minelittlepony.mson.api.Mson;
|
import com.minelittlepony.mson.api.Mson;
|
||||||
import com.minelittlepony.mson.api.MsonModel;
|
import com.minelittlepony.mson.api.MsonModel;
|
||||||
|
@ -31,7 +30,7 @@ import java.util.stream.Stream;
|
||||||
|
|
||||||
public final class ModelType {
|
public final class ModelType {
|
||||||
private static final Map<Race, PlayerModelKey<?, ?>> PLAYER_MODELS = new HashMap<>();
|
private static final Map<Race, PlayerModelKey<?, ?>> PLAYER_MODELS = new HashMap<>();
|
||||||
private static final Map<Wearable, GearModelKey<? extends IGear>> GEAR_MODELS = new HashMap<>();
|
private static final Map<Wearable, GearModelKey<? extends Gear>> GEAR_MODELS = new HashMap<>();
|
||||||
|
|
||||||
public static final ModelKey<DJPon3EarsModel> DJ_PON_3 = register("dj_pon_three", DJPon3EarsModel::new);
|
public static final ModelKey<DJPon3EarsModel> DJ_PON_3 = register("dj_pon_three", DJPon3EarsModel::new);
|
||||||
|
|
||||||
|
@ -57,78 +56,69 @@ public final class ModelType {
|
||||||
public static final ModelKey<PonyArmourModel<?>> INNER_PONY_ARMOR = register("armor/inner_pony_armor", PonyArmourModel::new);
|
public static final ModelKey<PonyArmourModel<?>> INNER_PONY_ARMOR = register("armor/inner_pony_armor", PonyArmourModel::new);
|
||||||
public static final ModelKey<PonyArmourModel<?>> OUTER_PONY_ARMOR = register("armor/outer_pony_armor", PonyArmourModel::new);
|
public static final ModelKey<PonyArmourModel<?>> OUTER_PONY_ARMOR = register("armor/outer_pony_armor", PonyArmourModel::new);
|
||||||
|
|
||||||
public static final GearModelKey<Stetson> STETSON = registerGear("stetson", Wearable.STETSON, Stetson::new);
|
public static final GearModelKey<AbstractGearModel> STETSON = registerGear("stetson", Wearable.STETSON, t -> new WearableGear(Wearable.STETSON, BodyPart.HEAD, 0.15F));
|
||||||
public static final GearModelKey<SaddleBags> SADDLEBAGS_BOTH = registerGear("saddlebags", Wearable.SADDLE_BAGS_BOTH, t -> new SaddleBags(t, Wearable.SADDLE_BAGS_BOTH));
|
public static final GearModelKey<SaddleBags> SADDLEBAGS_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_LEFT = registerGear(SADDLEBAGS_BOTH, Wearable.SADDLE_BAGS_LEFT, t -> new SaddleBags(t, Wearable.SADDLE_BAGS_LEFT));
|
||||||
public static final GearModelKey<SaddleBags> SADDLEBAGS_RIGHT = registerGear(SADDLEBAGS_BOTH, Wearable.SADDLE_BAGS_RIGHT, t -> new SaddleBags(t, Wearable.SADDLE_BAGS_RIGHT));
|
public static final GearModelKey<SaddleBags> SADDLEBAGS_RIGHT = registerGear(SADDLEBAGS_BOTH, Wearable.SADDLE_BAGS_RIGHT, t -> new SaddleBags(t, Wearable.SADDLE_BAGS_RIGHT));
|
||||||
public static final GearModelKey<Crown> CROWN = registerGear("crown", Wearable.CROWN, Crown::new);
|
public static final GearModelKey<Crown> CROWN = registerGear("crown", Wearable.CROWN, Crown::new);
|
||||||
public static final GearModelKey<Muffin> MUFFIN = registerGear("muffin", Wearable.MUFFIN, Muffin::new);
|
public static final GearModelKey<AbstractGearModel> MUFFIN = registerGear("muffin", Wearable.MUFFIN, t -> new WearableGear(Wearable.MUFFIN, BodyPart.HEAD, 0.45F).addPart(t.getChild("crown")));
|
||||||
public static final GearModelKey<WitchHat> WITCH_HAT = registerGear("witch_hat", Wearable.HAT, WitchHat::new);
|
public static final GearModelKey<AbstractGearModel> WITCH_HAT = registerGear("witch_hat", Wearable.HAT, t -> new WearableGear(Wearable.HAT, BodyPart.HEAD, 0.7F).addPart(t.getChild("hat")));
|
||||||
public static final GearModelKey<ChristmasHat> ANTLERS = registerGear("antlers", Wearable.ANTLERS, ChristmasHat::new);
|
public static final GearModelKey<DeerAntlers> ANTLERS = registerGear("antlers", Wearable.ANTLERS, DeerAntlers::new);
|
||||||
|
|
||||||
public static final PlayerModelKey<LivingEntity, AlicornModel<?>> ALICORN = registerPlayer("alicorn", Race.ALICORN, AlicornModel::new);
|
public static final PlayerModelKey<LivingEntity, AlicornModel<?>> ALICORN = registerPlayer("alicorn", Race.ALICORN, AlicornModel::new);
|
||||||
public static final PlayerModelKey<LivingEntity, UnicornModel<?>> UNICORN = registerPlayer("unicorn", Race.UNICORN, UnicornModel::new);
|
public static final PlayerModelKey<LivingEntity, UnicornModel<?>> UNICORN = registerPlayer("unicorn", Race.UNICORN, UnicornModel::new);
|
||||||
public static final PlayerModelKey<LivingEntity, UnicornModel<?>> KIRIN = registerPlayer("kirin", Race.KIRIN, UnicornModel::new);
|
public static final PlayerModelKey<LivingEntity, KirinModel<?>> KIRIN = registerPlayer("kirin", Race.KIRIN, KirinModel::new);
|
||||||
public static final PlayerModelKey<LivingEntity, PegasusModel<?>> PEGASUS = registerPlayer("pegasus", Race.PEGASUS, PegasusModel::new);
|
public static final PlayerModelKey<LivingEntity, PegasusModel<?>> PEGASUS = registerPlayer("pegasus", Race.PEGASUS, PegasusModel::new);
|
||||||
public static final PlayerModelKey<LivingEntity, PegasusModel<?>> GRYPHON = registerPlayer("gryphon", Race.GRYPHON, PegasusModel::new);
|
public static final PlayerModelKey<LivingEntity, PegasusModel<?>> GRYPHON = registerPlayer("gryphon", Race.GRYPHON, PegasusModel::new);
|
||||||
public static final PlayerModelKey<LivingEntity, PegasusModel<?>> HIPPOGRIFF = registerPlayer("hippogriff", Race.HIPPOGRIFF, PegasusModel::new);
|
public static final PlayerModelKey<LivingEntity, PegasusModel<?>> HIPPOGRIFF = registerPlayer("hippogriff", Race.HIPPOGRIFF, PegasusModel::new, PonyArmourModel::new);
|
||||||
public static final PlayerModelKey<LivingEntity, EarthPonyModel<?>> EARTH_PONY = registerPlayer("earth_pony", Race.EARTH, EarthPonyModel::new);
|
public static final PlayerModelKey<LivingEntity, EarthPonyModel<?>> EARTH_PONY = registerPlayer("earth_pony", Race.EARTH, EarthPonyModel::new);
|
||||||
public static final PlayerModelKey<LivingEntity, SeaponyModel<?>> SEA_PONY = registerPlayer("sea_pony", Race.SEAPONY, SeaponyModel::new, SeaponyModel.Armour::new, PlayerSeaponyRenderer::new);
|
public static final PlayerModelKey<LivingEntity, SeaponyModel<?>> SEA_PONY = registerPlayer("sea_pony", Race.SEAPONY, SeaponyModel::new, SeaponyModel.Armour::new);
|
||||||
public static final PlayerModelKey<LivingEntity, PegasusModel<?>> BAT_PONY = registerPlayer("bat_pony", Race.BATPONY, PegasusModel::new);
|
public static final PlayerModelKey<LivingEntity, PegasusModel<?>> BAT_PONY = registerPlayer("bat_pony", Race.BATPONY, PegasusModel::new);
|
||||||
public static final PlayerModelKey<LivingEntity, ChangelingModel<?>> CHANGELING = registerPlayer("changeling", Race.CHANGELING, ChangelingModel::new);
|
public static final PlayerModelKey<LivingEntity, ChangelingModel<?>> CHANGELING = registerPlayer("changeling", Race.CHANGELING, ChangelingModel::new);
|
||||||
public static final PlayerModelKey<LivingEntity, ChangelingModel<?>> CHANGEDLING = registerPlayer("reformed_changeling", Race.CHANGEDLING, ChangelingModel::new);
|
public static final PlayerModelKey<LivingEntity, ChangelingModel<?>> CHANGEDLING = registerPlayer("reformed_changeling", Race.CHANGEDLING, ChangelingModel::new);
|
||||||
public static final PlayerModelKey<LivingEntity, EarthPonyModel<?>> ZEBRA = registerPlayer("zebra", Race.ZEBRA, EarthPonyModel::new);
|
public static final PlayerModelKey<LivingEntity, EarthPonyModel<?>> ZEBRA = registerPlayer("zebra", Race.ZEBRA, EarthPonyModel::new);
|
||||||
|
|
||||||
static <E extends LivingEntity, T extends Model & MsonModel & IModel> PlayerModelKey<E, T> registerPlayer(String name, Race race,
|
static <E extends LivingEntity, T extends Model & MsonModel & PonyModel<?>> PlayerModelKey<E, T> registerPlayer(String name, Race race,
|
||||||
BiFunction<ModelPart, Boolean, T> constructor) {
|
BiFunction<ModelPart, Boolean, T> constructor) {
|
||||||
return registerPlayer(name, race, constructor, PlayerPonyRenderer::new);
|
return registerPlayer(name, race, constructor, PonyArmourModel::new);
|
||||||
}
|
|
||||||
|
|
||||||
static <E extends LivingEntity, T extends Model & MsonModel & IModel> PlayerModelKey<E, T> registerPlayer(String name, Race race,
|
|
||||||
BiFunction<ModelPart, Boolean, T> constructor,
|
|
||||||
PlayerModelKey.RendererFactory rendererFactory) {
|
|
||||||
return registerPlayer(name, race, constructor, PonyArmourModel::new, rendererFactory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
static <E extends LivingEntity, T extends Model & MsonModel & IModel> PlayerModelKey<E, T> registerPlayer(String name, Race race,
|
static <E extends LivingEntity, T extends Model & MsonModel & PonyModel<?>> PlayerModelKey<E, T> registerPlayer(String name, Race race,
|
||||||
BiFunction<ModelPart, Boolean, T> constructor,
|
BiFunction<ModelPart, Boolean, T> constructor,
|
||||||
MsonModel.Factory<PonyArmourModel<E>> armorFactory,
|
MsonModel.Factory<PonyArmourModel<E>> armorFactory) {
|
||||||
PlayerModelKey.RendererFactory rendererFactory) {
|
return (PlayerModelKey<E, T>)PLAYER_MODELS.computeIfAbsent(race, r -> new PlayerModelKey<>(name, constructor, armorFactory));
|
||||||
return (PlayerModelKey<E, T>)PLAYER_MODELS.computeIfAbsent(race, r -> {
|
|
||||||
return new PlayerModelKey<>(name, constructor, rendererFactory, armorFactory);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
static <T extends AbstractGear> GearModelKey<T> registerGear(String name, Wearable wearable, MsonModel.Factory<T> constructor) {
|
static <T extends AbstractGearModel> GearModelKey<T> registerGear(String name, Wearable wearable, MsonModel.Factory<T> constructor) {
|
||||||
return (GearModelKey<T>)GEAR_MODELS.computeIfAbsent(wearable, w -> {
|
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(new Identifier("minelittlepony", "gear/" + name), constructor), constructor);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
static <T extends AbstractGear> GearModelKey<T> registerGear(GearModelKey<T> key, Wearable wearable, MsonModel.Factory<T> constructor) {
|
static <T extends AbstractGearModel> GearModelKey<T> registerGear(GearModelKey<T> key, Wearable wearable, MsonModel.Factory<T> constructor) {
|
||||||
return (GearModelKey<T>)GEAR_MODELS.computeIfAbsent(wearable, w -> new GearModelKey<T>(key.key, constructor));
|
return (GearModelKey<T>)GEAR_MODELS.computeIfAbsent(wearable, w -> new GearModelKey<T>(key.key, constructor));
|
||||||
}
|
}
|
||||||
|
|
||||||
static <T extends Model> ModelKey<T> register(String name, MsonModel.Factory<T> constructor) {
|
static <T extends Model> ModelKey<T> register(String name, MsonModel.Factory<T> constructor) {
|
||||||
return Mson.getInstance().registerModel(new Identifier("minelittlepony", name), constructor);
|
return new ModelKeyImpl<T>(new Identifier("minelittlepony", name), constructor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Nullable
|
@Nullable
|
||||||
public static <E extends LivingEntity, T extends Model & MsonModel & IModel> PlayerModelKey<E, T> getPlayerModel(Race race) {
|
public static <E extends LivingEntity, T extends Model & MsonModel & PonyModel<?>> PlayerModelKey<E, T> getPlayerModel(Race race) {
|
||||||
return (PlayerModelKey<E, T>)PLAYER_MODELS.get(race);
|
return (PlayerModelKey<E, T>)PLAYER_MODELS.get(race);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Stream<Map.Entry<Wearable, GearModelKey<? extends IGear>>> getWearables() {
|
public static Stream<Map.Entry<Wearable, GearModelKey<? extends Gear>>> getWearables() {
|
||||||
return GEAR_MODELS.entrySet().stream();
|
return GEAR_MODELS.entrySet().stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bootstrap() { }
|
public static void bootstrap() { }
|
||||||
|
|
||||||
public record GearModelKey<T extends IGear>(ModelKey<T> key, MsonModel.Factory<T> constructor) {
|
public record GearModelKey<T extends Gear>(ModelKey<T> key, MsonModel.Factory<T> constructor) {
|
||||||
public T createModel() {
|
public T createModel() {
|
||||||
return key.createModel(constructor);
|
return key.createModel(constructor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,33 +2,27 @@ package com.minelittlepony.client.model;
|
||||||
|
|
||||||
import net.minecraft.client.model.Model;
|
import net.minecraft.client.model.Model;
|
||||||
import net.minecraft.client.model.ModelPart;
|
import net.minecraft.client.model.ModelPart;
|
||||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
|
||||||
import net.minecraft.client.render.entity.EntityRendererFactory;
|
|
||||||
import net.minecraft.client.render.entity.PlayerEntityRenderer;
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.IModel;
|
import com.minelittlepony.api.model.Models;
|
||||||
|
import com.minelittlepony.api.model.PonyModel;
|
||||||
import com.minelittlepony.client.model.armour.PonyArmourModel;
|
import com.minelittlepony.client.model.armour.PonyArmourModel;
|
||||||
import com.minelittlepony.mson.api.ModelKey;
|
import com.minelittlepony.mson.api.*;
|
||||||
import com.minelittlepony.mson.api.Mson;
|
|
||||||
import com.minelittlepony.mson.api.MsonModel;
|
|
||||||
|
|
||||||
import java.util.function.*;
|
import java.util.function.*;
|
||||||
|
|
||||||
public record PlayerModelKey<T extends LivingEntity, M extends Model & MsonModel & IModel> (
|
public record PlayerModelKey<T extends LivingEntity, M extends Model & PonyModel<?>> (
|
||||||
ModelKey<M> steveKey,
|
ModelKey<M> steveKey,
|
||||||
ModelKey<M> alexKey,
|
ModelKey<M> alexKey,
|
||||||
RendererFactory factory,
|
|
||||||
MsonModel.Factory<PonyArmourModel<T>> armorFactory
|
MsonModel.Factory<PonyArmourModel<T>> armorFactory
|
||||||
) {
|
) {
|
||||||
PlayerModelKey(String name, BiFunction<ModelPart, Boolean, M> modelFactory, RendererFactory rendererFactory, MsonModel.Factory<PonyArmourModel<T>> armorFactory) {
|
PlayerModelKey(String name, BiFunction<ModelPart, Boolean, M> modelFactory, MsonModel.Factory<PonyArmourModel<T>> armorFactory) {
|
||||||
this(
|
this(
|
||||||
Mson.getInstance().registerModel(new Identifier("minelittlepony", "races/steve/" + name), tree -> modelFactory.apply(tree, false)),
|
new ModelKeyImpl<>(new Identifier("minelittlepony", "races/steve/" + name), tree -> modelFactory.apply(tree, false)),
|
||||||
Mson.getInstance().registerModel(new Identifier("minelittlepony", "races/alex/" + name), tree -> modelFactory.apply(tree, true)),
|
new ModelKeyImpl<>(new Identifier("minelittlepony", "races/alex/" + name), tree -> modelFactory.apply(tree, true)),
|
||||||
rendererFactory,
|
|
||||||
armorFactory
|
armorFactory
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -37,25 +31,12 @@ public record PlayerModelKey<T extends LivingEntity, M extends Model & MsonModel
|
||||||
return slimArms ? alexKey : steveKey;
|
return slimArms ? alexKey : steveKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <K extends T, N extends M> ModelWrapper<K, N> create(boolean slimArms) {
|
public <E extends T, N extends M> Models<E, N> create(boolean slimArms) {
|
||||||
return create(slimArms, null);
|
return create(slimArms, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
public <K extends T, N extends M> ModelWrapper<K, N> create(boolean slimArms, @Nullable Consumer<N> initializer) {
|
public <E extends T, N extends M> Models<E, N> create(boolean slimArms, @Nullable Consumer<N> initializer) {
|
||||||
return new ModelWrapper(this, slimArms, initializer);
|
return new Models(this, slimArms, initializer);
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public Function<EntityRendererFactory.Context, PlayerEntityRenderer> getFactory(boolean slimArms) {
|
|
||||||
return d -> factory.create(d, slimArms, (PlayerModelKey<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>>)this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface RendererFactory {
|
|
||||||
PlayerEntityRenderer create(
|
|
||||||
EntityRendererFactory.Context context,
|
|
||||||
boolean slim,
|
|
||||||
PlayerModelKey<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> key
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package com.minelittlepony.api.model.armour;
|
package com.minelittlepony.client.model.armour;
|
||||||
|
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.registry.Registries;
|
import net.minecraft.registry.Registries;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
import com.minelittlepony.client.model.armour.PonyArmourModel;
|
|
||||||
import com.minelittlepony.mson.api.ModelKey;
|
import com.minelittlepony.mson.api.ModelKey;
|
||||||
import com.minelittlepony.mson.api.Mson;
|
import com.minelittlepony.mson.api.Mson;
|
||||||
|
|
||||||
|
@ -18,7 +17,7 @@ public interface ArmorModelRegistry {
|
||||||
if (id.getNamespace().equals("minecraft")) {
|
if (id.getNamespace().equals("minecraft")) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
return REGISTRY.computeIfAbsent(id.withPath(p -> "models/armor/" + layer.name().toLowerCase(Locale.ROOT) + "_" + p + ".json"), i -> {
|
return REGISTRY.computeIfAbsent(id.withPath(p -> "armor/" + layer.name().toLowerCase(Locale.ROOT) + "_" + p + ".json"), i -> {
|
||||||
return Optional.of(Mson.getInstance().registerModel(i, PonyArmourModel::new));
|
return Optional.of(Mson.getInstance().registerModel(i, PonyArmourModel::new));
|
||||||
}).filter(key -> key.getModelData().isPresent());
|
}).filter(key -> key.getModelData().isPresent());
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.minelittlepony.api.model.armour;
|
package com.minelittlepony.client.model.armour;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The layer used to render a given armour piece.
|
* The layer used to render a given armour piece.
|
|
@ -13,9 +13,6 @@ import com.google.common.base.Strings;
|
||||||
import com.google.common.cache.Cache;
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.minelittlepony.api.config.PonyConfig;
|
import com.minelittlepony.api.config.PonyConfig;
|
||||||
import com.minelittlepony.api.model.armour.ArmourLayer;
|
|
||||||
import com.minelittlepony.api.model.armour.ArmourVariant;
|
|
||||||
import com.minelittlepony.api.model.armour.IArmourTextureResolver;
|
|
||||||
import com.minelittlepony.util.ResourceUtil;
|
import com.minelittlepony.util.ResourceUtil;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
@ -38,8 +35,8 @@ import java.util.concurrent.TimeUnit;
|
||||||
* - the "minecraft" namespace is always replaced with "minelittlepony"
|
* - the "minecraft" namespace is always replaced with "minelittlepony"
|
||||||
* <p>
|
* <p>
|
||||||
*/
|
*/
|
||||||
public class DefaultArmourTextureResolver implements IArmourTextureResolver {
|
public class ArmourTextureResolver {
|
||||||
public static final DefaultArmourTextureResolver INSTANCE = new DefaultArmourTextureResolver();
|
public static final ArmourTextureResolver INSTANCE = new ArmourTextureResolver();
|
||||||
|
|
||||||
private final Cache<String, Identifier> cache = CacheBuilder.newBuilder()
|
private final Cache<String, Identifier> cache = CacheBuilder.newBuilder()
|
||||||
.expireAfterAccess(30, TimeUnit.SECONDS)
|
.expireAfterAccess(30, TimeUnit.SECONDS)
|
||||||
|
@ -49,7 +46,6 @@ public class DefaultArmourTextureResolver implements IArmourTextureResolver {
|
||||||
cache.invalidateAll();
|
cache.invalidateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Identifier getTexture(LivingEntity entity, ItemStack stack, EquipmentSlot slot, ArmourLayer layer, @Nullable String type) {
|
public Identifier getTexture(LivingEntity entity, ItemStack stack, EquipmentSlot slot, ArmourLayer layer, @Nullable String type) {
|
||||||
Identifier material = stack.getItem() instanceof ArmorItem armor
|
Identifier material = stack.getItem() instanceof ArmorItem armor
|
||||||
? new Identifier(armor.getMaterial().getName())
|
? new Identifier(armor.getMaterial().getName())
|
||||||
|
@ -129,7 +125,6 @@ public class DefaultArmourTextureResolver implements IArmourTextureResolver {
|
||||||
return MinecraftClient.getInstance().getResourceManager().getResource(texture).isPresent();
|
return MinecraftClient.getInstance().getResourceManager().getResource(texture).isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ArmourVariant getVariant(ArmourLayer layer, Identifier resolvedTexture) {
|
public ArmourVariant getVariant(ArmourLayer layer, Identifier resolvedTexture) {
|
||||||
if (resolvedTexture.getPath().endsWith("_pony.png")) {
|
if (resolvedTexture.getPath().endsWith("_pony.png")) {
|
||||||
return ArmourVariant.NORMAL;
|
return ArmourVariant.NORMAL;
|
|
@ -1,7 +1,6 @@
|
||||||
package com.minelittlepony.api.model.armour;
|
package com.minelittlepony.client.model.armour;
|
||||||
|
|
||||||
import com.minelittlepony.client.model.ModelType;
|
import com.minelittlepony.client.model.ModelType;
|
||||||
import com.minelittlepony.client.model.armour.PonyArmourModel;
|
|
||||||
import com.minelittlepony.mson.api.ModelKey;
|
import com.minelittlepony.mson.api.ModelKey;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
|
@ -5,20 +5,18 @@ import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.armour.*;
|
import com.minelittlepony.api.model.PonyModel;
|
||||||
import com.minelittlepony.client.model.AbstractPonyModel;
|
import com.minelittlepony.client.model.AbstractPonyModel;
|
||||||
import com.minelittlepony.client.model.IPonyModel;
|
|
||||||
|
|
||||||
public class PonyArmourModel<T extends LivingEntity> extends AbstractPonyModel<T> implements IArmourModel<T> {
|
public class PonyArmourModel<T extends LivingEntity> extends AbstractPonyModel<T> {
|
||||||
|
|
||||||
public PonyArmourModel(ModelPart tree) {
|
public PonyArmourModel(ModelPart tree) {
|
||||||
super(tree);
|
super(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean poseModel(T entity, float limbAngle, float limbDistance, float age, float headYaw, float headPitch,
|
public boolean poseModel(T entity, float limbAngle, float limbDistance, float age, float headYaw, float headPitch,
|
||||||
EquipmentSlot slot, ArmourLayer layer,
|
EquipmentSlot slot, ArmourLayer layer,
|
||||||
IPonyModel<T> mainModel) {
|
PonyModel<T> mainModel) {
|
||||||
|
|
||||||
if (!setVisibilities(slot, layer)) {
|
if (!setVisibilities(slot, layer)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -6,6 +6,8 @@ import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.entity.mob.EndermanEntity;
|
import net.minecraft.entity.mob.EndermanEntity;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
|
import com.minelittlepony.api.pony.meta.Race;
|
||||||
|
|
||||||
public class EnderStallionModel extends SkeleponyModel<EndermanEntity> {
|
public class EnderStallionModel extends SkeleponyModel<EndermanEntity> {
|
||||||
|
|
||||||
public boolean isCarrying;
|
public boolean isCarrying;
|
||||||
|
@ -54,8 +56,8 @@ public class EnderStallionModel extends SkeleponyModel<EndermanEntity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canFly() {
|
public Race getRace() {
|
||||||
return isAlicorn;
|
return isAlicorn ? (super.getRace().hasHorn() ? Race.ALICORN : Race.PEGASUS) : super.getRace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,10 +7,10 @@ import net.minecraft.client.render.entity.model.GuardianEntityModel;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.entity.mob.GuardianEntity;
|
import net.minecraft.entity.mob.GuardianEntity;
|
||||||
|
|
||||||
import com.minelittlepony.client.model.IPonyMixinModel;
|
import com.minelittlepony.api.model.PonyModelMixin;
|
||||||
import com.minelittlepony.client.model.entity.race.SeaponyModel;
|
import com.minelittlepony.client.model.entity.race.SeaponyModel;
|
||||||
|
|
||||||
public class GuardianPonyModel extends GuardianEntityModel implements IPonyMixinModel.Caster<GuardianEntity, SeaponyModel<GuardianEntity>, ModelPart> {
|
public class GuardianPonyModel extends GuardianEntityModel implements PonyModelMixin.Caster<GuardianEntity, SeaponyModel<GuardianEntity>, ModelPart> {
|
||||||
private final SeaponyModel<GuardianEntity> mixin;
|
private final SeaponyModel<GuardianEntity> mixin;
|
||||||
|
|
||||||
public GuardianPonyModel(ModelPart tree) {
|
public GuardianPonyModel(ModelPart tree) {
|
||||||
|
@ -18,28 +18,29 @@ public class GuardianPonyModel extends GuardianEntityModel implements IPonyMixin
|
||||||
mixin = new SeaponyModel<>(tree);
|
mixin = new SeaponyModel<>(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAngles(GuardianEntity entity, float move, float swing, float ticks, float headYaw, float headPitch) {
|
|
||||||
mixin().setAngles(entity, move, swing, ticks, headYaw, headPitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float limbDistance, float limbAngle, float tickDelta, float alpha) {
|
|
||||||
mixin().render(stack, vertices, overlayUv, lightUv, limbDistance, limbAngle, tickDelta, alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void animateModel(GuardianEntity entity, float move, float swing, float float_3) {
|
|
||||||
mixin().animateModel(entity, move, swing, float_3);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void copyStateTo(EntityModel<GuardianEntity> model) {
|
|
||||||
mixin().copyStateTo(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SeaponyModel<GuardianEntity> mixin() {
|
public SeaponyModel<GuardianEntity> mixin() {
|
||||||
return mixin;
|
return mixin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) {
|
||||||
|
mixin().render(matrices, vertices, light, overlay, red, green, blue, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void animateModel(GuardianEntity entity, float limbAngle, float limbDistance, float tickDelta) {
|
||||||
|
mixin().animateModel(entity, limbAngle, limbDistance, tickDelta);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyStateTo(EntityModel<GuardianEntity> copy) {
|
||||||
|
mixin().copyStateTo(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAngles(GuardianEntity entity, float limbAngle, float limbSpeed, float animationProgress, float headYaw, float headPitch) {
|
||||||
|
mixin().setVisible(true);
|
||||||
|
mixin().setAngles(entity, limbAngle, limbSpeed, animationProgress, headYaw, headPitch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import net.minecraft.entity.mob.PiglinActivity;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.ModelAttributes;
|
import com.minelittlepony.api.model.ModelAttributes;
|
||||||
import com.minelittlepony.api.pony.IPony;
|
import com.minelittlepony.api.pony.Pony;
|
||||||
|
|
||||||
public class PiglinPonyModel extends ZomponyModel<HostileEntity> {
|
public class PiglinPonyModel extends ZomponyModel<HostileEntity> {
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ public class PiglinPonyModel extends ZomponyModel<HostileEntity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLivingState(HostileEntity entity, IPony pony, ModelAttributes.Mode mode) {
|
public void updateLivingState(HostileEntity entity, Pony pony, ModelAttributes.Mode mode) {
|
||||||
super.updateLivingState(entity, pony, mode);
|
super.updateLivingState(entity, pony, mode);
|
||||||
leftArmPose = ArmPose.EMPTY;
|
leftArmPose = ArmPose.EMPTY;
|
||||||
rightArmPose = entity.getMainHandStack().isEmpty() ? ArmPose.EMPTY : ArmPose.ITEM;
|
rightArmPose = entity.getMainHandStack().isEmpty() ? ArmPose.EMPTY : ArmPose.ITEM;
|
||||||
|
|
|
@ -8,10 +8,10 @@ import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.Arm;
|
import net.minecraft.util.Arm;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
|
|
||||||
import com.minelittlepony.client.model.IMobModel;
|
import com.minelittlepony.api.model.MobPosingHelper;
|
||||||
import com.minelittlepony.client.model.entity.race.AlicornModel;
|
import com.minelittlepony.client.model.entity.race.AlicornModel;
|
||||||
|
|
||||||
public class SkeleponyModel<T extends HostileEntity> extends AlicornModel<T> implements IMobModel {
|
public class SkeleponyModel<T extends HostileEntity> extends AlicornModel<T> {
|
||||||
|
|
||||||
public boolean isUnicorn;
|
public boolean isUnicorn;
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ public class SkeleponyModel<T extends HostileEntity> extends AlicornModel<T> imp
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void rotateArmHolding(ModelPart arm, float direction, float swingProgress, float ticks) {
|
protected void rotateArmHolding(ModelPart arm, float direction, float swingProgress, float ticks) {
|
||||||
IMobModel.rotateArmHolding(arm, direction, swingProgress, ticks);
|
MobPosingHelper.rotateArmHolding(arm, direction, swingProgress, ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -78,7 +78,7 @@ public class SkeleponyModel<T extends HostileEntity> extends AlicornModel<T> imp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected float getLegOutset() {
|
protected float getLegOutset() {
|
||||||
if (attributes.isSleeping) return 2.6f;
|
if (attributes.isLyingDown) return 2.6f;
|
||||||
if (attributes.isCrouching) return 0;
|
if (attributes.isCrouching) return 0;
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
package com.minelittlepony.client.model.entity;
|
package com.minelittlepony.client.model.entity;
|
||||||
|
|
||||||
import net.minecraft.client.model.ModelPart;
|
import net.minecraft.client.model.ModelPart;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.entity.mob.WitchEntity;
|
import net.minecraft.entity.mob.WitchEntity;
|
||||||
|
import net.minecraft.util.*;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.RotationAxis;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.ModelAttributes;
|
import com.minelittlepony.api.model.ModelAttributes;
|
||||||
import com.minelittlepony.api.pony.IPony;
|
import com.minelittlepony.api.pony.Pony;
|
||||||
import com.minelittlepony.api.pony.meta.Wearable;
|
import com.minelittlepony.api.pony.meta.*;
|
||||||
import com.minelittlepony.client.model.entity.race.EarthPonyModel;
|
import com.minelittlepony.client.model.entity.race.EarthPonyModel;
|
||||||
|
|
||||||
public class WitchPonyModel extends EarthPonyModel<WitchEntity> {
|
public class WitchPonyModel extends EarthPonyModel<WitchEntity> {
|
||||||
|
@ -16,7 +19,7 @@ public class WitchPonyModel extends EarthPonyModel<WitchEntity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLivingState(WitchEntity entity, IPony pony, ModelAttributes.Mode mode) {
|
public void updateLivingState(WitchEntity entity, Pony pony, ModelAttributes.Mode mode) {
|
||||||
super.updateLivingState(entity, pony, mode);
|
super.updateLivingState(entity, pony, mode);
|
||||||
|
|
||||||
if (entity.hasCustomName() && "Filly".equals(entity.getCustomName().getString())) {
|
if (entity.hasCustomName() && "Filly".equals(entity.getCustomName().getString())) {
|
||||||
|
@ -61,10 +64,13 @@ public class WitchPonyModel extends EarthPonyModel<WitchEntity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isWearing(Wearable wearable) {
|
protected void positionheldItem(Arm arm, MatrixStack matrices) {
|
||||||
if (wearable == Wearable.HAT) {
|
super.positionheldItem(arm, matrices);
|
||||||
return true;
|
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(10));
|
||||||
}
|
}
|
||||||
return super.isWearing(wearable);
|
|
||||||
|
@Override
|
||||||
|
public boolean isWearing(Wearable wearable) {
|
||||||
|
return wearable == Wearable.HAT || super.isWearing(wearable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package com.minelittlepony.client.model.entity;
|
package com.minelittlepony.client.model.entity;
|
||||||
|
|
||||||
import com.minelittlepony.client.model.IMobModel;
|
import com.minelittlepony.api.model.MobPosingHelper;
|
||||||
|
import com.minelittlepony.api.pony.meta.Race;
|
||||||
import com.minelittlepony.client.model.entity.race.AlicornModel;
|
import com.minelittlepony.client.model.entity.race.AlicornModel;
|
||||||
import net.minecraft.client.model.ModelPart;
|
import net.minecraft.client.model.ModelPart;
|
||||||
import net.minecraft.entity.mob.HostileEntity;
|
import net.minecraft.entity.mob.HostileEntity;
|
||||||
|
|
||||||
public class ZomponyModel<Zombie extends HostileEntity> extends AlicornModel<Zombie> implements IMobModel {
|
public class ZomponyModel<Zombie extends HostileEntity> extends AlicornModel<Zombie> {
|
||||||
|
|
||||||
private boolean isPegasus;
|
private boolean isPegasus;
|
||||||
|
|
||||||
|
@ -23,13 +24,13 @@ public class ZomponyModel<Zombie extends HostileEntity> extends AlicornModel<Zom
|
||||||
protected void rotateLegs(float move, float swing, float ticks, Zombie entity) {
|
protected void rotateLegs(float move, float swing, float ticks, Zombie entity) {
|
||||||
super.rotateLegs(move, swing, ticks, entity);
|
super.rotateLegs(move, swing, ticks, entity);
|
||||||
if (isZombified(entity)) {
|
if (isZombified(entity)) {
|
||||||
IMobModel.rotateUndeadArms(this, move, ticks);
|
MobPosingHelper.rotateUndeadArms(this, move, ticks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canFly() {
|
public Race getRace() {
|
||||||
return isPegasus;
|
return isPegasus ? (super.getRace().hasHorn() ? Race.ALICORN : Race.PEGASUS) : super.getRace();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isZombified(Zombie entity) {
|
protected boolean isZombified(Zombie entity) {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
package com.minelittlepony.client.model.entity.race;
|
package com.minelittlepony.client.model.entity.race;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.IPart;
|
import com.minelittlepony.api.model.SubModel;
|
||||||
import com.minelittlepony.api.model.IPegasus;
|
import com.minelittlepony.api.model.WingedPonyModel;
|
||||||
import com.minelittlepony.client.model.part.PonyWings;
|
import com.minelittlepony.client.model.part.PonyWings;
|
||||||
import com.minelittlepony.mson.api.ModelView;
|
import com.minelittlepony.mson.api.ModelView;
|
||||||
|
|
||||||
import net.minecraft.client.model.ModelPart;
|
import net.minecraft.client.model.ModelPart;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
|
||||||
public class AlicornModel<T extends LivingEntity> extends UnicornModel<T> implements IPegasus {
|
public class AlicornModel<T extends LivingEntity> extends UnicornModel<T> implements WingedPonyModel<T> {
|
||||||
|
|
||||||
private PonyWings<AlicornModel<T>> wings;
|
private PonyWings<AlicornModel<T>> wings;
|
||||||
|
|
||||||
|
@ -20,11 +20,11 @@ public class AlicornModel<T extends LivingEntity> extends UnicornModel<T> implem
|
||||||
public void init(ModelView context) {
|
public void init(ModelView context) {
|
||||||
super.init(context);
|
super.init(context);
|
||||||
wings = addPart(context.findByName("wings"));
|
wings = addPart(context.findByName("wings"));
|
||||||
bodyRenderList.add(forPart(this::getWings).checked(this::canFly));
|
bodyRenderList.add(forPart(this::getWings).checked(() -> getRace().hasWings()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPart getWings() {
|
public SubModel getWings() {
|
||||||
return wings;
|
return wings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,12 @@ public class ChangelingModel<T extends LivingEntity> extends AlicornModel<T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean wingsAreOpen() {
|
public boolean wingsAreOpen() {
|
||||||
return (isFlying() || attributes.isCrouching) && !getAttributes().isGliding;
|
return (getAttributes().isFlying || getAttributes().isCrouching) && !getAttributes().isGliding;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getWingRotationFactor(float ticks) {
|
public float getWingRotationFactor(float ticks) {
|
||||||
if (isFlying()) {
|
if (getAttributes().isFlying) {
|
||||||
return MathHelper.sin(ticks * 3) + WINGS_HALF_SPREAD_ANGLE;
|
return MathHelper.sin(ticks * 3) + WINGS_HALF_SPREAD_ANGLE;
|
||||||
}
|
}
|
||||||
return WINGS_RAISED_ANGLE;
|
return WINGS_RAISED_ANGLE;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.minelittlepony.client.model.entity.race;
|
package com.minelittlepony.client.model.entity.race;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.IPart;
|
import com.minelittlepony.api.model.SubModel;
|
||||||
import com.minelittlepony.client.model.AbstractPonyModel;
|
import com.minelittlepony.client.model.AbstractPonyModel;
|
||||||
import com.minelittlepony.client.model.part.*;
|
import com.minelittlepony.client.model.part.*;
|
||||||
import com.minelittlepony.mson.api.ModelView;
|
import com.minelittlepony.mson.api.ModelView;
|
||||||
|
@ -12,12 +12,19 @@ public class EarthPonyModel<T extends LivingEntity> extends AbstractPonyModel<T>
|
||||||
|
|
||||||
private final boolean smallArms;
|
private final boolean smallArms;
|
||||||
|
|
||||||
protected IPart tail;
|
protected SubModel tail;
|
||||||
protected PonySnout snout;
|
protected PonySnout snout;
|
||||||
protected PonyEars ears;
|
protected PonyEars ears;
|
||||||
|
|
||||||
|
private final ModelPart mane;
|
||||||
|
private final ModelPart nose;
|
||||||
|
private final ModelPart tailStub;
|
||||||
|
|
||||||
public EarthPonyModel(ModelPart tree, boolean smallArms) {
|
public EarthPonyModel(ModelPart tree, boolean smallArms) {
|
||||||
super(tree);
|
super(tree);
|
||||||
|
mane = neck.getChild("mane");
|
||||||
|
nose = head.getChild("nose");
|
||||||
|
tailStub = body.getChild("tail_stub");
|
||||||
this.smallArms = smallArms;
|
this.smallArms = smallArms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,4 +52,12 @@ public class EarthPonyModel<T extends LivingEntity> extends AbstractPonyModel<T>
|
||||||
}
|
}
|
||||||
return super.getLegOutset();
|
return super.getLegOutset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVisible(boolean visible) {
|
||||||
|
super.setVisible(visible);
|
||||||
|
mane.visible = attributes.isHorsey;
|
||||||
|
nose.visible = attributes.isHorsey;
|
||||||
|
tailStub.visible = !attributes.isHorsey;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.minelittlepony.client.model.entity.race;
|
||||||
|
|
||||||
|
import net.minecraft.client.model.ModelPart;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
|
||||||
|
import com.minelittlepony.api.model.Pivot;
|
||||||
|
|
||||||
|
public class KirinModel<T extends LivingEntity> extends UnicornModel<T> {
|
||||||
|
|
||||||
|
private final ModelPart beard;
|
||||||
|
|
||||||
|
public KirinModel(ModelPart tree, boolean smallArms) {
|
||||||
|
super(tree, smallArms);
|
||||||
|
beard = neck.getChild("beard");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void adjustBody(float pitch, Pivot pivot) {
|
||||||
|
super.adjustBody(pitch, pivot);
|
||||||
|
beard.resetTransform();
|
||||||
|
beard.pitch -= neck.pitch;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,14 @@
|
||||||
package com.minelittlepony.client.model.entity.race;
|
package com.minelittlepony.client.model.entity.race;
|
||||||
|
|
||||||
import com.minelittlepony.api.model.IPart;
|
import com.minelittlepony.api.model.SubModel;
|
||||||
import com.minelittlepony.api.model.IPegasus;
|
import com.minelittlepony.api.model.WingedPonyModel;
|
||||||
import com.minelittlepony.client.model.part.PonyWings;
|
import com.minelittlepony.client.model.part.PonyWings;
|
||||||
import com.minelittlepony.mson.api.ModelView;
|
import com.minelittlepony.mson.api.ModelView;
|
||||||
|
|
||||||
import net.minecraft.client.model.ModelPart;
|
import net.minecraft.client.model.ModelPart;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
|
||||||
public class PegasusModel<T extends LivingEntity> extends EarthPonyModel<T> implements IPegasus {
|
public class PegasusModel<T extends LivingEntity> extends EarthPonyModel<T> implements WingedPonyModel<T> {
|
||||||
|
|
||||||
private PonyWings<PegasusModel<T>> wings;
|
private PonyWings<PegasusModel<T>> wings;
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ public class PegasusModel<T extends LivingEntity> extends EarthPonyModel<T> impl
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPart getWings() {
|
public SubModel getWings() {
|
||||||
return wings;
|
return wings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue