Skip to content

Commit

Permalink
Add ExtendedResource
Browse files Browse the repository at this point in the history
  • Loading branch information
FirstMegaGame4 committed Dec 23, 2023
1 parent 2b20931 commit 7fefe83
Show file tree
Hide file tree
Showing 9 changed files with 294 additions and 11 deletions.
15 changes: 4 additions & 11 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,6 @@ repositories {
// for more information about repositories.
}

loom {
splitEnvironmentSourceSets()

mods {
"env_json" {
sourceSet sourceSets.main
}
}

}

dependencies {
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
Expand All @@ -44,6 +33,10 @@ dependencies {
// modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}"
}

loom {
accessWidenerPath = file("src/main/resources/env_json.accesswidener")
}

processResources {
inputs.property "version", project.version

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package fr.firstmegagame4.env.json.api.resource;

import fr.firstmegagame4.env.json.api.EnvJson;
import fr.firstmegagame4.env.json.impl.resource.ExtendedResourceImpl;
import net.minecraft.resource.Resource;
import net.minecraft.resource.ResourcePack;
import net.minecraft.resource.metadata.ResourceMetadata;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;

public interface ExtendedResource {

static ExtendedResource of(Resource resource) {
return ExtendedResourceImpl.of(resource);
}

ResourcePack getPack();

String getResourcePackName();

boolean isAlwaysStable();

InputStream getInputStream() throws IOException;

BufferedReader getReader() throws IOException;

ResourceMetadata getMetadata() throws IOException;

EnvJson getEnvJson() throws IOException;

Resource asResource();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package fr.firstmegagame4.env.json.impl.resource;

import fr.firstmegagame4.env.json.api.EnvJson;
import fr.firstmegagame4.env.json.api.resource.ExtendedResource;
import fr.firstmegagame4.env.json.mixin.ResourceAccessor;
import net.minecraft.resource.InputSupplier;
import net.minecraft.resource.Resource;
import net.minecraft.resource.ResourcePack;
import net.minecraft.resource.metadata.ResourceMetadata;
import org.jetbrains.annotations.ApiStatus;

import java.io.IOException;
import java.io.InputStream;

@ApiStatus.Internal
public class ExtendedResourceImpl extends Resource implements ExtendedResource {

public static ExtendedResource of(Resource resource) {
ResourceAccessor accessor = (ResourceAccessor) resource;
ResourceDuckInterface ducked = (ResourceDuckInterface) resource;
return new ExtendedResourceImpl(accessor.getPack(), accessor.getInputSupplier(), accessor.getMetadataSupplier(), ducked.env_json$getEnvJsonSupplier(), accessor.getMetadata(), ducked.env_json$getEnvJson());
}

private ExtendedResourceImpl(ResourcePack pack, InputSupplier<InputStream> inputSupplier, InputSupplier<ResourceMetadata> metadataSupplier, InputSupplier<EnvJson> envJsonSupplier, ResourceMetadata resourceMetadata, EnvJson envJson) {
super(pack, inputSupplier, metadataSupplier);
ResourceDuckInterface ducked = (ResourceDuckInterface) this;
ducked.env_json$initEnvJsonSupplier(envJsonSupplier);
ducked.env_json$initEnvJson(envJson);
}

@Override
public EnvJson getEnvJson() throws IOException {
ResourceDuckInterface ducked = (ResourceDuckInterface) this;
return ducked.env_json$getEnvJson() == null ? ducked.en_json$applyEnvJson() : ducked.env_json$getEnvJson();
}

@Override
public Resource asResource() {
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package fr.firstmegagame4.env.json.impl.resource;

import fr.firstmegagame4.env.json.api.EnvJson;
import net.minecraft.resource.InputSupplier;
import org.jetbrains.annotations.ApiStatus;

import java.io.IOException;

@ApiStatus.Internal
public interface ResourceDuckInterface {

void env_json$initEnvJsonSupplier(InputSupplier<EnvJson> envJsonSupplier);

void env_json$initEnvJson(EnvJson envJson);

EnvJson en_json$applyEnvJson() throws IOException;

InputSupplier<EnvJson> env_json$getEnvJsonSupplier();

EnvJson env_json$getEnvJson();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package fr.firstmegagame4.env.json.mixin;

import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import com.llamalad7.mixinextras.sugar.Share;
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
import fr.firstmegagame4.env.json.api.EnvJson;
import fr.firstmegagame4.env.json.impl.resource.ResourceDuckInterface;
import net.minecraft.resource.*;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

@Mixin(NamespaceResourceManager.class)
public class NamespaceResourceManagerMixin {

@Unique
private static final EnvJson ENV_JSON_NONE = null;

@Shadow
@Final
protected List<NamespaceResourceManager.FilterablePack> packList;

@Shadow
@Final
private ResourceType type;

@ModifyExpressionValue(method = "getResource", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/NamespaceResourceManager;createResource(Lnet/minecraft/resource/ResourcePack;Lnet/minecraft/util/Identifier;Lnet/minecraft/resource/InputSupplier;Lnet/minecraft/resource/InputSupplier;)Lnet/minecraft/resource/Resource;"))
private Resource onResourceCreated(Resource original, Identifier identifier, @Local(ordinal = 0) int i) {
((ResourceDuckInterface) original).env_json$initEnvJsonSupplier(this.createEnvJsonSupplier(identifier, i));
return original;
}

@WrapOperation(method = "getAllResources", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourcePack;open(Lnet/minecraft/resource/ResourceType;Lnet/minecraft/util/Identifier;)Lnet/minecraft/resource/InputSupplier;"))
private InputSupplier<InputStream> onResourceAdd(ResourcePack instance, ResourceType resourceType, Identifier identifier, Operation<InputSupplier<InputStream>> original, @Local(ordinal = 0) boolean bl, @Share("envJsonInputSupplier") LocalRef<InputSupplier<EnvJson>> ref) {
InputSupplier<InputStream> inputSupplier = original.call(instance, resourceType, identifier);
Identifier envJsonPath = this.getEnvJsonPath(identifier);
if (inputSupplier != null) {
InputSupplier<EnvJson> envJsonInputSupplier;
if (bl) {
envJsonInputSupplier = () -> null;
}
else {
envJsonInputSupplier = () -> {
InputSupplier<InputStream> supplier = instance.open(resourceType, envJsonPath);
return supplier != null ? this.loadEnvJson(supplier) : NamespaceResourceManagerMixin.ENV_JSON_NONE;
};
}
ref.set(envJsonInputSupplier);
}
return inputSupplier;
}

@WrapOperation(method = "getAllResources", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z"))
private <E> boolean onResourceCreated(List<E> instance, E e, Operation<Boolean> original, @Share("envJsonInputSupplier") LocalRef<InputSupplier<EnvJson>> ref) {
((ResourceDuckInterface) e).env_json$initEnvJsonSupplier(ref.get());
// noinspection MixinExtrasOperationParameters
return original.call(instance, e);
}

@Unique
private Identifier getEnvJsonPath(Identifier identifier) {
return identifier.withPath(identifier.getPath() + ".env.json");
}

@Unique
private InputSupplier<EnvJson> createEnvJsonSupplier(Identifier identifier, int index) {
return () -> {
Identifier envJsonPath = this.getEnvJsonPath(identifier);
// noinspection OverflowingLoopIndex
for (int i = this.packList.size() - 1; i >= index; i++) {
NamespaceResourceManager.FilterablePack filterablePack = this.packList.get(i);
ResourcePack resourcePack = filterablePack.underlying();
if (resourcePack != null) {
InputSupplier<InputStream> inputSupplier = resourcePack.open(this.type, envJsonPath);
if (inputSupplier != null) {
return this.loadEnvJson(inputSupplier);
}
}
if (filterablePack.isFiltered(envJsonPath)) {
break;
}
}
return null;
};
}

@Unique
private EnvJson loadEnvJson(InputSupplier<InputStream> supplier) throws IOException {
InputStream inputStream = supplier.get();
EnvJson envJson = EnvJson.parse(inputStream);
inputStream.close();
return envJson;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package fr.firstmegagame4.env.json.mixin;

import net.minecraft.resource.InputSupplier;
import net.minecraft.resource.Resource;
import net.minecraft.resource.ResourcePack;
import net.minecraft.resource.metadata.ResourceMetadata;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

import java.io.InputStream;

@Mixin(Resource.class)
public interface ResourceAccessor {

@Accessor
ResourcePack getPack();

@Accessor
InputSupplier<InputStream> getInputSupplier();

@Accessor
InputSupplier<ResourceMetadata> getMetadataSupplier();

@Nullable
@Accessor
ResourceMetadata getMetadata();
}
45 changes: 45 additions & 0 deletions src/main/java/fr/firstmegagame4/env/json/mixin/ResourceMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package fr.firstmegagame4.env.json.mixin;

import fr.firstmegagame4.env.json.api.EnvJson;
import fr.firstmegagame4.env.json.impl.resource.ResourceDuckInterface;
import net.minecraft.resource.InputSupplier;
import net.minecraft.resource.Resource;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;

import java.io.IOException;

@Mixin(Resource.class)
public class ResourceMixin implements ResourceDuckInterface {

@Unique
private InputSupplier<EnvJson> envJsonSupplier = null;

@Unique
private EnvJson envJson = null;

@Override
public void env_json$initEnvJsonSupplier(InputSupplier<EnvJson> envJsonSupplier) {
this.envJsonSupplier = envJsonSupplier;
}

@Override
public void env_json$initEnvJson(EnvJson envJson) {
this.envJson = envJson;
}

@Override
public EnvJson en_json$applyEnvJson() throws IOException {
return this.envJson = this.envJsonSupplier.get();
}

@Override
public InputSupplier<EnvJson> env_json$getEnvJsonSupplier() {
return this.envJsonSupplier;
}

@Override
public EnvJson env_json$getEnvJson() {
return this.envJson;
}
}
3 changes: 3 additions & 0 deletions src/main/resources/env_json.accesswidener
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
accessWidener v1 named

accessible class net/minecraft/resource/NamespaceResourceManager$FilterablePack
14 changes: 14 additions & 0 deletions src/main/resources/env_json.mixins.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"required": true,
"package": "fr.firstmegagame4.env.json.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"NamespaceResourceManagerMixin",
"ResourceAccessor",
"ResourceMixin"
],
"client": [],
"injectors": {
"defaultRequire": 1
}
}

0 comments on commit 7fefe83

Please sign in to comment.