version 0.1.3
This commit is contained in:
parent
45288f6de8
commit
d5adec5aac
44
README.md
44
README.md
|
|
@ -1 +1,43 @@
|
|||
A lib by LostInLinearPast.
|
||||
# SnowyCrescentCore
|
||||
|
||||
|
||||
### Project Introduction
|
||||
|
||||
#### 1.Capability Tool
|
||||
|
||||
- You can register a capability with very little code. And It will auto sync to client.
|
||||
- **Supports for players and other entities**
|
||||
|
||||
#### 2.Player Animator Api
|
||||
|
||||
- **The animation has compose now!!! You can dance with other player.**
|
||||
|
||||
- You can **register layers** on the server via JSON or Event.
|
||||
- You can **register animation** on the server via JSON or Event.
|
||||
- You can **register raw animation** on the client via JSON or Event.
|
||||
- You can invite other player to participate in certain animations together.
|
||||
- You can apply to join other player who is playing animation with ride.
|
||||
- You can request a player to playing an animation.
|
||||
|
||||
### How to implementation?
|
||||
|
||||
**In repositories:**
|
||||
|
||||
```java
|
||||
repositories {
|
||||
maven {
|
||||
name = "Mafuyu404 Maven"
|
||||
url = "https://maven.sighs.cc/repository/maven-public/"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**In dependencies:**
|
||||
|
||||
```java
|
||||
dependencies {
|
||||
implementation("com.linearpast:sccore:1.20.1-0.1.3")
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ mapping_version=2023.09.03-1.20.1
|
|||
mod_id=sccore
|
||||
mod_name=SnowyCrescentCore
|
||||
mod_license=GNU AGPL 3.0
|
||||
mod_version=1.20.1-0.1.2.1
|
||||
mod_version=1.20.1-0.1.3
|
||||
mod_group_id=com.linearpast
|
||||
mod_authors=LostInLinearPast
|
||||
mod_description=A lib about capability and player animator.
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ public class JsonCommand {
|
|||
ModLang.TranslatableMessage.ANIMATION_JSON_PATH.getKey(),
|
||||
path.toString()
|
||||
));
|
||||
source.sendSuccess(() -> component, true);
|
||||
} catch (Exception e) {
|
||||
source.sendFailure(Component.translatable(
|
||||
ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,162 @@
|
|||
package com.linearpast.sccore.animation.data.util;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.linearpast.sccore.SnowyCrescentCore;
|
||||
import com.linearpast.sccore.animation.data.RawAnimationData;
|
||||
import com.linearpast.sccore.animation.data.Ride;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class RawAnimJson {
|
||||
private static final String Key = "key";
|
||||
private static final String WithRide = "withRide";
|
||||
private static final String Offset = "offset";
|
||||
private static final String XRot = "xRot";
|
||||
private static final String YRot = "yRot";
|
||||
private static final String ExistTick = "existTick";
|
||||
private static final String ComponentsAnimation = "componentsAnimation";
|
||||
|
||||
public static class Reader {
|
||||
private final JsonElement originElement;
|
||||
Reader(Path jsonFile) throws Exception {
|
||||
File file = jsonFile.toFile();
|
||||
if (!file.exists()) {
|
||||
throw new FileNotFoundException("File does not exist: " + file.getAbsolutePath());
|
||||
}
|
||||
this.originElement = JsonParser.parseReader(new FileReader(file));
|
||||
}
|
||||
|
||||
Reader(JsonElement originElement) {
|
||||
this.originElement = originElement;
|
||||
}
|
||||
|
||||
public static Reader stream(Path path) throws Exception {
|
||||
return new Reader(path);
|
||||
}
|
||||
|
||||
public static Reader stream(JsonElement jsonElement) {
|
||||
return new Reader(jsonElement);
|
||||
}
|
||||
|
||||
public RawAnimationData parse() {
|
||||
return fromJson();
|
||||
}
|
||||
|
||||
public RawAnimationData fromJson() {
|
||||
try {
|
||||
JsonObject json = originElement.getAsJsonObject();
|
||||
RawAnimationData animation = RawAnimationData.create(new ResourceLocation(json.get(Key).getAsString()));
|
||||
|
||||
if(json.has(WithRide)){
|
||||
Ride ride = Ride.create();
|
||||
JsonObject withRide = json.get(WithRide).getAsJsonObject();
|
||||
JsonObject offsetJson = withRide.get(Offset).getAsJsonObject();
|
||||
if(withRide.has(ComponentsAnimation)){
|
||||
JsonArray elements = withRide.get(ComponentsAnimation).getAsJsonArray();
|
||||
for (JsonElement element : elements) {
|
||||
String componentKeyString = element.getAsString();
|
||||
ResourceLocation componentKey = new ResourceLocation(componentKeyString);
|
||||
ride.addComponentAnimation(componentKey);
|
||||
}
|
||||
}
|
||||
Vec3 offset = new Vec3(
|
||||
offsetJson.get("x").getAsDouble(),
|
||||
offsetJson.get("y").getAsDouble(),
|
||||
offsetJson.get("z").getAsDouble()
|
||||
);
|
||||
ride.withOffset(offset).withExistTick(withRide.get(ExistTick).getAsInt())
|
||||
.withXRot(withRide.get(XRot).getAsFloat())
|
||||
.withYRot(withRide.get(YRot).getAsFloat());
|
||||
animation.withRide(ride);
|
||||
}
|
||||
return animation;
|
||||
} catch (Exception e) {
|
||||
throw new JsonParseException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Writer {
|
||||
private static final String example = "example";
|
||||
private final @Nullable Path file;
|
||||
private final RawAnimationData animation;
|
||||
Writer(@Nullable Path file, RawAnimationData animation) {
|
||||
this.animation = animation;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
public static Writer stream(Path path, RawAnimationData animation) {
|
||||
return new Writer(path, animation);
|
||||
}
|
||||
|
||||
public static Writer stream(RawAnimationData animation) {
|
||||
return new Writer(null, animation);
|
||||
}
|
||||
|
||||
public static Path syntaxExample(Path directory) throws Exception {
|
||||
ResourceLocation exampleLocation = new ResourceLocation(SnowyCrescentCore.MODID, Writer.example);
|
||||
RawAnimationData example = RawAnimationData.create(exampleLocation)
|
||||
.withRide(Ride.create()
|
||||
.withOffset(new Vec3(0.0f, 1.0f, 0.0f))
|
||||
.withExistTick(200)
|
||||
.withXRot(180)
|
||||
.withYRot(0)
|
||||
.addComponentAnimation(exampleLocation)
|
||||
);
|
||||
Writer writer = stream(directory, example);
|
||||
return writer.syntax();
|
||||
}
|
||||
|
||||
public Path syntax() throws Exception {
|
||||
if(file == null) throw new NullPointerException("file is null");
|
||||
Path modIdPath = file.resolve(animation.getKey().getNamespace());
|
||||
Path resultPath = modIdPath.resolve(animation.getKey().getPath() + ".anim.json");
|
||||
if(resultPath.toFile().exists()) return resultPath;
|
||||
if(!Files.exists(modIdPath)) Files.createDirectories(modIdPath);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
try (FileWriter writer = new FileWriter(resultPath.toFile())) {
|
||||
gson.toJson(toJson(), writer);
|
||||
return resultPath;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public JsonElement toJson() {
|
||||
JsonObject json = new JsonObject();
|
||||
ResourceLocation key = animation.getKey();
|
||||
json.addProperty(Key, key.toString());
|
||||
Ride ride = animation.getRide();
|
||||
if(ride != null) {
|
||||
JsonObject jsonRide = new JsonObject();
|
||||
JsonObject jsonOffset = new JsonObject();
|
||||
Vec3 offset = ride.getOffset();
|
||||
jsonOffset.addProperty("x", offset.x);
|
||||
jsonOffset.addProperty("y", offset.y);
|
||||
jsonOffset.addProperty("z", offset.z);
|
||||
jsonRide.add(Offset, jsonOffset);
|
||||
jsonRide.addProperty(XRot, ride.getXRot());
|
||||
jsonRide.addProperty(YRot, ride.getYRot());
|
||||
jsonRide.addProperty(ExistTick, ride.getExistTick());
|
||||
|
||||
if(!ride.getComponentAnimations().isEmpty()) {
|
||||
JsonArray jsonComponents = new JsonArray();
|
||||
ride.getComponentAnimations().forEach(component ->
|
||||
jsonComponents.add(component.toString())
|
||||
);
|
||||
jsonRide.add(ComponentsAnimation, jsonComponents);
|
||||
}
|
||||
json.add(WithRide, jsonRide);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ import com.linearpast.sccore.animation.mixin.IMixinPlayerAnimationFactoryHolder;
|
|||
import com.linearpast.sccore.animation.network.toclient.AnimationClientStatusPacket;
|
||||
import com.linearpast.sccore.animation.network.toclient.AnimationJsonPacket;
|
||||
import com.linearpast.sccore.animation.service.RawAnimationService;
|
||||
import com.linearpast.sccore.animation.utils.FileUtils;
|
||||
import com.linearpast.sccore.core.ModChannel;
|
||||
import com.linearpast.sccore.utils.ModuleAccess;
|
||||
import dev.kosmx.playerAnim.api.layered.AnimationStack;
|
||||
|
|
@ -43,20 +44,12 @@ import net.minecraftforge.event.server.ServerStartedEvent;
|
|||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
public class AnimationRegistry {
|
||||
private static final Map<ResourceLocation, GenericAnimationData> animations = new HashMap<>();
|
||||
|
|
@ -92,27 +85,27 @@ public class AnimationRegistry {
|
|||
} catch (IOException e) { return; }
|
||||
}
|
||||
|
||||
safeUnzip(dataPackPath.resolve("animation.zip").toString(), animationPath.toAbsolutePath().toString());
|
||||
Set<Path> animZipPaths = getAllFile(
|
||||
FileUtils.safeUnzip(dataPackPath.resolve("animation.zip").toString(), animationPath.toAbsolutePath().toString());
|
||||
Set<Path> animZipPaths = FileUtils.getAllFile(
|
||||
dataPackPath.resolve("animation"),
|
||||
path -> path.toString().endsWith(".anim.zip")
|
||||
);
|
||||
Set<Path> layerZipPaths = getAllFile(
|
||||
Set<Path> layerZipPaths = FileUtils.getAllFile(
|
||||
dataPackPath.resolve("animation"),
|
||||
path -> path.toString().endsWith(".layer.zip")
|
||||
);
|
||||
for (Path zipPath : animZipPaths) {
|
||||
safeUnzip(zipPath.toString(), animationPath.toAbsolutePath().toString());
|
||||
FileUtils.safeUnzip(zipPath.toString(), animationPath.toAbsolutePath().toString());
|
||||
}
|
||||
for (Path zipPath : layerZipPaths) {
|
||||
safeUnzip(zipPath.toString(), animationPath.toAbsolutePath().toString());
|
||||
FileUtils.safeUnzip(zipPath.toString(), animationPath.toAbsolutePath().toString());
|
||||
}
|
||||
|
||||
Set<Path> animPaths = getAllFile(
|
||||
Set<Path> animPaths = FileUtils.getAllFile(
|
||||
dataPackPath.resolve("animation"),
|
||||
path -> path.toString().endsWith(".anim.json")
|
||||
);
|
||||
Set<Path> layerPaths = getAllFile(
|
||||
Set<Path> layerPaths = FileUtils.getAllFile(
|
||||
dataPackPath.resolve("animation"),
|
||||
path -> path.getFileName().toString().equals("animation.layer.json")
|
||||
);
|
||||
|
|
@ -180,44 +173,6 @@ public class AnimationRegistry {
|
|||
|
||||
}
|
||||
|
||||
private static Set<Path> getAllFile(Path directory, Predicate<Path> filter) {
|
||||
try (Stream<Path> walk = Files.walk(directory)) {
|
||||
return walk.filter(Files::isRegularFile)
|
||||
.filter(filter)
|
||||
.collect(Collectors.toSet());
|
||||
} catch (Exception ignored) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
||||
private static void safeUnzip(String zipFile, String destDir) {
|
||||
Path destPath = Paths.get(destDir).toAbsolutePath();
|
||||
|
||||
try (ZipFile zip = new ZipFile(zipFile)) {
|
||||
Files.createDirectories(destPath);
|
||||
Enumeration<? extends ZipEntry> entries = zip.entries();
|
||||
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = entries.nextElement();
|
||||
Path entryPath = destPath.resolve(entry.getName()).normalize();
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
Files.createDirectories(entryPath);
|
||||
} else {
|
||||
Files.createDirectories(entryPath.getParent());
|
||||
try (InputStream in = zip.getInputStream(entry);
|
||||
OutputStream out = Files.newOutputStream(entryPath, StandardOpenOption.CREATE)) {
|
||||
byte[] buffer = new byte[8192];
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static class ClientCache {
|
||||
|
|
|
|||
|
|
@ -3,14 +3,21 @@ package com.linearpast.sccore.animation.register;
|
|||
import com.linearpast.sccore.SnowyCrescentCore;
|
||||
import com.linearpast.sccore.animation.command.argument.AnimationArgument;
|
||||
import com.linearpast.sccore.animation.data.RawAnimationData;
|
||||
import com.linearpast.sccore.animation.data.util.RawAnimJson;
|
||||
import com.linearpast.sccore.animation.event.create.AnimationRegisterEvent;
|
||||
import com.linearpast.sccore.animation.utils.FileUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class RawAnimationRegistry {
|
||||
|
|
@ -41,7 +48,38 @@ public class RawAnimationRegistry {
|
|||
resetAnimations();
|
||||
AnimationRegisterEvent.RawAnimation event = new AnimationRegisterEvent.RawAnimation();
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
registerAnimations(event.getAnimations());
|
||||
Map<ResourceLocation, RawAnimationData> animationDataMap = new HashMap<>(event.getAnimations());
|
||||
Minecraft instance = Minecraft.getInstance();
|
||||
Path dataPackPath = instance.getResourcePackDirectory();
|
||||
Path animationPath = dataPackPath.resolve("animation");
|
||||
if (!Files.exists(animationPath)) {
|
||||
try {
|
||||
Files.createDirectories(animationPath);
|
||||
} catch (IOException e) { return; }
|
||||
}
|
||||
FileUtils.safeUnzip(dataPackPath.resolve("animation.zip").toString(), animationPath.toAbsolutePath().toString());
|
||||
Set<Path> animZipPaths = FileUtils.getAllFile(
|
||||
dataPackPath.resolve("animation"),
|
||||
path -> path.toString().endsWith(".anim.zip")
|
||||
);
|
||||
for (Path zipPath : animZipPaths) {
|
||||
FileUtils.safeUnzip(zipPath.toString(), animationPath.toAbsolutePath().toString());
|
||||
}
|
||||
Set<Path> animPaths = FileUtils.getAllFile(
|
||||
dataPackPath.resolve("animation"),
|
||||
path -> path.toString().endsWith(".anim.json")
|
||||
);
|
||||
|
||||
for (Path path : animPaths) {
|
||||
try {
|
||||
RawAnimJson.Reader reader = RawAnimJson.Reader.stream(path);
|
||||
RawAnimationData anim = reader.parse();
|
||||
animationDataMap.put(anim.getKey(), anim);
|
||||
} catch (Exception ignored) {
|
||||
SnowyCrescentCore.log.error("Failed to parse raw animation JSON: {}", path.toString());
|
||||
}
|
||||
}
|
||||
registerAnimations(animationDataMap);
|
||||
}
|
||||
|
||||
private static void resetAnimations() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
package com.linearpast.sccore.animation.utils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
public class FileUtils {
|
||||
public static Set<Path> getAllFile(Path directory, Predicate<Path> filter) {
|
||||
try (Stream<Path> walk = Files.walk(directory)) {
|
||||
return walk.filter(Files::isRegularFile)
|
||||
.filter(filter)
|
||||
.collect(Collectors.toSet());
|
||||
} catch (Exception ignored) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
||||
public static void safeUnzip(String zipFile, String destDir) {
|
||||
Path destPath = Paths.get(destDir).toAbsolutePath();
|
||||
|
||||
try (ZipFile zip = new ZipFile(zipFile)) {
|
||||
Files.createDirectories(destPath);
|
||||
Enumeration<? extends ZipEntry> entries = zip.entries();
|
||||
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = entries.nextElement();
|
||||
Path entryPath = destPath.resolve(entry.getName()).normalize();
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
Files.createDirectories(entryPath);
|
||||
} else {
|
||||
Files.createDirectories(entryPath.getParent());
|
||||
try (InputStream in = zip.getInputStream(entry);
|
||||
OutputStream out = Files.newOutputStream(entryPath, StandardOpenOption.CREATE)) {
|
||||
byte[] buffer = new byte[8192];
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
}
|
||||
|
|
@ -47,12 +47,12 @@ public class ModAnimation {
|
|||
*/
|
||||
public static void onAnimationRegister(AnimationRegisterEvent.Animation event) {
|
||||
//You must define corresponding Animation to invite
|
||||
GenericAnimationData amLTRL = GenericAnimationData.create(AmLyingToRightLying)
|
||||
.withLyingType(GenericAnimationData.LyingType.RIGHT)
|
||||
.withName("Lying-to-Right-Lying");
|
||||
GenericAnimationData amSTL = GenericAnimationData.create(AmStandToLying)
|
||||
.withName("Stand-to-Lying")
|
||||
.withLyingType(GenericAnimationData.LyingType.FRONT);
|
||||
// GenericAnimationData amLTRL = GenericAnimationData.create(AmLyingToRightLying)
|
||||
// .withLyingType(GenericAnimationData.LyingType.RIGHT)
|
||||
// .withName("Lying-to-Right-Lying");
|
||||
// GenericAnimationData amSTL = GenericAnimationData.create(AmStandToLying)
|
||||
// .withName("Stand-to-Lying")
|
||||
// .withLyingType(GenericAnimationData.LyingType.FRONT);
|
||||
GenericAnimationData waltzGentleman = GenericAnimationData.create(WaltzGentleman)
|
||||
.withName("Waltz-Gentleman")
|
||||
.withRide(Ride.create().addComponentAnimation(WaltzLady));
|
||||
|
|
@ -62,8 +62,8 @@ public class ModAnimation {
|
|||
.withRide(Ride.create().addComponentAnimation(WaltzGentleman));
|
||||
|
||||
//You can use it to invite an Animation
|
||||
event.registerAnimation(AmLyingToRightLying, amLTRL);
|
||||
event.registerAnimation(AmStandToLying, amSTL);
|
||||
// event.registerAnimation(AmLyingToRightLying, amLTRL);
|
||||
// event.registerAnimation(AmStandToLying, amSTL);
|
||||
event.registerAnimation(WaltzGentleman, waltzGentleman);
|
||||
event.registerAnimation(WaltzLady, waltzLady);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user