WIP: initial epic fight core extraction (Phase 0)
83 files forkés d'Epic Fight (~18k LOC). Base non-compilable en l'état.
Contenu extrait :
- math/ — OpenMatrix4f, Vec3f/4f/2f, QuaternionUtils, MathUtils, ...
- armature/ — Armature, Joint, JointTransform, HumanoidArmature
- anim/ — Animator, ServerAnimator, ClientAnimator, LivingMotion, ...
- anim/types/ — StaticAnimation, DynamicAnimation, MovementAnimation, LinkAnimation,
ConcurrentLinkAnimation, LayerOffAnimation, EntityState
- anim/client/ — Layer, ClientAnimator, JointMask
- mesh/ — SkinnedMesh, SingleGroupVertexBuilder, Mesh, HumanoidMesh, ...
- cloth/ — AbstractSimulator, ClothSimulator (dépendance transitive de StaticMesh)
- asset/ — JsonAssetLoader, AssetAccessor
- patch/ — EntityPatch, LivingEntityPatch, PlayerPatch, ClientPlayerPatch
- util/ — ParseUtil, TypeFlexibleHashMap
- exception/ — AssetLoadingException
- event/ — PatchedRenderersEvent, PrepareModelEvent, RegisterResourceLayersEvent
- render/ — TiedUpRenderTypes
Headers GPLv3 + attribution injectés sur tous les .java.
Package declarations fixées sur Armature.java et TiedUpRenderTypes.java.
115 imports résiduels à résoudre manuellement :
- yesman.epicfight.main (EpicFightMod, EpicFightSharedConstants) — 30
- yesman.epicfight.gameasset (Animations, Armatures, EpicFightSounds) — 12
- yesman.epicfight.api.physics + physics.ik (combat physics) — 16
- yesman.epicfight.network.* (combat packets) — 13
- yesman.epicfight.world.* (combat entity logic) — 10
- yesman.epicfight.config.ClientConfig — 3
- yesman.epicfight.skill, .client.gui, .particle, .collider — divers combat/UI
Stratégie fix (2-3 sem manuel) : strip usage combat, stubs pour refs
core (EpicFightMod → TiedUpMod, SharedConstants → TiedUpRigConstants,
ClientConfig → TiedUpAnimationConfig).
This commit is contained in:
278
src/main/java/com/tiedup/remake/rig/armature/Joint.java
Normal file
278
src/main/java/com/tiedup/remake/rig/armature/Joint.java
Normal file
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Derived from Epic Fight (https://github.com/Epic-Fight/epicfight)
|
||||
* by the Epic Fight Team, licensed under GPLv3.
|
||||
* Modifications © 2026 TiedUp! Remake Contributors, distributed under GPLv3.
|
||||
*/
|
||||
|
||||
package com.tiedup.remake.rig.anim;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Queue;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import com.tiedup.remake.rig.armature.Armature;
|
||||
import com.tiedup.remake.rig.math.OpenMatrix4f;
|
||||
|
||||
public class Joint {
|
||||
public static final Joint EMPTY = new Joint("empty", -1, new OpenMatrix4f());
|
||||
|
||||
private final List<Joint> subJoints = Lists.newArrayList();
|
||||
private final int jointId;
|
||||
private final String jointName;
|
||||
private final OpenMatrix4f localTransform;
|
||||
private final OpenMatrix4f toOrigin = new OpenMatrix4f();
|
||||
|
||||
public Joint(String name, int jointId, OpenMatrix4f localTransform) {
|
||||
this.jointId = jointId;
|
||||
this.jointName = name;
|
||||
this.localTransform = localTransform.unmodifiable();
|
||||
}
|
||||
|
||||
public void addSubJoints(Joint... joints) {
|
||||
for (Joint joint : joints) {
|
||||
if (!this.subJoints.contains(joint)) {
|
||||
this.subJoints.add(joint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeSubJoints(Joint... joints) {
|
||||
for (Joint joint : joints) {
|
||||
this.subJoints.remove(joint);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Joint> getAllJoints() {
|
||||
List<Joint> list = Lists.newArrayList();
|
||||
this.getSubJoints(list);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public void iterSubJoints(Consumer<Joint> iterTask) {
|
||||
iterTask.accept(this);
|
||||
|
||||
for (Joint joint : this.subJoints) {
|
||||
joint.iterSubJoints(iterTask);
|
||||
}
|
||||
}
|
||||
|
||||
private void getSubJoints(List<Joint> list) {
|
||||
list.add(this);
|
||||
|
||||
for (Joint joint : this.subJoints) {
|
||||
joint.getSubJoints(list);
|
||||
}
|
||||
}
|
||||
|
||||
public void initOriginTransform(OpenMatrix4f parentTransform) {
|
||||
OpenMatrix4f modelTransform = OpenMatrix4f.mul(parentTransform, this.localTransform, null);
|
||||
OpenMatrix4f.invert(modelTransform, this.toOrigin);
|
||||
|
||||
for (Joint joint : this.subJoints) {
|
||||
joint.initOriginTransform(modelTransform);
|
||||
}
|
||||
}
|
||||
|
||||
public OpenMatrix4f getLocalTransform() {
|
||||
return this.localTransform;
|
||||
}
|
||||
|
||||
public OpenMatrix4f getToOrigin() {
|
||||
return this.toOrigin;
|
||||
}
|
||||
|
||||
public List<Joint> getSubJoints() {
|
||||
return this.subJoints;
|
||||
}
|
||||
|
||||
// Null if index out of range
|
||||
@Nullable
|
||||
public Joint getSubJoint(int index) {
|
||||
if (index < 0 || this.subJoints.size() <= index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.subJoints.get(index);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.jointName;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return this.jointId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof Joint joint) {
|
||||
return this.jointName.equals(joint.jointName) && this.jointId == joint.jointId;
|
||||
} else {
|
||||
return super.equals(o);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.jointName.hashCode() ^ this.jointId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the method that memorize path search results. {@link Armature#searchPathIndex(Joint, String)}
|
||||
*
|
||||
* @param builder
|
||||
* @param jointName
|
||||
* @return
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public HierarchicalJointAccessor.Builder searchPath(HierarchicalJointAccessor.Builder builder, String jointName) {
|
||||
if (jointName.equals(this.getName())) {
|
||||
return builder;
|
||||
} else {
|
||||
int i = 0;
|
||||
|
||||
for (Joint subJoint : this.subJoints) {
|
||||
HierarchicalJointAccessor.Builder nextBuilder = subJoint.searchPath(builder.append(i), jointName);
|
||||
i++;
|
||||
|
||||
if (nextBuilder != null) {
|
||||
return nextBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("\nid: " + this.jointId);
|
||||
sb.append("\nname: " + this.jointName);
|
||||
sb.append("\nlocal transform: " + this.localTransform);
|
||||
sb.append("\nto origin: " + this.toOrigin);
|
||||
sb.append("\nchildren: [");
|
||||
|
||||
int idx = 0;
|
||||
|
||||
for (Joint joint : this.subJoints) {
|
||||
idx++;
|
||||
sb.append(joint.jointName);
|
||||
|
||||
if (idx != this.subJoints.size()) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
sb.append("]\n");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String printIncludingChildren() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(this.toString());
|
||||
|
||||
for (Joint joint : this.subJoints) {
|
||||
sb.append(joint.printIncludingChildren());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static class HierarchicalJointAccessor {
|
||||
private Queue<Integer> indicesToTerminal;
|
||||
private final String signature;
|
||||
|
||||
private HierarchicalJointAccessor(Builder builder) {
|
||||
this.indicesToTerminal = builder.indicesToTerminal;
|
||||
this.signature = builder.signature;
|
||||
}
|
||||
|
||||
public AccessTicket createAccessTicket(Joint rootJoint) {
|
||||
return new AccessTicket(this.indicesToTerminal, rootJoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof HierarchicalJointAccessor accessor) {
|
||||
this.signature.equals(accessor.signature);
|
||||
}
|
||||
|
||||
return super.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.signature.hashCode();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder(new LinkedList<> (), "");
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private Queue<Integer> indicesToTerminal;
|
||||
private String signature;
|
||||
|
||||
private Builder(Queue<Integer> indicesToTerminal, String signature) {
|
||||
this.indicesToTerminal = indicesToTerminal;
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public Builder append(int index) {
|
||||
String signatureNext;
|
||||
|
||||
if (this.indicesToTerminal.isEmpty()) {
|
||||
signatureNext = this.signature + String.valueOf(index);
|
||||
} else {
|
||||
signatureNext = this.signature + "-" + String.valueOf(index);
|
||||
}
|
||||
|
||||
Queue<Integer> nextQueue = new LinkedList<> (this.indicesToTerminal);
|
||||
nextQueue.add(index);
|
||||
|
||||
return new Builder(nextQueue, signatureNext);
|
||||
}
|
||||
|
||||
public HierarchicalJointAccessor build() {
|
||||
return new HierarchicalJointAccessor(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class AccessTicket implements Iterator<Joint> {
|
||||
Queue<Integer> accecssStack;
|
||||
Joint joint;
|
||||
|
||||
private AccessTicket(Queue<Integer> indicesToTerminal, Joint rootJoint) {
|
||||
this.accecssStack = new LinkedList<> (indicesToTerminal);
|
||||
this.joint = rootJoint;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return !this.accecssStack.isEmpty();
|
||||
}
|
||||
|
||||
public Joint next() {
|
||||
if (this.hasNext()) {
|
||||
int nextIndex = this.accecssStack.poll();
|
||||
this.joint = this.joint.subJoints.get(nextIndex);
|
||||
} else {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
return this.joint;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user