Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added examples/kubejs/images/energizing.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/kubejs/images/results_builder.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions examples/kubejs/lang.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//Needs to be on client_scripts folder!
//Or you can have a client event to add the lang key without needing to do things with .json
//But it might be a more difficult way to translate it with external tools!

ClientEvents.lang('en_us', event => {
event.add('replication.matter_type.matter_lambda', 'Esto es una tombola, tombola')
})
233 changes: 233 additions & 0 deletions examples/kubejs/matter_recipes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
/*
Needs to be on the server_scripts folder!

This is the main part about this little guide, how to add matter to items and blocks
There are 2 ways (only for smelting and crafting recipes), they are assigned automatically or manually
By default, you can get calculations up to 11 depth, that means that from log to final item,
there can only be 11 recipes

For all the other items, you need to add them manually, which is a bit of a bummer,
but thats why we are here

This example uses Powah's items and blocks, but you can use any other mod!
It applies the same principles!

Links:
Replication global object -> https://github.com/Buuz135/Replication/blob/1.21/src/main/java/com/buuz135/replication/integration/kubejs/ReplicationKubeJSGateway.java
Registry -> https://github.com/Buuz135/Replication/blob/1.21/src/main/java/com/buuz135/replication/ReplicationRegistry.java

Currently there are these types:
earth, nether, ender, organic, metallic, precious, living, quantum

To disable automatic recipes, check configuration (ReplicationConfig.RecipeCalculation) and set MAX_RECIPE_DEPTH to 0
*/

ServerEvents.recipes(event => {

const ENERGY_TO_MATTER_FACTOR = 0.01;//Since energy is free in most packs, there is a low "efficiency"

//Lets take dry ice as example, but you can do for another things:
/*{
"type": "powah:energizing", //recipe type if we need want all recipes from a particular machine
"energy": 120000, //energy cost
"ingredients": [ //An array of items, which you can get the
{
"tag": "c:rods/blaze"
}
],
"result": {
"count": 1,
"id": "powah:crystal_blazing"
}
}
*/

//You can have a Set to store the values to store the items you previous did
//to concat them or add compact to mods!
//let matter = new WeakSet()

//Thats for more advanced setups, if you have recipes calculation on
//Here is getting all recipes from Powah!'s Energizing, which you can add compact this way

//Here we use the event.custom
//Below this, on another event, there is a builder, sort of nicer way to add matter if you like them!
event.forEachRecipe({ type: 'powah:energizing' }, recipe => { //forEachRecipe is a way to iterate all recipes from a type
let json = recipe.json;

let energy = json.get('energy');
if(!energy)
{
console.warn(`Recipe without energy: ${recipe.getId()}`);
return;
}

//Result
let result = json.get('result');
if(!result)
{
console.warn(`Recipe without results: ${recipe.getId()}`);
return;
}

let idElement = result.get('id');
if(!idElement)
{
console.warn(`No output: ${recipe.getId()}`);
return;
}
let itemId = idElement.getAsString ? idElement.getAsString() : String(idElement).replace("\"", "");

let count = 1;
if(result.has('count'))
{
count = result.get('count');
}

let matterAmount = energy * ENERGY_TO_MATTER_FACTOR;
let matterMap = {
'metallic': matterAmount
};
event.custom(Replication.matterValueForItem(itemId, matterMap));
});
});

