mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-11-14 14:33:57 +01:00
The version vision
- Implement rudimentary backend version requirements - Backends ship with a hard coded backend version - Mods can specify a minimum major/minor backend version - If a backend's version is below any mod's required version it is considered disabled
This commit is contained in:
parent
3a949c717a
commit
094acf5741
@ -13,6 +13,13 @@ public interface Backend {
|
|||||||
*/
|
*/
|
||||||
Engine createEngine(LevelAccessor level);
|
Engine createEngine(LevelAccessor level);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The version of flywheel this backend was written against.
|
||||||
|
*
|
||||||
|
* @return A backend version.
|
||||||
|
*/
|
||||||
|
BackendVersion version();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The priority of this backend.
|
* The priority of this backend.
|
||||||
* <p>The backend with the highest priority upon first launch will be chosen as the default backend.
|
* <p>The backend with the highest priority upon first launch will be chosen as the default backend.
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package dev.engine_room.flywheel.api.backend;
|
||||||
|
|
||||||
|
public record BackendVersion(int major, int minor) implements Comparable<BackendVersion> {
|
||||||
|
@Override
|
||||||
|
public int compareTo(BackendVersion o) {
|
||||||
|
if (major != o.major) {
|
||||||
|
return Integer.compare(major, o.major);
|
||||||
|
}
|
||||||
|
return Integer.compare(minor, o.minor);
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ package dev.engine_room.flywheel.backend;
|
|||||||
|
|
||||||
import dev.engine_room.flywheel.api.Flywheel;
|
import dev.engine_room.flywheel.api.Flywheel;
|
||||||
import dev.engine_room.flywheel.api.backend.Backend;
|
import dev.engine_room.flywheel.api.backend.Backend;
|
||||||
|
import dev.engine_room.flywheel.api.backend.BackendVersion;
|
||||||
import dev.engine_room.flywheel.backend.compile.IndirectPrograms;
|
import dev.engine_room.flywheel.backend.compile.IndirectPrograms;
|
||||||
import dev.engine_room.flywheel.backend.compile.InstancingPrograms;
|
import dev.engine_room.flywheel.backend.compile.InstancingPrograms;
|
||||||
import dev.engine_room.flywheel.backend.engine.EngineImpl;
|
import dev.engine_room.flywheel.backend.engine.EngineImpl;
|
||||||
@ -12,11 +13,14 @@ import dev.engine_room.flywheel.lib.backend.SimpleBackend;
|
|||||||
import dev.engine_room.flywheel.lib.util.ShadersModHelper;
|
import dev.engine_room.flywheel.lib.util.ShadersModHelper;
|
||||||
|
|
||||||
public final class Backends {
|
public final class Backends {
|
||||||
|
private static final BackendVersion VERSION = new BackendVersion(1, 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use GPU instancing to render everything.
|
* Use GPU instancing to render everything.
|
||||||
*/
|
*/
|
||||||
public static final Backend INSTANCING = SimpleBackend.builder()
|
public static final Backend INSTANCING = SimpleBackend.builder()
|
||||||
.engineFactory(level -> new EngineImpl(level, new InstancedDrawManager(InstancingPrograms.get()), 256))
|
.engineFactory(level -> new EngineImpl(level, new InstancedDrawManager(InstancingPrograms.get()), 256))
|
||||||
|
.version(VERSION)
|
||||||
.priority(500)
|
.priority(500)
|
||||||
.supported(() -> GlCompat.SUPPORTS_INSTANCING && InstancingPrograms.allLoaded() && !ShadersModHelper.isShaderPackInUse())
|
.supported(() -> GlCompat.SUPPORTS_INSTANCING && InstancingPrograms.allLoaded() && !ShadersModHelper.isShaderPackInUse())
|
||||||
.register(Flywheel.rl("instancing"));
|
.register(Flywheel.rl("instancing"));
|
||||||
@ -26,6 +30,7 @@ public final class Backends {
|
|||||||
*/
|
*/
|
||||||
public static final Backend INDIRECT = SimpleBackend.builder()
|
public static final Backend INDIRECT = SimpleBackend.builder()
|
||||||
.engineFactory(level -> new EngineImpl(level, new IndirectDrawManager(IndirectPrograms.get()), 256))
|
.engineFactory(level -> new EngineImpl(level, new IndirectDrawManager(IndirectPrograms.get()), 256))
|
||||||
|
.version(VERSION)
|
||||||
.priority(1000)
|
.priority(1000)
|
||||||
.supported(() -> GlCompat.SUPPORTS_INDIRECT && IndirectPrograms.allLoaded() && !ShadersModHelper.isShaderPackInUse())
|
.supported(() -> GlCompat.SUPPORTS_INDIRECT && IndirectPrograms.allLoaded() && !ShadersModHelper.isShaderPackInUse())
|
||||||
.register(Flywheel.rl("indirect"));
|
.register(Flywheel.rl("indirect"));
|
||||||
|
@ -4,7 +4,10 @@ import java.util.Objects;
|
|||||||
import java.util.function.BooleanSupplier;
|
import java.util.function.BooleanSupplier;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import dev.engine_room.flywheel.api.backend.Backend;
|
import dev.engine_room.flywheel.api.backend.Backend;
|
||||||
|
import dev.engine_room.flywheel.api.backend.BackendVersion;
|
||||||
import dev.engine_room.flywheel.api.backend.Engine;
|
import dev.engine_room.flywheel.api.backend.Engine;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
@ -13,11 +16,13 @@ public final class SimpleBackend implements Backend {
|
|||||||
private final Function<LevelAccessor, Engine> engineFactory;
|
private final Function<LevelAccessor, Engine> engineFactory;
|
||||||
private final int priority;
|
private final int priority;
|
||||||
private final BooleanSupplier isSupported;
|
private final BooleanSupplier isSupported;
|
||||||
|
private final BackendVersion version;
|
||||||
|
|
||||||
public SimpleBackend(int priority, Function<LevelAccessor, Engine> engineFactory, BooleanSupplier isSupported) {
|
public SimpleBackend(int priority, Function<LevelAccessor, Engine> engineFactory, BooleanSupplier isSupported, BackendVersion version) {
|
||||||
this.priority = priority;
|
this.priority = priority;
|
||||||
this.engineFactory = engineFactory;
|
this.engineFactory = engineFactory;
|
||||||
this.isSupported = isSupported;
|
this.isSupported = isSupported;
|
||||||
|
this.version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder builder() {
|
||||||
@ -29,6 +34,11 @@ public final class SimpleBackend implements Backend {
|
|||||||
return engineFactory.apply(level);
|
return engineFactory.apply(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BackendVersion version() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int priority() {
|
public int priority() {
|
||||||
return priority;
|
return priority;
|
||||||
@ -40,9 +50,13 @@ public final class SimpleBackend implements Backend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static final class Builder {
|
public static final class Builder {
|
||||||
private Function<LevelAccessor, Engine> engineFactory;
|
|
||||||
private int priority = 0;
|
private int priority = 0;
|
||||||
|
@Nullable
|
||||||
|
private Function<LevelAccessor, Engine> engineFactory;
|
||||||
|
@Nullable
|
||||||
private BooleanSupplier isSupported;
|
private BooleanSupplier isSupported;
|
||||||
|
@Nullable
|
||||||
|
private BackendVersion version;
|
||||||
|
|
||||||
public Builder engineFactory(Function<LevelAccessor, Engine> engineFactory) {
|
public Builder engineFactory(Function<LevelAccessor, Engine> engineFactory) {
|
||||||
this.engineFactory = engineFactory;
|
this.engineFactory = engineFactory;
|
||||||
@ -59,11 +73,17 @@ public final class SimpleBackend implements Backend {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder version(BackendVersion version) {
|
||||||
|
this.version = version;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Backend register(ResourceLocation id) {
|
public Backend register(ResourceLocation id) {
|
||||||
Objects.requireNonNull(engineFactory);
|
Objects.requireNonNull(engineFactory);
|
||||||
Objects.requireNonNull(isSupported);
|
Objects.requireNonNull(isSupported);
|
||||||
|
Objects.requireNonNull(version);
|
||||||
|
|
||||||
return Backend.REGISTRY.registerAndGet(id, new SimpleBackend(priority, engineFactory, isSupported));
|
return Backend.REGISTRY.registerAndGet(id, new SimpleBackend(priority, engineFactory, isSupported, version));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package dev.engine_room.flywheel.impl;
|
package dev.engine_room.flywheel.impl;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import dev.engine_room.flywheel.api.Flywheel;
|
import dev.engine_room.flywheel.api.Flywheel;
|
||||||
import dev.engine_room.flywheel.api.backend.Backend;
|
import dev.engine_room.flywheel.api.backend.Backend;
|
||||||
|
import dev.engine_room.flywheel.api.backend.BackendVersion;
|
||||||
import dev.engine_room.flywheel.impl.visualization.VisualizationManagerImpl;
|
import dev.engine_room.flywheel.impl.visualization.VisualizationManagerImpl;
|
||||||
import dev.engine_room.flywheel.lib.backend.SimpleBackend;
|
import dev.engine_room.flywheel.lib.backend.SimpleBackend;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
@ -15,6 +17,7 @@ public final class BackendManagerImpl {
|
|||||||
throw new UnsupportedOperationException("Cannot create engine when backend is off.");
|
throw new UnsupportedOperationException("Cannot create engine when backend is off.");
|
||||||
})
|
})
|
||||||
.supported(() -> true)
|
.supported(() -> true)
|
||||||
|
.version(new BackendVersion(0, 0))
|
||||||
.register(Flywheel.rl("off"));
|
.register(Flywheel.rl("off"));
|
||||||
|
|
||||||
public static final Backend DEFAULT_BACKEND = findDefaultBackend();
|
public static final Backend DEFAULT_BACKEND = findDefaultBackend();
|
||||||
@ -33,7 +36,7 @@ public final class BackendManagerImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Don't store this statically because backends can theoretically change their priorities at runtime.
|
// Don't store this statically because backends can theoretically change their priorities at runtime.
|
||||||
private static ArrayList<Backend> backendsByPriority() {
|
private static List<Backend> backendsByPriority() {
|
||||||
var backends = new ArrayList<>(Backend.REGISTRY.getAll());
|
var backends = new ArrayList<>(Backend.REGISTRY.getAll());
|
||||||
|
|
||||||
// Sort with keys backwards so that the highest priority is first.
|
// Sort with keys backwards so that the highest priority is first.
|
||||||
@ -53,27 +56,46 @@ public final class BackendManagerImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void chooseBackend() {
|
private static void chooseBackend() {
|
||||||
|
var requirements = FlwImplXplat.INSTANCE.modRequirements();
|
||||||
|
|
||||||
var preferred = FlwConfig.INSTANCE.backend();
|
var preferred = FlwConfig.INSTANCE.backend();
|
||||||
if (preferred.isSupported()) {
|
if (preferred.isSupported()) {
|
||||||
|
if (meetsModRequirements(requirements, preferred)) {
|
||||||
backend = preferred;
|
backend = preferred;
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
var minVersion = requirements.minimumBackendVersion();
|
||||||
|
FlwImpl.LOGGER.warn("Preferred backend '{}' does not meet minimum version requirement {}.{}", Backend.REGISTRY.getIdOrThrow(preferred), minVersion.major(), minVersion.minor());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backend = fallback(preferred, requirements);
|
||||||
|
|
||||||
|
FlwImpl.LOGGER.warn("Flywheel backend fell back from '{}' to '{}'", Backend.REGISTRY.getIdOrThrow(preferred), Backend.REGISTRY.getIdOrThrow(backend));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Backend fallback(Backend preferred, ModRequirements requirements) {
|
||||||
var backendsByPriority = backendsByPriority();
|
var backendsByPriority = backendsByPriority();
|
||||||
|
|
||||||
var startIndex = backendsByPriority.indexOf(preferred) + 1;
|
var startIndex = backendsByPriority.indexOf(preferred) + 1;
|
||||||
|
|
||||||
// For safety in case we don't find anything
|
// For safety in case we don't find anything
|
||||||
backend = OFF_BACKEND;
|
var out = OFF_BACKEND;
|
||||||
for (int i = startIndex; i < backendsByPriority.size(); i++) {
|
for (int i = startIndex; i < backendsByPriority.size(); i++) {
|
||||||
var candidate = backendsByPriority.get(i);
|
var candidate = backendsByPriority.get(i);
|
||||||
if (candidate.isSupported()) {
|
if (candidate.isSupported()) {
|
||||||
backend = candidate;
|
if (meetsModRequirements(requirements, candidate)) {
|
||||||
|
out = candidate;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
FlwImpl.LOGGER.warn("Flywheel backend fell back from '{}' to '{}'", Backend.REGISTRY.getIdOrThrow(preferred), Backend.REGISTRY.getIdOrThrow(backend));
|
private static boolean meetsModRequirements(ModRequirements requirements, Backend candidate) {
|
||||||
|
return candidate.version()
|
||||||
|
.compareTo(requirements.minimumBackendVersion()) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getBackendString() {
|
public static String getBackendString() {
|
||||||
|
@ -17,4 +17,6 @@ public interface FlwImplXplat {
|
|||||||
boolean useSodium0_6Compat();
|
boolean useSodium0_6Compat();
|
||||||
|
|
||||||
boolean useIrisCompat();
|
boolean useIrisCompat();
|
||||||
|
|
||||||
|
ModRequirements modRequirements();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
package dev.engine_room.flywheel.impl;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import dev.engine_room.flywheel.api.backend.BackendVersion;
|
||||||
|
|
||||||
|
public record ModRequirements(BackendVersion minimumBackendVersion, List<Entry> entries) {
|
||||||
|
public record Entry(String modId, BackendVersion version) {
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,17 @@
|
|||||||
package dev.engine_room.flywheel.impl;
|
package dev.engine_room.flywheel.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import dev.engine_room.flywheel.api.backend.BackendVersion;
|
||||||
import dev.engine_room.flywheel.api.event.ReloadLevelRendererCallback;
|
import dev.engine_room.flywheel.api.event.ReloadLevelRendererCallback;
|
||||||
import dev.engine_room.flywheel.impl.compat.CompatMod;
|
import dev.engine_room.flywheel.impl.compat.CompatMod;
|
||||||
import dev.engine_room.flywheel.impl.compat.FabricSodiumCompat;
|
import dev.engine_room.flywheel.impl.compat.FabricSodiumCompat;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import net.fabricmc.loader.api.ModContainer;
|
||||||
|
import net.fabricmc.loader.api.metadata.CustomValue;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
|
||||||
public class FlwImplXplatImpl implements FlwImplXplat {
|
public class FlwImplXplatImpl implements FlwImplXplat {
|
||||||
@ -36,4 +44,54 @@ public class FlwImplXplatImpl implements FlwImplXplat {
|
|||||||
public boolean useIrisCompat() {
|
public boolean useIrisCompat() {
|
||||||
return CompatMod.IRIS.isLoaded;
|
return CompatMod.IRIS.isLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModRequirements modRequirements() {
|
||||||
|
List<ModRequirements.Entry> entries = new ArrayList<>();
|
||||||
|
|
||||||
|
for (ModContainer mod : FabricLoader.getInstance()
|
||||||
|
.getAllMods()) {
|
||||||
|
var metadata = mod.getMetadata();
|
||||||
|
|
||||||
|
var custom = metadata.getCustomValue("flywheel");
|
||||||
|
|
||||||
|
if (custom != null && custom.getType() == CustomValue.CvType.OBJECT) {
|
||||||
|
var object = custom.getAsObject();
|
||||||
|
|
||||||
|
var major = getCustomValueAsInt(object.get("backend_major_version"));
|
||||||
|
var minor = getCustomValueAsInt(object.get("backend_minor_version"));
|
||||||
|
|
||||||
|
// Major version is required
|
||||||
|
if (major != null) {
|
||||||
|
// Minor version defaults to 0
|
||||||
|
var version = new BackendVersion(major, minor == null ? 0 : minor);
|
||||||
|
|
||||||
|
entries.add(new ModRequirements.Entry(metadata.getId(), version));
|
||||||
|
} else {
|
||||||
|
FlwImpl.LOGGER.warn("Mod {} has invalid required backend version", metadata.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!entries.isEmpty()) {
|
||||||
|
var minVersion = entries.stream()
|
||||||
|
.map(ModRequirements.Entry::version)
|
||||||
|
.min(BackendVersion::compareTo)
|
||||||
|
.get();
|
||||||
|
|
||||||
|
return new ModRequirements(minVersion, entries);
|
||||||
|
} else {
|
||||||
|
return new ModRequirements(new BackendVersion(0, 0), List.of());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static Integer getCustomValueAsInt(@Nullable CustomValue major) {
|
||||||
|
if (major != null && major.getType() == CustomValue.CvType.NUMBER) {
|
||||||
|
return major.getAsNumber()
|
||||||
|
.intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,5 +35,11 @@
|
|||||||
"breaks": {
|
"breaks": {
|
||||||
"sodium": ["<0.5.0", "~0.6.0- <0.6.0-beta.2"],
|
"sodium": ["<0.5.0", "~0.6.0- <0.6.0-beta.2"],
|
||||||
"embeddium": "*"
|
"embeddium": "*"
|
||||||
|
},
|
||||||
|
"custom" : {
|
||||||
|
"flywheel" : {
|
||||||
|
"backend_major_version" : 1,
|
||||||
|
"backend_minor_version" : 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,18 @@
|
|||||||
package dev.engine_room.flywheel.impl;
|
package dev.engine_room.flywheel.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.electronwill.nightconfig.core.Config;
|
||||||
|
|
||||||
|
import dev.engine_room.flywheel.api.backend.BackendVersion;
|
||||||
import dev.engine_room.flywheel.api.event.ReloadLevelRendererEvent;
|
import dev.engine_room.flywheel.api.event.ReloadLevelRendererEvent;
|
||||||
import dev.engine_room.flywheel.impl.compat.CompatMod;
|
import dev.engine_room.flywheel.impl.compat.CompatMod;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
import net.minecraftforge.fml.ModList;
|
||||||
import net.minecraftforge.fml.loading.LoadingModList;
|
import net.minecraftforge.fml.loading.LoadingModList;
|
||||||
|
import net.minecraftforge.forgespi.language.IModInfo;
|
||||||
|
|
||||||
public class FlwImplXplatImpl implements FlwImplXplat {
|
public class FlwImplXplatImpl implements FlwImplXplat {
|
||||||
@Override
|
@Override
|
||||||
@ -36,4 +44,46 @@ public class FlwImplXplatImpl implements FlwImplXplat {
|
|||||||
public boolean useIrisCompat() {
|
public boolean useIrisCompat() {
|
||||||
return CompatMod.IRIS.isLoaded || CompatMod.OCULUS.isLoaded;
|
return CompatMod.IRIS.isLoaded || CompatMod.OCULUS.isLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModRequirements modRequirements() {
|
||||||
|
List<ModRequirements.Entry> entries = new ArrayList<>();
|
||||||
|
|
||||||
|
ModList.get()
|
||||||
|
.forEachModFile(file -> {
|
||||||
|
var info = file.getModFileInfo();
|
||||||
|
|
||||||
|
for (IModInfo mod : info.getMods()) {
|
||||||
|
var modProperties = mod.getModProperties()
|
||||||
|
.get("flywheel");
|
||||||
|
|
||||||
|
// There's no well-defined API for custom properties like in fabric.
|
||||||
|
// It just returns an object, but internally it's represented with nightconfig.
|
||||||
|
if (modProperties instanceof Config config) {
|
||||||
|
// Minor version defaults to 0, major is required
|
||||||
|
int major = config.getIntOrElse("backend_major_version", Integer.MIN_VALUE);
|
||||||
|
int minor = config.getIntOrElse("backend_minor_version", 0);
|
||||||
|
|
||||||
|
if (major != Integer.MIN_VALUE) {
|
||||||
|
entries.add(new ModRequirements.Entry(mod.getModId(), new BackendVersion(major, minor)));
|
||||||
|
} else {
|
||||||
|
FlwImpl.LOGGER.warn("Mod {} has invalid required backend version", mod.getModId());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FlwImpl.LOGGER.warn("Mod {} has invalid flywheel properties", mod.getModId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!entries.isEmpty()) {
|
||||||
|
var minVersion = entries.stream()
|
||||||
|
.map(ModRequirements.Entry::version)
|
||||||
|
.min(BackendVersion::compareTo)
|
||||||
|
.get();
|
||||||
|
|
||||||
|
return new ModRequirements(minVersion, entries);
|
||||||
|
} else {
|
||||||
|
return new ModRequirements(new BackendVersion(0, 0), List.of());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,10 @@ authors = "Jozufozu, PepperCode1"
|
|||||||
displayURL = "${mod_homepage}"
|
displayURL = "${mod_homepage}"
|
||||||
displayTest = "IGNORE_ALL_VERSION"
|
displayTest = "IGNORE_ALL_VERSION"
|
||||||
|
|
||||||
|
[modproperties.${ mod_id }.flywheel]
|
||||||
|
backend_major_version = 1
|
||||||
|
backend_minor_version = 0
|
||||||
|
|
||||||
[[dependencies.${mod_id}]]
|
[[dependencies.${mod_id}]]
|
||||||
modId = "minecraft"
|
modId = "minecraft"
|
||||||
mandatory = true
|
mandatory = true
|
||||||
|
Loading…
Reference in New Issue
Block a user