2023-06-29 13:42:36 +02:00
|
|
|
/*
|
|
|
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
|
|
*
|
|
|
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
|
|
* Copyright (c) contributors
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
* THE SOFTWARE.
|
|
|
|
*/
|
2022-05-28 21:55:41 +02:00
|
|
|
package de.bluecolored.bluemap.core.resources.resourcepack.blockmodel;
|
|
|
|
|
|
|
|
import com.google.gson.TypeAdapter;
|
|
|
|
import com.google.gson.annotations.JsonAdapter;
|
|
|
|
import com.google.gson.stream.JsonReader;
|
|
|
|
import com.google.gson.stream.JsonWriter;
|
2022-07-24 12:10:00 +02:00
|
|
|
import de.bluecolored.bluemap.api.debug.DebugDump;
|
2022-05-28 21:55:41 +02:00
|
|
|
import de.bluecolored.bluemap.core.resources.ResourcePath;
|
2022-05-29 02:34:26 +02:00
|
|
|
import de.bluecolored.bluemap.core.resources.resourcepack.ResourcePack;
|
2022-05-28 21:55:41 +02:00
|
|
|
import de.bluecolored.bluemap.core.resources.resourcepack.texture.Texture;
|
|
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
2022-05-29 02:34:26 +02:00
|
|
|
import java.util.Objects;
|
2022-05-28 21:55:41 +02:00
|
|
|
import java.util.function.Function;
|
|
|
|
|
|
|
|
@DebugDump
|
|
|
|
@JsonAdapter(TextureVariable.Adapter.class)
|
|
|
|
public class TextureVariable {
|
|
|
|
|
|
|
|
private String referenceName;
|
|
|
|
private ResourcePath<Texture> texturePath;
|
|
|
|
|
|
|
|
private transient volatile boolean isReference, isResolving;
|
|
|
|
|
2022-05-29 02:34:26 +02:00
|
|
|
private TextureVariable(TextureVariable copyFrom) {
|
|
|
|
this.referenceName = copyFrom.referenceName;
|
|
|
|
this.texturePath = copyFrom.texturePath;
|
|
|
|
this.isReference = copyFrom.isReference;
|
|
|
|
this.isResolving = copyFrom.isResolving;
|
|
|
|
}
|
|
|
|
|
2022-05-28 21:55:41 +02:00
|
|
|
public TextureVariable(String referenceName) {
|
2022-05-29 02:34:26 +02:00
|
|
|
this.referenceName = Objects.requireNonNull(referenceName);
|
2022-05-28 21:55:41 +02:00
|
|
|
this.texturePath = null;
|
|
|
|
this.isReference = true;
|
|
|
|
this.isResolving = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public TextureVariable(ResourcePath<Texture> texturePath) {
|
|
|
|
this.referenceName = null;
|
2022-05-29 02:34:26 +02:00
|
|
|
this.texturePath = Objects.requireNonNull(texturePath);
|
2022-05-28 21:55:41 +02:00
|
|
|
this.isReference = false;
|
|
|
|
this.isResolving = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Nullable
|
|
|
|
public String getReferenceName() {
|
|
|
|
return referenceName;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setReferenceName(String referenceName) {
|
|
|
|
this.referenceName = referenceName;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Nullable
|
|
|
|
public ResourcePath<Texture> getTexturePath() {
|
|
|
|
return texturePath;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Nullable
|
|
|
|
public ResourcePath<Texture> getTexturePath(Function<String, TextureVariable> supplier) {
|
|
|
|
if (this.isReference) return resolveTexturePath(supplier);
|
|
|
|
return this.texturePath;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Nullable
|
|
|
|
private ResourcePath<Texture> resolveTexturePath(Function<String, TextureVariable> supplier) {
|
|
|
|
synchronized (TextureVariable.class) {
|
|
|
|
if (this.isReference && !this.isResolving) {
|
|
|
|
this.isResolving = true; // set to avoid trying to resolve reference-loops
|
|
|
|
|
|
|
|
// resolve
|
|
|
|
TextureVariable referenced = supplier.apply(this.referenceName);
|
|
|
|
if (referenced != null) {
|
|
|
|
this.texturePath = referenced.getTexturePath(supplier);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.isReference = false;
|
2022-05-29 02:34:26 +02:00
|
|
|
this.isResolving = false;
|
2022-05-28 21:55:41 +02:00
|
|
|
}
|
|
|
|
return this.texturePath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setTexturePath(ResourcePath<Texture> texturePath) {
|
|
|
|
this.texturePath = texturePath;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isReference() {
|
|
|
|
return isReference;
|
|
|
|
}
|
|
|
|
|
2022-05-29 02:34:26 +02:00
|
|
|
public TextureVariable copy() {
|
|
|
|
synchronized (TextureVariable.class) {
|
|
|
|
return new TextureVariable(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void optimize(ResourcePack resourcePack) {
|
|
|
|
synchronized (TextureVariable.class) {
|
|
|
|
if (texturePath != null) {
|
|
|
|
texturePath = resourcePack.getTexturePath(texturePath.getFormatted());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-28 21:55:41 +02:00
|
|
|
static class Adapter extends TypeAdapter<TextureVariable> {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void write(JsonWriter out, TextureVariable value) throws IOException {
|
|
|
|
throw new UnsupportedOperationException();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public TextureVariable read(JsonReader in) throws IOException {
|
|
|
|
String value = in.nextString();
|
|
|
|
if (value.isEmpty()) throw new IOException("Can't parse an empty String into a TextureVariable");
|
Make TextureVariable references align with game behaviour (#525)
While the current implementation of reference handling in
this class was the correct way to go (only handling
texture names starting with # as references), the game is
happy to accept references without a leading hashtag, since
it just chops it off and continues on the same code path
regardless.
This commit makes the reference handling in BlueMap align
with this behaviour, potentially allowing "broken" models
to render as they do in game.
This method works for reference resolving, since if a string
passed into the texture field contains a ':' then it must be
a namespaced key, and if it contains a '/' it has to be a
resource key, because the 'minecraft' namespace is implied
in these cases. The other way around, if someone were to pass
in a string like 'oak_planks', it is safe to assume it is a
reference, since the implied resource key would be
'minecraft:oak_planks', but textures aren't at the root level
in that namespace.
2024-03-17 14:56:32 +01:00
|
|
|
|
2022-05-28 21:55:41 +02:00
|
|
|
if (value.charAt(0) == '#') {
|
|
|
|
return new TextureVariable(value.substring(1));
|
|
|
|
} else {
|
Make TextureVariable references align with game behaviour (#525)
While the current implementation of reference handling in
this class was the correct way to go (only handling
texture names starting with # as references), the game is
happy to accept references without a leading hashtag, since
it just chops it off and continues on the same code path
regardless.
This commit makes the reference handling in BlueMap align
with this behaviour, potentially allowing "broken" models
to render as they do in game.
This method works for reference resolving, since if a string
passed into the texture field contains a ':' then it must be
a namespaced key, and if it contains a '/' it has to be a
resource key, because the 'minecraft' namespace is implied
in these cases. The other way around, if someone were to pass
in a string like 'oak_planks', it is safe to assume it is a
reference, since the implied resource key would be
'minecraft:oak_planks', but textures aren't at the root level
in that namespace.
2024-03-17 14:56:32 +01:00
|
|
|
if (!(value.contains(":") || value.contains("/"))) {
|
|
|
|
return new TextureVariable(value);
|
|
|
|
}
|
|
|
|
|
2022-05-28 21:55:41 +02:00
|
|
|
return new TextureVariable(new ResourcePath<>(value));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|