ServerEvents.recipes(event => {

const MatterBuilder = () => {
let _input = null;
let _inputType = null; // 'item', 'tag', 'ingredient'
let _matterMap = {};
let _customId = null;

const defaultId = () => {
if(!_input) return 'unknown';
let inputStr = _input;
if(typeof _input === 'object')
{
inputStr = _input.item || _input.tag || JSON.stringify(_input);
}
let cleaned = inputStr.toString().replace(/[#]/g, '').replace(/[^a-z0-9_.-]/gi, '_').toLowerCase();
let matterPart = Object.keys(_matterMap).join('_');
return `replication:matter_value/${cleaned}_${matterPart}`;
};

return {
/**
* @param {string} itemId - ID of the item (e.g: 'minecraft:stone')
*/
withItem(itemId)
{
_input = itemId;
_inputType = 'item';
return this;
},

/**
* @param {string} tag - Tag (e.g: '#c:iron_ingots' or 'c:iron_ingots')
*/
withTag(tag)
{
_input = tag.startsWith('#') ? tag.substring(1) : tag;
_inputType = 'tag';
return this;
},

/**
* @param {Object} ingredient - e.g: { item: 'minecraft:stone' } or { tag: 'c:ingots' }
*/
withIngredient(ingredient)
{
_input = ingredient;
_inputType = 'ingredient';
return this;
},

/**
* Add matter to a recipe
* @param {string} type - Matter key (ej: 'earth', 'metallic')
* @param {number} amount - Amount of matter, must be an integer, will round up for numbers with decimals
*/
addMatter(type, amount)
{
_matterMap[type] = amount;
return this;
},

/**
* Asign a id to the recipe and register it.
* @param {string} id - ID of the recipe 'namespace:path' (e.g mymodpack:replication/matter/...)
*/
withId(id)
{
_customId = id;
return this.register()
},

/**
* Generate the recipe with default ID, you can use withId to do the same but with an recipe id
* @returns void
*/
register()
{
if(!_input || !_inputType)
{
console.error('[MatterValueBuilder] No input specified. Use withItem, withTag or withIngredient. Skipping');
return;
}

if(typeof Replication === 'undefined')
{
console.error('[MatterValueBuilder] Replication object is not available. Is the mod loaded?');
return;
}

let recipeJson;
if(_inputType === 'item')
{
recipeJson = Replication.matterValueForItem(_input, _matterMap); //Given a item and a map of matters with amount, return a json object with those matters and item
}
else if(_inputType === 'tag')
{
recipeJson = Replication.matterValueForTag(_input, _matterMap); //Given a tag and a map of matters with amount, return a json object with those matters and tag
}
else
{
recipeJson = Replication.matterValue(_input, _matterMap); //Given an ingredient and a map of matters with amount, return a json object with those matters and ingredient
}

if(_customId)
{
event.custom(recipeJson).id(_customId);
}
else
{
//KubeJS generate a random recipe id each time, so we would need
//to give an id ourselft or an generated one from inputs
event.custom(recipeJson).id(defaultId());
}
}
};
};

//This is how to use the builder
MatterBuilder()
.withItem('guideme:guide')
.addMatter('earth', 3.0) //This is fine, since it will transform to 3
.addMatter('metallic', 1.5) //This is mostly fine, it will transform to 2
.withId('mypack:replication/guide');

//But you can do more with the builder, remember the first setup? Well, we have more, you can use the builder
//to give more or less, depending on what you want!
let a_value = 0 //Lets say that we add a value depending on a variable
let builder = MatterBuilder()
.withItem('replication:matter_blueprint')
.addMatter('earth', 3.0) //This is fine, since it will transform to 3
.addMatter('metallic', 1.5) //This is mostly fine, it will transform to 2

if(a_value < 5)
{
builder.addMatter('ender', 4)
}

builder.register()
})
118 changes: 118 additions & 0 deletions examples/kubejs/register_matter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
Needs to be on startup_scripts folder!

Similar to registering items and blocks, we need to do the same
for our matter types

You must have a .png with the texture on the kubejs/assets/replication/textures/gui/mattertypes/<id of the matter>.png
or the game will crash if you open the terminal!

Links:
ReplicationRegistry -> https://github.com/Buuz135/Replication/blob/1.21/src/main/java/com/buuz135/replication/ReplicationRegistry.java
MatterTypeBuilder -> https://github.com/Buuz135/Replication/blob/1.21/src/main/java/com/buuz135/replication/integration/kubejs/MatterTypeBuilder.java


Here is every way you can do it!
*/
StartupEvents.registry('replication:matter_types', event => {
//The simplest way
event.create("ultimatium") //Id of the matter, we will need it later
.color(0.2, 0.7, 1.0, 1.0) //RGBA (from 0.0 to 1.0)
.displayName("Ultimatum") //Display name
.max(100) //can be any number, doesnt matter

//The hard way but cool one!
//First we need the builder, we need to load some classes first
const MatterRegistry = Java.loadClass('com.buuz135.replication.ReplicationRegistry')
const MatterTypeBuilder = Java.loadClass('com.buuz135.replication.integration.kubejs.MatterTypeBuilder')

//You can do something similar as the builder on the matter_recipes.js on server_scripts
let myBuilder = new MatterTypeBuilder('matter_to_add')
myBuilder.color(0.5, 0.1, 0.9, 1.0).max(2500)
event.add(MatterRegistry.MATTER_TYPES_KEY, myBuilder)

//Another hard way
//This time using a lambda, for customs colors!
//This is how quantum matter type is done!

//We need to load the classes first
const CustomMatterType = Java.loadClass('com.buuz135.replication.integration.kubejs.CustomMatterType')
const FloatArrayList = Java.loadClass('it.unimi.dsi.fastutil.floats.FloatArrayList');
//Minecraft class is just to get the time of the day
const Minecraft = Java.loadClass('net.minecraft.client.Minecraft');

//In this case, we need an arrow function (a.k.a a lambda), useful if you need to have more complex setups, like this one
//or quantum matter
event.createCustom('matter_lambda', () => {
let name = "matter_lambda" //To give a name, we need a lang file with the following "replication.matter_type.matter_lambda": "Matter Lambda",

//Dynamic color depending on some conditions
//In this case, depending on the time of the day and a period
//while doing a rainbow

//At the end, you must have the variable list with 4 values or crash
//RGBA, then convert to float shown on the return
let color = () => {
let list = new FloatArrayList();
try
{
let level = Minecraft.getInstance().level;
if(level)
{
let time = level.getDayTime(); //MC time, around 60k samples, more than enough for most
let period = 200; //full cycle every 10 seconds (20 ticks/sec)
let hue = (time % period) / period; // 0..1

//HSV to RGB (saturation=1, value=1)
let h = hue;
let s = 1.0;
let v = 1.0;

let r, g, b;
let i = Math.floor(h * 6);
let f = h * 6 - i;
let p = v * (1 - s);
let q = v * (1 - f * s);
let t = v * (1 - (1 - f) * s);

switch(i % 6)
{
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
case 5: r = v; g = p; b = q; break;
}

list.add(r);
list.add(g);
list.add(b);
list.add(1.0); //alpha
}
else
{
//A default color just in case level is null
list.add(0.5);
list.add(0.5);
list.add(0.5);
list.add(1.0);
}
}
catch(e)
{
//If any error (e.g., on server or you pass an string to a number),
//return a default color
list.add(1.0);
list.add(1.0);
list.add(1.0);
list.add(1.0);
//console.log(e) //This spam the logs a lot but tells you a lot too
}
return list.toFloatArray();
};

let max = 5000
return new CustomMatterType(name, color, max)
})
})