1.21.1 Update

This commit is contained in:
2025-03-08 12:58:19 +01:00
parent 7e33133848
commit 245c393ff8
30 changed files with 682 additions and 623 deletions

4
README.md Normal file
View File

@@ -0,0 +1,4 @@
# Mechanical Lemon Lib
## License
- Certain sections of the code are from the Create mod, which is licensed under the MIT license. See Create's license for more information.

View File

@@ -1,135 +1,191 @@
plugins {
id 'eclipse'
id 'idea'
id 'net.minecraftforge.gradle' version '[6.0.16,6.2)'
id 'maven-publish'
id "idea"
id "net.neoforged.moddev" version "2.0.74"
id "dev.ithundxr.silk" version "0.11.15"
id "me.modmuss50.mod-publish-plugin" version "0.8.3"
id "maven-publish"
}
apply from: "./gradle/java.gradle"
apply from: "gradle/property_loader.gradle"
group = "com.oierbravo.${mod_id}"
group = "com.${mod_author}.${mod_id}"
version = "${minecraft_version}-${mod_version}"
archivesBaseName = mod_id
java {
toolchain.languageVersion = JavaLanguageVersion.of(17)
idea {
module {
downloadJavadoc = true
downloadSources = true
}
}
minecraft {
mappings channel: mapping_channel, version: mapping_version
neoForge {
version = project.neo_version
copyIdeResources = true
accessTransformers = project.files('src/main/resources/META-INF/accesstransformer.cfg')
parchment {
minecraftVersion = project.parchment_minecraft_version
mappingsVersion = project.parchment_version
}
mods {
"$mod_id" {
sourceSet sourceSets.main
}
}
runs {
// applies to all the run configs below
configureEach {
workingDirectory project.file('run')
systemProperty 'forge.logging.markers', ''
systemProperty 'forge.logging.console.level', 'info'
jvmArguments = ["-XX:+IgnoreUnrecognizedVMOptions", "-XX:+AllowEnhancedClassRedefinition"]
//jvmArgs("-XX:-OmitStackTraceInFastThrow") // uncomment when you get exceptions with null messages etc
//jvmArgs '-XX:+UnlockCommercialFeatures' // uncomment for profiling
// Recommended logging data for a userdev environment
// The markers can be added/remove as needed separated by commas.
// "SCAN": For mods scan.
// "REGISTRIES": For firing of registry events.
// "REGISTRYDUMP": For getting the contents of all registries.
property 'forge.logging.markers', 'REGISTRIES'
systemProperty 'mixin.debug.export', 'true'
systemProperty 'mixin.debug.verbose', 'true'
programArgument '-mixin.config=create.mixins.json'
//programArgument '-mixin.config=ponder.mixins.json'
//systemProperty("mixin.env.remapRefMap", "true")
//systemProperty("mixin.env.refMapRemappingFile", "${projectDir}/build/createSrgToMcp/output.srg")
// Recommended logging level for the console
// You can set various levels here.
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
property 'forge.logging.console.level', 'debug'
mods {
"${mod_id}" {
source sourceSets.main
}
}
}
client {
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
property 'forge.enabledGameTestNamespaces', mod_id
client()
gameDirectory = project.file('run')
}
server {
property 'forge.enabledGameTestNamespaces', mod_id
args '--nogui'
}
server()
// This run config launches GameTestServer and runs all registered gametests, then exits.
// By default, the server will crash when no gametests are provided.
// The gametest system is also enabled by default for other run configs under the /test command.
gameTestServer {
property 'forge.enabledGameTestNamespaces', mod_id
gameDirectory = project.file('run/server')
}
data {
// example of overriding the workingDirectory set in configureEach above
workingDirectory project.file('run-data')
data()
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
gameDirectory = project.file('run')
systemProperty 'forge.logging.markers', 'REGISTRIES,REGISTRYDUMP'
systemProperty 'forge.logging.console.level', 'debug'
programArguments.addAll("--mod", mod_id as String, "--all", "--output", file("src/generated/resources/").getAbsolutePath(), "--existing", file("src/main/resources").getAbsolutePath())
}
gameTestServer {
type = "gameTestServer"
gameDirectory = project.file('run/gametest')
// setForceExit false <- FIXME 1.20
}
}
}
// Include resources generated by data generators.
sourceSets.main.resources { srcDir 'src/generated/resources' }
sourceSets.main {
resources {
srcDir 'src/generated/resources'
exclude '.cache/'
}
}
repositories {
maven { url = "https://maven.createmod.net" } // Create, Ponder, Flywheel
maven { url = "https://raw.githubusercontent.com/Fuzss/modresources/main/maven/" } // ForgeConfigAPIPort
maven { url = "https://mvn.devos.one/snapshots" } // Registrate
maven { url = "https://maven.blamejared.com" } // JEI, Vazkii's Mods
maven {
// location of the maven for Registrate and Flywheel
name = 'tterrag maven'
url = 'https://maven.tterrag.com'
// location of the maven for Curios API
url = "https://maven.theillusivec4.top/"
}
maven {
// location of maven for CC: Tweaked
name = "squiddev"
url = "https://squiddev.cc/maven/"
}
maven {
url = 'https://www.cursemaven.com'
content {
includeGroup "curse.maven"
}
}
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
content {
includeGroup "maven.modrinth"
}
}
maven {
url "https://jitpack.io"
content {
includeGroup "com.github.llamalad7.mixinextras"
}
}
maven {
url "https://maven.saps.dev/minecraft"
content {
includeGroup "dev.latvian.mods"
includeGroup "dev.ftb.mods"
}
}
maven {
url "https://maven.architectury.dev/"
content {
includeGroup "dev.architectury"
}
}
mavenLocal()
flatDir {
dirs 'libs'
}
}
dependencies {
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
implementation 'org.jetbrains:annotations:22.0.0'
implementation("com.simibubi.create:create-${minecraft_version}:${create_version}:slim") { transitive = false }
implementation("net.createmod.ponder:Ponder-NeoForge-${minecraft_version}:${ponder_version}")
compileOnly("dev.engine-room.flywheel:flywheel-neoforge-api-${minecraft_version}:${flywheel_version}")
runtimeOnly("dev.engine-room.flywheel:flywheel-neoforge-${minecraft_version}:${flywheel_version}")
implementation("com.tterrag.registrate:Registrate:${registrate_version}")
compileOnly("top.theillusivec4.curios:curios-neoforge:${curios_version}+${curios_minecraft_version}:api")
runtimeOnly("top.theillusivec4.curios:curios-neoforge:${curios_version}+${curios_minecraft_version}")
implementation("curse.maven:jade-324717:${jade_id}")
//runtimeOnly("dev.architectury:architectury-neoforge:13.0.8")
//implementation("dev.ftb.mods:ftb-chunks-neoforge:2101.1.1")
//implementation("dev.ftb.mods:ftb-teams-neoforge:2101.1.0")
//implementation("dev.ftb.mods:ftb-library-neoforge:2101.1.3")
implementation fg.deobf("curse.maven:jade-324717:${jade_id}")
implementation fg.deobf("com.simibubi.create:create-${create_minecraft_version}:${create_version}:slim") { transitive = false }
implementation fg.deobf("com.jozufozu.flywheel:flywheel-forge-${flywheel_minecraft_version}:${flywheel_version}")
implementation fg.deobf("com.tterrag.registrate:Registrate:${registrate_version}")
}
tasks.named('processResources', ProcessResources).configure {
var replaceProperties = [minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range,
forge_version : forge_version, forge_version_range: forge_version_range,
loader_version_range: loader_version_range,
mod_id : mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: mod_version,
mod_authors : mod_authors, mod_description: mod_description,]
processResources {
def buildProps = project.properties.clone()
inputs.properties replaceProperties
// Replaces FML's magic file.jarVersion string with the correct version at build time.
buildProps.put('file', [jarVersion: project.version])
filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) {
expand replaceProperties + [project: project]
filesMatching(['META-INF/neoforge.mods.toml', 'pack.mcmeta']) {
expand buildProps
}
}
tasks.named('jar', Jar).configure {
manifest {
attributes(["Specification-Title" : mod_id,
"Specification-Vendor" : mod_authors,
"Specification-Version" : "1", // We are version 1 of ourselves
"Implementation-Title" : project.name,
"Implementation-Version" : project.jar.archiveVersion,
"Implementation-Vendor" : mod_authors,
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")])
compileJava {
options.compilerArgs = ['-Xdiags:verbose']
}
finalizedBy 'reobfJar'
jar {
from('LICENSE') {
rename { "${it}_${archivesBaseName}" }
}
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
}
publishing {
// other settings of publication
publications {

View File

@@ -1,27 +1,33 @@
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false
minecraft_version=1.20.1
minecraft_version_range=[1.20.1,1.21)
forge_version=47.3.7
forge_version_range=[47,)
loader_version_range=[47,)
mapping_channel=official
mapping_version=1.20.1
minecraft_version = 1.21.1
minecraft_version_range=[1.21.1]
neo_version = 21.1.125
neo_version_range=[21.1.125,)
parchment_minecraft_version = 1.21.1
parchment_version = 2024.11.17
# Dependency Versions
mod_id=mechanical_lemon_lib
mod_name=MechanicalLemonLib
mod_license=MIT
mod_version=0.0.23
mod_license=LGPL3
mod_version=0.1.3
mod_group_id=com.oierbravo
mod_authors=oierbravo
mod_description=Library
mod_author=oierbravo
mod_description=Mod Utility Library
# dependency versions
create_minecraft_version = 1.20.1
flywheel_minecraft_version = 1.20.1
create_version = 0.5.1.h-48
flywheel_version = 0.6.11-13
registrate_version = MC1.20-1.3.3
create_version = 6.0.2-32
ponder_version = 1.0.44
flywheel_version = 1.0.1-11
registrate_version = MC1.21-1.3.0+62
jei_minecraft_version = 1.21.1
jei_version = 19.21.0.247
curios_minecraft_version = 1.21.1
curios_version = 9.2.2
sodium_version = 0.6.9
jade_id = 4654448
jade_id = 6198776

39
gradle/java.gradle Normal file
View File

@@ -0,0 +1,39 @@
apply plugin: 'java'
java.toolchain.languageVersion = JavaLanguageVersion.of(21)
java.withSourcesJar()
java.withJavadocJar()
jar {
manifest {
attributes([
'Specification-Title' : mod_name,
'Specification-Vendor' : mod_author,
'Specification-Version' : project.jar.archiveVersion,
'Implementation-Title' : project.name,
'Implementation-Version' : project.jar.archiveVersion,
'Implementation-Vendor' : mod_author,
'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
'Timestampe' : System.currentTimeMillis(),
'Built-On-Java' : "${System.getProperty('java.vm.version')} (${System.getProperty('java.vm.vendor')})",
'Built-On-Minecraft' : minecraft_version
])
}
}
tasks.withType(JavaCompile).configureEach {
it.options.encoding = 'UTF-8'
it.options.release = 21
}
// Disables Gradle's custom module metadata from being published to maven. The
// metadata includes mapped dependencies which are not reasonably consumable by
// other mod developers.
tasks.withType(GenerateModuleMetadata) {
enabled = false
}
javadoc {
// Suppress annoying warnings when generating JavaDoc files.
options.addStringOption('Xdoclint:none', '-quiet')
}

View File

@@ -0,0 +1,48 @@
/*
This module can inject build properties from a JSON file. Each property in the
JSON file will be mapped to a build property using the key of that property.
Property keys ending with _comment will be skipped.
If a secretFile property exists and points to a valid JSON file that file will
be automatically loaded. You can manually load a file using the loadProperties
method.
*/
import groovy.json.JsonSlurper
// Auto detects a secret file and injects it.
if (project.rootProject.hasProperty("secretFile")) {
project.logger.lifecycle("Automatically loading properties from the secretFile")
final def secretsFile = project.rootProject.file(project.rootProject.getProperty("secretFile"))
if (secretsFile.exists() && secretsFile.name.endsWith(".json")) {
loadProperties(secretsFile)
}
}
// Loads properties using a specified json file.
def loadProperties(propertyFile) {
if (propertyFile.exists()) {
propertyFile.withReader {
Map propMap = new JsonSlurper().parse it
for (entry in propMap) {
// Filter entries that use _comment in the key.
if (!entry.key.endsWith("_comment")) {
project.ext.set(entry.key, entry.value)
}
}
project.logger.lifecycle("Successfully loaded " + propMap.size() + " properties")
propMap.clear()
}
} else {
project.logger.warn("The property file " + propertyFile.getName() + " could not be loaded. It does not exist.")
}
}
// Allows other scripts to use these methods.
ext {
loadProperties = this.&loadProperties
}

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -2,32 +2,9 @@ package com.oierbravo.mechanical_lemon_lib;
import com.mojang.logging.LogUtils;
import com.oierbravo.mechanical_lemon_lib.register.LemonCreativeModeTabs;
import net.minecraft.client.Minecraft;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.food.FoodProperties;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.CreativeModeTabs;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.material.MapColor;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.BuildCreativeModeTabContentsEvent;
import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.common.Mod;
import org.slf4j.Logger;
@Mod(MechanicalLemonLib.MODID)
@@ -36,12 +13,11 @@ public class MechanicalLemonLib {
public static final String MODID = "mechanical_lemon_lib";
private static final Logger LOGGER = LogUtils.getLogger();
public MechanicalLemonLib() {
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
public MechanicalLemonLib(IEventBus modEventBus, ModContainer modContainer) {
MinecraftForge.EVENT_BUS.register(this);
LemonCreativeModeTabs.register(modEventBus);
}
}

View File

@@ -3,6 +3,7 @@ package com.oierbravo.mechanical_lemon_lib.foundation.blockEntity.behaviour;
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Mth;
import net.minecraft.world.level.Level;
@@ -37,19 +38,19 @@ public class CycleBehavior extends BlockEntityBehaviour {
}
@Override
public void read(CompoundTag compound, boolean clientPacket) {
public void read(CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket) {
running = compound.getBoolean("Running");
finished = compound.getBoolean("Finished");
prevRunningTicks = runningTicks = compound.getInt("Ticks");
super.read(compound, clientPacket);
super.read(compound,registries, clientPacket);
}
@Override
public void write(CompoundTag compound, boolean clientPacket) {
public void write(CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket) {
compound.putBoolean("Running", running);
compound.putBoolean("Finished", finished);
compound.putInt("Ticks", runningTicks);
super.write(compound, clientPacket);
super.write(compound, registries, clientPacket);
}
public void start() {

View File

@@ -3,6 +3,7 @@ package com.oierbravo.mechanical_lemon_lib.foundation.blockEntity.behaviour;
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Mth;
import net.minecraft.world.level.Level;
@@ -25,6 +26,7 @@ public class DynamicCycleBehavior extends BlockEntityBehaviour {
int getProcessingTime();
boolean tryProcess(boolean simulate);
void playSound();
void setWorking(boolean value);
}
public <T extends SmartBlockEntity & DynamicCycleBehaviorSpecifics> DynamicCycleBehavior(T te) {
@@ -35,33 +37,36 @@ public class DynamicCycleBehavior extends BlockEntityBehaviour {
}
@Override
public void read(CompoundTag compound, boolean clientPacket) {
public void read(CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket) {
currentTime = compound.getInt("CurrentTime");
processingTime = compound.getInt("ProcessingTime");
running = compound.getBoolean("Running");
finished = compound.getBoolean("Finished");
super.read(compound, clientPacket);
super.read(compound, registries, clientPacket);
}
@Override
public void write(CompoundTag compound, boolean clientPacket) {
public void write(CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket) {
compound.putInt("CurrentTime", currentTime);
compound.putInt("ProcessingTime", processingTime);
compound.putBoolean("Running", running);
compound.putBoolean("Finished", finished);
super.write(compound, clientPacket);
super.write(compound, registries, clientPacket);
}
public void start() {
running = true;
currentTime = 0;
processingTime = specifics.getProcessingTime();
specifics.setWorking(true);
blockEntity.sendData();
}
public void stop(){
running = false;
currentTime = 0;
processingTime = 0;
specifics.setWorking(false);
blockEntity.sendData();
}
@Override
@@ -85,7 +90,15 @@ public class DynamicCycleBehavior extends BlockEntityBehaviour {
}
return;
}
if(running)
if(!specifics.tryProcess(true)){
running = false;
blockEntity.sendData();
return;
}
specifics.setWorking(true);
running = true;
currentTime += getRunningTickSpeed();
if (currentTime >= getProccessingTime() && specifics.getKineticSpeed() != 0) {
@@ -94,17 +107,18 @@ public class DynamicCycleBehavior extends BlockEntityBehaviour {
stop();
apply();
specifics.onCycleCompleted();
}
}
blockEntity.sendData();
}
}
}
public float getProgress(float partialTicks){
int runningTicks = Math.abs(this.runningTicks);
float ticks = Mth.lerp(partialTicks, prevRunningTicks, runningTicks);
return ticks/ getProccessingTime() * 100;
}
protected int getProccessingTime(){
public int getProccessingTime(){
return processingTime;
}
@@ -129,4 +143,14 @@ public class DynamicCycleBehavior extends BlockEntityBehaviour {
return 0;
return Mth.clamp(currentTime * 100 / (getProccessingTime()), 0,100);
}
public int getCurrentTime(){
return currentTime;
}
public boolean isRunning(){
return running;
}
public boolean isFinished(){
return finished;
}
}

View File

@@ -8,6 +8,7 @@ import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import net.minecraft.ChatFormatting;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
@@ -100,11 +101,8 @@ public class RecipeRequirementsBehaviour<R extends IRecipeWithRequirements> exte
return added;
}
@Override
public void write(CompoundTag compound, boolean clientPacket) {
public void write(CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket) {
ListTag missingRequirementsTag = new ListTag();
for(String missingId : missingRequirements){
CompoundTag tag = new CompoundTag();
@@ -112,19 +110,18 @@ public class RecipeRequirementsBehaviour<R extends IRecipeWithRequirements> exte
missingRequirementsTag.add(tag);
}
compound.put("MissingRequirements", missingRequirementsTag);
super.write(compound, clientPacket);
super.write(compound, registries, clientPacket);
}
@Override
public void read(CompoundTag compound, boolean clientPacket){
public void read(CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket) {
missingRequirements = new ArrayList<>();
ListTag missingRequirementsTag = compound.getList("MissingRequirements", Tag.TAG_COMPOUND);
for( Tag tag : missingRequirementsTag ){
CompoundTag requirementsTag = (CompoundTag) tag;
missingRequirements.add(requirementsTag.getString("t"));
}
super.read(compound, clientPacket);
super.read(compound, registries, clientPacket);
}
public interface RecipeRequirementsSpecifics<R extends IRecipeWithRequirements> {

View File

@@ -1,65 +1,41 @@
package com.oierbravo.mechanical_lemon_lib.foundation.data;
import com.google.gson.JsonObject;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.tterrag.registrate.util.entry.FluidEntry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.GsonHelper;
import net.minecraftforge.common.crafting.conditions.ICondition;
import net.minecraftforge.common.crafting.conditions.IConditionSerializer;
import net.minecraftforge.fluids.ForgeFlowingFluid;
import net.minecraftforge.registries.ForgeRegistries;
import net.neoforged.neoforge.common.conditions.ICondition;
import net.neoforged.neoforge.common.conditions.ModLoadedCondition;
import net.neoforged.neoforge.fluids.BaseFlowingFluid;
public class FluidExistsCondition implements ICondition {
private static final ResourceLocation NAME = new ResourceLocation("create_mechanical_chicken", "fluid_exists");
private final ResourceLocation fluid;
public record FluidExistsCondition(String fluid) implements ICondition {
public static MapCodec<FluidExistsCondition> CODEC = RecordCodecBuilder.mapCodec((builder) -> builder.group(Codec.STRING.fieldOf("fluid_exists").forGetter(FluidExistsCondition::fluid)).apply(builder, FluidExistsCondition::new));
public FluidExistsCondition(String location) {
this(new ResourceLocation(location));
public FluidExistsCondition(String fluid) {
this.fluid = fluid;
}
public FluidExistsCondition(String namespace, String path) {
this(new ResourceLocation(namespace, path));
}
public FluidExistsCondition(ResourceLocation pFluid) {
this.fluid = pFluid;
}
public FluidExistsCondition(FluidEntry<ForgeFlowingFluid.Flowing> fluid) {
this(fluid.getId());
}
@Override
public ResourceLocation getID() {
return NAME;
}
public String toString() {
return "fluid_exists(\"" + this.fluid + "\")";
}
public boolean test(IContext context) {
if(fluid.getNamespace().startsWith("#"))
ResourceLocation fluidLocation = ResourceLocation.tryParse(fluid);
if(fluidLocation == null)
return false;
if(fluidLocation.getNamespace().startsWith("#"))
return true; //Tags always true;
return ForgeRegistries.FLUIDS.containsKey(this.fluid);
}
public static class Serializer implements IConditionSerializer<FluidExistsCondition> {
public static final Serializer INSTANCE = new Serializer();
public Serializer() {
return BuiltInRegistries.FLUID.containsKey(fluidLocation);
}
public void write(JsonObject json, FluidExistsCondition value) {
json.addProperty("fluid", value.fluid.toString());
@Override
public MapCodec<? extends ICondition> codec() {
return CODEC;
}
public FluidExistsCondition read(JsonObject json) {
return new FluidExistsCondition(new ResourceLocation(GsonHelper.getAsString(json, "fluid")));
}
public ResourceLocation getID() {
return FluidExistsCondition.NAME;
}
}
}

View File

@@ -0,0 +1,37 @@
package com.oierbravo.mechanical_lemon_lib.foundation.energy;
import net.neoforged.neoforge.energy.EnergyStorage;
public abstract class AbstractEnergyStorage extends EnergyStorage {
public AbstractEnergyStorage(int capacity, int maxTransfer) {
super(capacity, maxTransfer);
}
@Override
public int extractEnergy(int maxExtract, boolean simulate) {
int extractedEnergy = super.extractEnergy(maxExtract, simulate);
if(extractedEnergy != 0) {
onEnergyChanged();
}
return extractedEnergy;
}
@Override
public int receiveEnergy(int maxReceive, boolean simulate) {
int receiveEnergy = super.receiveEnergy(maxReceive, simulate);
if(receiveEnergy != 0) {
onEnergyChanged();
}
return receiveEnergy;
}
public int setEnergy(int energy) {
this.energy = energy;
return energy;
}
public abstract void onEnergyChanged();
}

View File

@@ -1,13 +1,9 @@
package com.oierbravo.mechanical_lemon_lib.foundation.recipe;
import com.google.gson.JsonObject;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.Container;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.item.crafting.RecipeInput;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.HashMap;
@@ -16,7 +12,7 @@ import java.util.Map;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public abstract class BaseRecipe<T extends Container, P extends BaseRecipeParams> implements Recipe<T>, IRecipeWithRequirements {
public abstract class BaseRecipe<T extends RecipeInput, P extends BaseRecipeParams> implements Recipe<T>, IRecipeWithRequirements {
protected ResourceLocation id;
@@ -42,9 +38,4 @@ public abstract class BaseRecipe<T extends Container, P extends BaseRecipeParams
return true;
}
@Override
public ResourceLocation getId() {
return id;
}
}

View File

@@ -2,16 +2,21 @@ package com.oierbravo.mechanical_lemon_lib.foundation.recipe;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.minecraft.data.recipes.FinishedRecipe;
import net.minecraft.advancements.Criterion;
import net.minecraft.data.recipes.RecipeBuilder;
import net.minecraft.data.recipes.RecipeOutput;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.crafting.conditions.ICondition;
import net.minecraftforge.common.crafting.conditions.ModLoadedCondition;
import net.minecraftforge.common.crafting.conditions.NotCondition;
import net.neoforged.neoforge.common.conditions.ICondition;
import net.neoforged.neoforge.common.conditions.ModLoadedCondition;
import net.neoforged.neoforge.common.conditions.NotCondition;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
public abstract class BaseRecipeBuilder<R extends BaseRecipe<?,P>, P extends BaseRecipeParams> {
@@ -27,7 +32,7 @@ public abstract class BaseRecipeBuilder<R extends BaseRecipe<?,P>, P extends Bas
public abstract R build();
public void build(Consumer<FinishedRecipe> consumer) {
public void build(Consumer<RecipeBuilder> consumer) {
consumer.accept(new DataGenResult<>(build(), recipeConditions));
}
@@ -53,28 +58,53 @@ public abstract class BaseRecipeBuilder<R extends BaseRecipe<?,P>, P extends Bas
return this;
}
public static class DataGenResult<S extends BaseRecipe<?,?>> implements FinishedRecipe {
public static class DataGenResult<S extends BaseRecipe<?,?>> implements RecipeBuilder {
private List<ICondition> recipeConditions;
private BaseRecipeSerializer<S,?> serializer;
private ResourceLocation id;
protected final Map<String, Criterion<?>> criteria = new LinkedHashMap<>();
@Nullable
protected String group;
private S recipe;
@SuppressWarnings("unchecked")
public DataGenResult(S recipe, List<ICondition> recipeConditions) {
this.recipe = recipe;
this.recipeConditions = recipeConditions;
ResourceLocation typeId = recipe.getId();
ResourceLocation typeId = recipe.id;
if (!(recipe.getSerializer() instanceof BaseRecipeSerializer))
throw new IllegalStateException("Cannot datagen Recipe of type: " + typeId);
this.id = new ResourceLocation(recipe.getId().getNamespace(),
typeId.getPath() + "/" + recipe.getId().getPath());
this.id = ResourceLocation.fromNamespaceAndPath(recipe.id.getNamespace(),
typeId.getPath() + "/" + recipe.id.getPath());
this.serializer = (BaseRecipeSerializer<S, ?>) recipe.getSerializer();
}
@Override
public RecipeBuilder unlockedBy(String name, Criterion<?> criterion) {
this.criteria.put(name, criterion);
return this;
}
@Override
public RecipeBuilder group(@Nullable String s) {
this.group = group;
return this; }
@Override
public Item getResult() {
return null;
}
@Override
public void save(RecipeOutput recipeOutput, ResourceLocation resourceLocation) {
}
/*@Override
public void serializeRecipeData(JsonObject json) {
serializer.write(json, recipe);
if (recipeConditions.isEmpty())
@@ -103,7 +133,7 @@ public abstract class BaseRecipeBuilder<R extends BaseRecipe<?,P>, P extends Bas
@Override
public ResourceLocation getAdvancementId() {
return null;
}
}*/
}
}

View File

@@ -29,7 +29,7 @@ public abstract class BaseRecipeSerializer<R extends BaseRecipe<?,?>, B extends
}
@Override
/*@Override
public @NotNull R fromJson(@NotNull ResourceLocation pRecipeId, @NotNull JsonObject pSerializedRecipe) {
return readFromJson(pRecipeId, pSerializedRecipe)
.withRequirements(RecipeRequirementsUtils.fromJson(pSerializedRecipe, enabledRecipeRequirements))
@@ -45,5 +45,5 @@ public abstract class BaseRecipeSerializer<R extends BaseRecipe<?,?>, B extends
@Override
public void toNetwork(@NotNull FriendlyByteBuf pBuffer, @NotNull R pRecipe) {
writeToBuffer(pBuffer, pRecipe);
}
}*/
}

View File

@@ -1,7 +1,6 @@
package com.oierbravo.mechanical_lemon_lib.foundation.recipe;
import com.google.gson.JsonObject;
import com.oierbravo.mechanical_lemon_lib.utility.Components;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.level.block.entity.BlockEntity;

View File

@@ -4,9 +4,7 @@ import com.google.gson.JsonObject;
import com.mojang.serialization.JsonOps;
import com.oierbravo.mechanical_lemon_lib.foundation.recipe.RecipeRequirement;
import com.oierbravo.mechanical_lemon_lib.foundation.recipe.RecipeRequirementType;
import net.minecraft.client.Minecraft;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceKey;
@@ -17,7 +15,6 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.entity.BlockEntity;
import java.util.Objects;
import java.util.Optional;
import static java.lang.constant.ConstantDescs.NULL;
@@ -36,11 +33,11 @@ public class BiomeRequirement extends RecipeRequirement {
}
public BiomeRequirement(TagKey<Biome> tag) {
this(null,tag);
biomeTagKey = tag;
}
public BiomeRequirement(ResourceKey<Biome> key) {
this(key,null);
biomeResourceKey = key;
}
public BiomeRequirement(ResourceKey<Biome> key, TagKey<Biome> tag) {
@@ -62,27 +59,22 @@ public class BiomeRequirement extends RecipeRequirement {
return true;
Holder<Biome> blockEntityBiome = pLevel.getBiome(pBlockEntity.getBlockPos());
/*if(pLevel.isClientSide()){
if(pLevel.isClientSide()){
return false;
}*/
RegistryAccess registryAccess;
if(pLevel.isClientSide())
registryAccess = Objects.requireNonNull(Minecraft.getInstance().getConnection()).registryAccess();
registryAccess = pLevel.registryAccess();
}
Optional<Holder.Reference<Biome>> requiredBiomeHolder = Objects.requireNonNull(registryAccess.registryOrThrow(Registries.BIOME).asLookup().get(biomeResourceKey));
Optional<Holder.Reference<Biome>> requiredBiomeHolder = pLevel.getServer().registryAccess().registryOrThrow(Registries.BIOME).asLookup().get(biomeResourceKey);
if(requiredBiomeHolder.isPresent()
&& blockEntityBiome.is(requiredBiomeHolder.get().key()))
return true;
return registryAccess.registryOrThrow(Registries.BIOME).getTag(biomeTagKey).map(t ->
return pLevel.getServer().registryAccess().registryOrThrow(Registries.BIOME).getTag(biomeTagKey).map(t ->
t.contains(blockEntityBiome)
).orElse(false);
}
public boolean isPresent(){
if(biomeTagKey == null && biomeResourceKey == null)
return false;

View File

@@ -0,0 +1,158 @@
package com.oierbravo.mechanical_lemon_lib.foundation.recipe.requirements;
import com.google.gson.JsonObject;
import com.mojang.serialization.JsonOps;
import com.oierbravo.mechanical_lemon_lib.foundation.recipe.RecipeRequirement;
import com.oierbravo.mechanical_lemon_lib.foundation.recipe.RecipeRequirementType;
import net.minecraft.client.Minecraft;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.entity.BlockEntity;
import java.util.Objects;
import java.util.Optional;
import static java.lang.constant.ConstantDescs.NULL;
public class BiomeRequirement extends RecipeRequirement {
public static final RecipeRequirementType<BiomeRequirement> TYPE = new BiomeRequirementType();
public static final BiomeRequirement EMPTY = new BiomeRequirement();
protected TagKey<Biome> biomeTagKey;
protected ResourceKey<Biome> biomeResourceKey;
public BiomeRequirement() {
}
public BiomeRequirement(TagKey<Biome> tag) {
this(null,tag);
}
public BiomeRequirement(ResourceKey<Biome> key) {
this(key,null);
}
public BiomeRequirement(ResourceKey<Biome> key, TagKey<Biome> tag) {
this.biomeResourceKey = key;
this.biomeTagKey = tag;
}
public static BiomeRequirement of(ResourceKey<Biome> key) {
return new BiomeRequirement(key);
}
public static BiomeRequirement of(TagKey<Biome> tag) {
return new BiomeRequirement(tag);
}
public static BiomeRequirement of(ResourceKey<Biome> key, TagKey<Biome> tag) {
return new BiomeRequirement(key, tag);
}
public boolean test(Level pLevel, BlockEntity pBlockEntity) {
if(biomeResourceKey == null && biomeTagKey == null)
return true;
Holder<Biome> blockEntityBiome = pLevel.getBiome(pBlockEntity.getBlockPos());
/*if(pLevel.isClientSide()){
return false;
}*/
RegistryAccess registryAccess;
if(pLevel.isClientSide())
registryAccess = Objects.requireNonNull(Minecraft.getInstance().getConnection()).registryAccess();
registryAccess = pLevel.registryAccess();
Optional<Holder.Reference<Biome>> requiredBiomeHolder = Objects.requireNonNull(registryAccess.registryOrThrow(Registries.BIOME).asLookup().get(biomeResourceKey));
if(requiredBiomeHolder.isPresent()
&& blockEntityBiome.is(requiredBiomeHolder.get().key()))
return true;
return registryAccess.registryOrThrow(Registries.BIOME).getTag(biomeTagKey).map(t ->
t.contains(blockEntityBiome)
).orElse(false);
}
public boolean isPresent(){
if(biomeTagKey == null && biomeResourceKey == null)
return false;
return true;
}
public String toString(){
if(biomeTagKey == null && biomeResourceKey == null)
return null;
if(biomeResourceKey != null)
return biomeResourceKey.location().toString();
return biomeTagKey.location().toString();
}
@Override
public RecipeRequirementType<?> getType() {
return TYPE;
}
private static class BiomeRequirementType extends RecipeRequirementType<BiomeRequirement> {
public BiomeRequirementType() {
super("biome");
}
public BiomeRequirementType(String id) {
super(id);
}
@Override
public BiomeRequirement fromJson(JsonObject pJson) {
if (GsonHelper.isValidNode(pJson, "biome")) {
ResourceKey<Biome> biomeResourceKey = ResourceKey.codec(Registries.BIOME).parse(JsonOps.INSTANCE, pJson.get("biome")).result().get();
TagKey<Biome> biomeTag = TagKey.codec(Registries.BIOME).parse(JsonOps.INSTANCE, pJson.get("biome")).result().get();
return BiomeRequirement.of(biomeResourceKey,biomeTag);
}
return BiomeRequirement.EMPTY;
}
@Override
public JsonObject toJson(JsonObject pJson, RecipeRequirement pRecipeRequirement){
if(!pRecipeRequirement.isPresent())
return pJson;
pJson.addProperty("biome", pRecipeRequirement.toString());
return pJson;
}
@Override
public BiomeRequirement fromNetwork(FriendlyByteBuf buffer) {
boolean hasRequirement = buffer.readBoolean();
if(hasRequirement) {
ResourceLocation rl = buffer.readResourceLocation();
if (NULL.equals(rl)) return BiomeRequirement.EMPTY;
else return BiomeRequirement.of(TagKey.create(Registries.BIOME, rl));
}
return BiomeRequirement.EMPTY;
}
@Override
public void toNetwork(FriendlyByteBuf buffer, RecipeRequirement pRecipeRequirement) {
if(pRecipeRequirement == null)
pRecipeRequirement = new BiomeRequirement();
if(pRecipeRequirement instanceof BiomeRequirement){
buffer.writeBoolean(pRecipeRequirement.isPresent());
if(pRecipeRequirement.isPresent()) {
TagKey<Biome> biome = ((BiomeRequirement) pRecipeRequirement).biomeTagKey;
buffer.writeResourceLocation(biome.location());
}
}
}
}
}

View File

@@ -0,0 +1,17 @@
package com.oierbravo.mechanical_lemon_lib.foundation.visual;
import com.simibubi.create.AllPartialModels;
import com.simibubi.create.content.kinetics.base.KineticBlockEntity;
import com.simibubi.create.content.kinetics.base.SingleAxisRotatingVisual;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.lib.model.Models;
import net.minecraft.core.Direction;
public class HalfShaftVisual<T extends KineticBlockEntity> extends SingleAxisRotatingVisual<T> {
public HalfShaftVisual(VisualizationContext context, T blockEntity, float partialTick, Direction direction) {
super(context, blockEntity, partialTick, direction, Models.partial(AllPartialModels.SHAFT_HALF));
}
public static <T extends KineticBlockEntity> HalfShaftVisual<T> bottomHalfShaft(VisualizationContext context, T blockEntity, float partialTick) {
return new HalfShaftVisual<>(context, blockEntity, partialTick, Direction.NORTH);
}
}

View File

@@ -1,5 +1,6 @@
package com.oierbravo.mechanical_lemon_lib.jade;
import com.oierbravo.mechanical_lemon_lib.utility.LibLang;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
@@ -10,17 +11,13 @@ import snownee.jade.api.ITooltip;
import snownee.jade.api.config.IPluginConfig;
import snownee.jade.api.ui.BoxStyle;
import snownee.jade.api.ui.IElementHelper;
import snownee.jade.util.Color;
import snownee.jade.api.ui.ProgressStyle;
public class ProgressComponentProvider implements IBlockComponentProvider, IServerDataProvider<BlockAccessor> {
public class LemonProgressComponentProvider implements IBlockComponentProvider, IServerDataProvider<BlockAccessor> {
private final ResourceLocation UID;
private final String translationKey;
String blockEntityID;
public ProgressComponentProvider(ResourceLocation UID, String id, String translationKey){
public LemonProgressComponentProvider(ResourceLocation UID){
this.UID = UID;
this.blockEntityID = id;
this.translationKey = translationKey;
}
public void appendTooltip(ITooltip tooltip, BlockAccessor accessor, IPluginConfig config) {
@@ -28,8 +25,10 @@ public class ProgressComponentProvider implements IBlockComponentProvider, IServ
int progress = accessor.getServerData().getInt("progress");
if(progress > 0){
IElementHelper helper = tooltip.getElementHelper();
tooltip.add(helper.progress((float)progress / 100, Component.translatable("mechanical_lemon_lib.progress",progress),helper.progressStyle().color(Color.hex("#FFFF00").toInt()), BoxStyle.DEFAULT,true));
IElementHelper helper = IElementHelper.get();
ProgressStyle progressStyle = helper.progressStyle().textColor(1);
tooltip.add(helper.progress((float)progress / 100, LibLang.translate("progress", progress).component().withColor(java.awt.Color.GRAY.getRGB()), progressStyle.color(java.awt.Color.YELLOW.getRGB()), BoxStyle.getTransparent(), false));
}
}

View File

@@ -1,26 +1,26 @@
package com.oierbravo.mechanical_lemon_lib.register;
import com.oierbravo.mechanical_lemon_lib.MechanicalLemonLib;
import net.minecraft.world.item.Items;
import net.neoforged.bus.api.IEventBus;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Items;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.RegistryObject;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
public class LemonCreativeModeTabs {
private static final DeferredRegister<CreativeModeTab> TAB_REGISTER =
DeferredRegister.create(Registries.CREATIVE_MODE_TAB, MechanicalLemonLib.MODID);
public static final RegistryObject<CreativeModeTab> MAIN_TAB = TAB_REGISTER.register("main",
public static final DeferredHolder<CreativeModeTab, CreativeModeTab> MAIN_TAB = TAB_REGISTER.register("main",
() -> CreativeModeTab.builder()
.title(Component.translatable("itemGroup.mechanical_lemon_lib"))
.icon(() -> Items.EGG.asItem().getDefaultInstance())
.build());
public static CreativeModeTab getBaseTab() {
return MAIN_TAB.get();
}

View File

@@ -1,37 +0,0 @@
package com.oierbravo.mechanical_lemon_lib.utility;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
public final class Components {
private static final Component IMMUTABLE_EMPTY = Component.empty();
public static Component immutableEmpty() {
return IMMUTABLE_EMPTY;
}
/** Use {@link #immutableEmpty()} when possible to prevent creating an extra object. */
public static MutableComponent empty() {
return Component.empty();
}
public static MutableComponent literal(String str) {
return Component.literal(str);
}
public static MutableComponent translatable(String key) {
return Component.translatable(key);
}
public static MutableComponent translatable(String key, Object... args) {
return Component.translatable(key, args);
}
public static MutableComponent keybind(String name) {
return Component.keybind(name);
}
}

View File

@@ -0,0 +1,41 @@
package com.oierbravo.mechanical_lemon_lib.utility;
import net.minecraft.core.BlockPos;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
public class ItemHandlerUtils {
public static boolean tryToPushBottom(Level pLevel, BlockPos pBlockPos, ItemStackHandler outputItems, boolean simulate){
ItemStack outputItemStack = outputItems.extractItem(0,64,true);
if(outputItemStack.isEmpty())
return false;
Optional<IItemHandler> belowItemHandler = getItemHandler(pLevel, pBlockPos.below());
if(belowItemHandler.isEmpty())
return false;
if(simulate)
return true;
ItemStack remainderItemStack = ItemHandlerHelper.insertItem(belowItemHandler.get(), outputItemStack, true);
outputItems.setStackInSlot(0,remainderItemStack);
ItemHandlerHelper.insertItem(belowItemHandler.get(), outputItemStack, false);
return true;
}
public static Optional<IItemHandler> getItemHandler(Level pLevel, BlockPos pBlockPos){
if(pLevel != null && pLevel.isClientSide())
return Optional.empty();
BlockEntity blockEntity = pLevel.getBlockEntity(pBlockPos);
if(blockEntity == null)
return Optional.empty();
@NotNull LazyOptional<IItemHandler> inventoryHandler = blockEntity.getCapability(ForgeCapabilities.ITEM_HANDLER);
if(!inventoryHandler.isPresent())
return Optional.empty();
return blockEntity.getCapability(ForgeCapabilities.ITEM_HANDLER).resolve();
}
}

View File

@@ -1,81 +0,0 @@
package com.oierbravo.mechanical_lemon_lib.utility;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import com.oierbravo.mechanical_lemon_lib.MechanicalLemonLib;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.fluids.FluidStack;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class Lang {
public static String asId(String name) {
return name.toLowerCase(Locale.ROOT);
}
public static String nonPluralId(String name) {
String asId = asId(name);
return asId.endsWith("s") ? asId.substring(0, asId.length() - 1) : asId;
}
public static List<Component> translatedOptions(String prefix, String... keys) {
List<Component> result = new ArrayList<>(keys.length);
for (String key : keys)
result.add(translate((prefix != null ? prefix + "." : "") + key).component());
return result;
}
//
public static LangBuilder builder() {
return new LangBuilder(MechanicalLemonLib.MODID);
}
public static LangBuilder builder(String namespace) {
return new LangBuilder(namespace);
}
//
public static LangBuilder blockName(BlockState state) {
return builder().add(state.getBlock()
.getName());
}
public static LangBuilder itemName(ItemStack stack) {
return builder().add(stack.getHoverName()
.copy());
}
public static LangBuilder fluidName(FluidStack stack) {
return builder().add(stack.getDisplayName()
.copy());
}
public static com.oierbravo.mechanical_lemon_lib.utility.LangBuilder translate(String langKey, Object... args) {
return builder().translate(langKey, args);
}
public static LangBuilder text(String text) {
return builder().text(text);
}
//
public static Object[] resolveBuilders(Object[] args) {
for (int i = 0; i < args.length; i++)
if (args[i]instanceof LangBuilder cb)
args[i] = cb.component();
return args;
}
}

View File

@@ -1,194 +0,0 @@
package com.oierbravo.mechanical_lemon_lib.utility;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import joptsimple.internal.Strings;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.player.Player;
import java.util.List;
public class LangBuilder {
String namespace;
MutableComponent component;
public LangBuilder(String namespace) {
this.namespace = namespace;
}
public LangBuilder space() {
return text(" ");
}
public LangBuilder newLine() {
return text("\n");
}
/**
* Appends a localised component<br>
* To add an independently formatted localised component, use add() and a nested
* builder
*
* @param langKey
* @param args
* @return
*/
public LangBuilder translate(String langKey, Object... args) {
return add(Components.translatable(namespace + "." + langKey, Lang.resolveBuilders(args)));
}
/**
* Appends a text component
*
* @param literalText
* @return
*/
public LangBuilder text(String literalText) {
return add(Components.literal(literalText));
}
/**
* Appends a colored text component
*
* @param format
* @param literalText
* @return
*/
public LangBuilder text(ChatFormatting format, String literalText) {
return add(Components.literal(literalText).withStyle(format));
}
/**
* Appends a colored text component
*
* @param color
* @param literalText
* @return
*/
public LangBuilder text(int color, String literalText) {
return add(Components.literal(literalText).withStyle(s -> s.withColor(color)));
}
/**
* Appends the contents of another builder
*
* @param otherBuilder
* @return
*/
public LangBuilder add(LangBuilder otherBuilder) {
return add(otherBuilder.component());
}
/**
* Appends a component
*
* @param customComponent
* @return
*/
public LangBuilder add(MutableComponent customComponent) {
component = component == null ? customComponent : component.append(customComponent);
return this;
}
/**
* Appends a component
*
* @param component the component to append
* @return this builder
*/
public LangBuilder add(Component component) {
if (component instanceof MutableComponent mutableComponent)
return add(mutableComponent);
else
return add(component.copy());
}
//
/**
* Applies the format to all added components
*
* @param format
* @return
*/
public LangBuilder style(ChatFormatting format) {
assertComponent();
component = component.withStyle(format);
return this;
}
/**
* Applies the color to all added components
*
* @param color
* @return
*/
public LangBuilder color(int color) {
assertComponent();
component = component.withStyle(s -> s.withColor(color));
return this;
}
//
public MutableComponent component() {
assertComponent();
return component;
}
public String string() {
return component().getString();
}
public String json() {
return Component.Serializer.toJson(component());
}
public void sendStatus(Player player) {
player.displayClientMessage(component(), true);
}
public void sendChat(Player player) {
player.displayClientMessage(component(), false);
}
public void addTo(List<? super MutableComponent> tooltip) {
tooltip.add(component());
}
public void forGoggles(List<? super MutableComponent> tooltip) {
forGoggles(tooltip, 0);
}
public void forGoggles(List<? super MutableComponent> tooltip, int indents) {
tooltip.add(Lang.builder()
.text(Strings.repeat(' ', getIndents(Minecraft.getInstance().font, 4 + indents)))
.add((Component) this)
.component());
}
public static final float DEFAULT_SPACE_WIDTH = 4.0F; // space width in vanilla's default font
static int getIndents(Font font, int defaultIndents) {
int spaceWidth = font.width(" ");
if (DEFAULT_SPACE_WIDTH == spaceWidth) {
return defaultIndents;
}
return Mth.ceil(DEFAULT_SPACE_WIDTH * defaultIndents / spaceWidth);
}
//
private void assertComponent() {
if (component == null)
throw new IllegalStateException("No components were added to builder");
}
}

View File

@@ -0,0 +1,14 @@
package com.oierbravo.mechanical_lemon_lib.utility;
import com.simibubi.create.api.stress.BlockStressValues;
import com.tterrag.registrate.util.nullness.NonNullConsumer;
import net.minecraft.world.level.block.Block;
import org.jetbrains.annotations.NotNull;
public class LemonRegistrate {
public static <B extends Block> @NotNull NonNullConsumer<B> setImpact(double value) {
return (block) -> {
BlockStressValues.IMPACTS.register(block, () -> value);
};
}
}

View File

@@ -1,6 +1,8 @@
package com.oierbravo.mechanical_lemon_lib.utility;
import com.oierbravo.mechanical_lemon_lib.MechanicalLemonLib;
import net.createmod.catnip.lang.Lang;
import net.createmod.catnip.lang.LangBuilder;
public class LibLang extends Lang {
public LibLang() {

View File

@@ -1,63 +0,0 @@
# This is an example mods.toml file. It contains the data relating to the loading mods.
# There are several mandatory fields (#mandatory), and many more that are optional (#optional).
# The overall format is standard TOML format, v0.5.0.
# Note that there are a couple of TOML lists in this file.
# Find more information on toml format here: https://github.com/toml-lang/toml
# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
modLoader = "javafml" #mandatory
# A version range to match for said mod loader - for regular FML @Mod it will be the forge version
loaderVersion = "${loader_version_range}" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties.
# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here.
license = "${mod_license}"
# A URL to refer people to when problems occur with this mod
#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional
# A list of mods - how many allowed here is determined by the individual mod loader
[[mods]] #mandatory
# The modid of the mod
modId = "${mod_id}" #mandatory
# The version number of the mod
version = "${mod_version}" #mandatory
# A display name for the mod
displayName = "${mod_name}" #mandatory
# A URL to query for updates for this mod. See the JSON update specification https://docs.minecraftforge.net/en/latest/misc/updatechecker/
#updateJSONURL="https://change.me.example.invalid/updates.json" #optional
# A URL for the "homepage" for this mod, displayed in the mod UI
#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional
# A file name (in the root of the mod JAR) containing a logo for display
#logoFile="mechanical_lemon_lib.png" #optional
# A text field displayed in the mod UI
#credits="Thanks for this example mod goes to Java" #optional
# A text field displayed in the mod UI
authors = "${mod_authors}" #optional
# Display Test controls the display for your mod in the server connection screen
# MATCH_VERSION means that your mod will cause a red X if the versions on client and server differ. This is the default behaviour and should be what you choose if you have server and client elements to your mod.
# IGNORE_SERVER_VERSION means that your mod will not cause a red X if it's present on the server but not on the client. This is what you should use if you're a server only mod.
# IGNORE_ALL_VERSION means that your mod will not cause a red X if it's present on the client or the server. This is a special case and should only be used if your mod has no server component.
# NONE means that no display test is set on your mod. You need to do this yourself, see IExtensionPoint.DisplayTest for more information. You can define any scheme you wish with this value.
# IMPORTANT NOTE: this is NOT an instruction as to which environments (CLIENT or DEDICATED SERVER) your mod loads on. Your mod should load (and maybe do nothing!) whereever it finds itself.
#displayTest="MATCH_VERSION" # MATCH_VERSION is the default if nothing is specified (#optional)
# The description text for the mod (multi line!) (#mandatory)
description = '''${mod_description}'''
# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional.
[[dependencies."${mod_id}"]] #optional
# the modid of the dependency
modId = "forge" #mandatory
# Does this dependency have to exist - if not, ordering below must be specified
mandatory = true #mandatory
# The version range of the dependency
versionRange = "${forge_version_range}" #mandatory
# An ordering relationship for the dependency - BEFORE or AFTER required if the dependency is not mandatory
# BEFORE - This mod is loaded BEFORE the dependency
# AFTER - This mod is loaded AFTER the dependency
ordering = "NONE"
# Side this dependency is applied on - BOTH, CLIENT, or SERVER
side = "BOTH"# Here's another dependency
[[dependencies."${mod_id}"]]
modId = "minecraft"
mandatory = true
# This version range declares a minimum of the current minecraft version up to but not including the next major version
versionRange = "${minecraft_version_range}"
ordering = "NONE"
side = "BOTH"

View File

@@ -0,0 +1,27 @@
modLoader = "javafml" #mandatory
loaderVersion = "[0,)"# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties.
license = "${mod_license}"
[[mods]] #mandatory
modId = "${mod_id}" #mandatory
version = "${mod_version}" #mandatory
displayName = "${mod_name}" #mandatory
#updateJSONURL="https://change.me.example.invalid/updates.json" #optional
#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional
#logoFile="mechanical_lemon_lib.png" #optional
#credits="Thanks for this example mod goes to Java" #optional
authors = "${mod_author}" #optional
description = '''${mod_description}'''
[[dependencies."${mod_id}"]]
modId="neoforge"
type="required"
versionRange="${neo_version_range}"
ordering="NONE"
side="BOTH"
[[dependencies."${mod_id}"]]
modId="minecraft"
type="required"
versionRange="${minecraft_version_range}"
ordering="NONE"
side="BOTH"

View File

@@ -1,8 +1,8 @@
{
"mechanical_lemon_lib.progress": "Progress: %d%%",
"mechanical_lemon_tab": "Mechanicals",
"mechanical_lemon_lib.ui.progress": "Progress: %d%%",
"itemGroup.mechanical_lemon_lib": "Mechanicals",
"mechanical_lemon_lib.ui.recipe_requirement.none.tooltip": "No specific requirement",
"mechanical_lemon_lib.ui.recipe_requirement.biome.tooltip": "Requires %s biome",
"mechanical_lemon_lib.ui.recipe_requirement.biome.tooltip": "Biome: %s",
"mechanical_lemon_lib.ui.recipe_requirement.min_height.tooltip": "Min Y: %s",
"mechanical_lemon_lib.ui.recipe_requirement.max_height.tooltip": "Max Y: %s",
"mechanical_lemon_lib.ui.recipe_requirement.min_speed.tooltip": "Min Speed: %s",