parent
7b6cce48b9
commit
e238ceceaf
@ -10,6 +10,8 @@ import net.minecraft.data.recipes.RecipeBuilder
|
|||||||
import net.minecraft.data.recipes.RecipeProvider
|
import net.minecraft.data.recipes.RecipeProvider
|
||||||
import net.minecraft.resources.ResourceLocation
|
import net.minecraft.resources.ResourceLocation
|
||||||
import net.minecraft.tags.TagKey
|
import net.minecraft.tags.TagKey
|
||||||
|
import net.minecraft.util.valueproviders.ConstantFloat
|
||||||
|
import net.minecraft.util.valueproviders.FloatProvider
|
||||||
import net.minecraft.world.item.Item
|
import net.minecraft.world.item.Item
|
||||||
import net.minecraft.world.item.crafting.Ingredient
|
import net.minecraft.world.item.crafting.Ingredient
|
||||||
import net.minecraft.world.level.ItemLike
|
import net.minecraft.world.level.ItemLike
|
||||||
@ -77,14 +79,15 @@ class MatteryRecipeProvider(generatorIn: DataGenerator) : RecipeProvider(generat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun plate(id: String, count: Int = 1, workTicks: Int = 200) {
|
fun plate(id: String, count: Int = 1, workTicks: Int = 200, experience: FloatProvider = ConstantFloat.ZERO) {
|
||||||
exec { _, consumer ->
|
exec { _, consumer ->
|
||||||
consumer.accept(PlatePressShallowFinishedRecipe(
|
consumer.accept(PlatePressShallowFinishedRecipe(
|
||||||
ResourceLocation(DataGen.MOD_ID, "plates/$id"),
|
ResourceLocation(DataGen.MOD_ID, "plates/$id"),
|
||||||
ResourceLocation("forge", "ingots/$id"),
|
ResourceLocation("forge", "ingots/$id"),
|
||||||
ResourceLocation("forge", "plates/$id"),
|
ResourceLocation("forge", "plates/$id"),
|
||||||
count,
|
count,
|
||||||
workTicks
|
workTicks,
|
||||||
|
experience = experience
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,18 @@ package ru.dbotthepony.mc.otm.datagen.recipes
|
|||||||
|
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonPrimitive
|
import com.google.gson.JsonPrimitive
|
||||||
|
import com.mojang.serialization.JsonOps
|
||||||
import net.minecraft.data.recipes.FinishedRecipe
|
import net.minecraft.data.recipes.FinishedRecipe
|
||||||
import net.minecraft.resources.ResourceLocation
|
import net.minecraft.resources.ResourceLocation
|
||||||
|
import net.minecraft.util.valueproviders.ConstantFloat
|
||||||
|
import net.minecraft.util.valueproviders.FloatProvider
|
||||||
|
import net.minecraft.util.valueproviders.UniformFloat
|
||||||
import net.minecraft.world.item.crafting.RecipeSerializer
|
import net.minecraft.world.item.crafting.RecipeSerializer
|
||||||
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe
|
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe
|
||||||
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipeFactory
|
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipeFactory
|
||||||
import ru.dbotthepony.mc.otm.container.set
|
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
|
||||||
import ru.dbotthepony.mc.otm.core.set
|
import ru.dbotthepony.mc.otm.core.set
|
||||||
|
import ru.dbotthepony.mc.otm.core.toJsonStrict
|
||||||
|
import ru.dbotthepony.mc.otm.data.getOrNull
|
||||||
|
|
||||||
class PlatePressFinishedRecipe(private val recipe: PlatePressRecipe) : FinishedRecipe {
|
class PlatePressFinishedRecipe(private val recipe: PlatePressRecipe) : FinishedRecipe {
|
||||||
override fun serializeRecipeData(it: JsonObject) {
|
override fun serializeRecipeData(it: JsonObject) {
|
||||||
@ -21,6 +25,7 @@ class PlatePressFinishedRecipe(private val recipe: PlatePressRecipe) : FinishedR
|
|||||||
}
|
}
|
||||||
|
|
||||||
it["work_time"] = JsonPrimitive(recipe.workTime)
|
it["work_time"] = JsonPrimitive(recipe.workTime)
|
||||||
|
it["experience"] = FloatProvider.CODEC.toJsonStrict(recipe.experience)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getId(): ResourceLocation {
|
override fun getId(): ResourceLocation {
|
||||||
@ -45,7 +50,8 @@ class PlatePressShallowFinishedRecipe(
|
|||||||
private val input: ResourceLocation,
|
private val input: ResourceLocation,
|
||||||
private val output: ResourceLocation,
|
private val output: ResourceLocation,
|
||||||
private val count: Int = 1,
|
private val count: Int = 1,
|
||||||
private val workTime: Int = 200
|
private val workTime: Int = 200,
|
||||||
|
private val experience: FloatProvider = ConstantFloat.ZERO,
|
||||||
) : FinishedRecipe {
|
) : FinishedRecipe {
|
||||||
override fun serializeRecipeData(it: JsonObject) {
|
override fun serializeRecipeData(it: JsonObject) {
|
||||||
it["input"] = JsonObject().also {
|
it["input"] = JsonObject().also {
|
||||||
@ -60,6 +66,7 @@ class PlatePressShallowFinishedRecipe(
|
|||||||
}
|
}
|
||||||
|
|
||||||
it["work_time"] = JsonPrimitive(workTime)
|
it["work_time"] = JsonPrimitive(workTime)
|
||||||
|
it["experience"] = FloatProvider.CODEC.toJsonStrict(experience)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getId(): ResourceLocation {
|
override fun getId(): ResourceLocation {
|
||||||
|
@ -1,19 +1,21 @@
|
|||||||
package ru.dbotthepony.mc.otm.datagen.recipes
|
package ru.dbotthepony.mc.otm.datagen.recipes
|
||||||
|
|
||||||
|
import net.minecraft.util.valueproviders.ConstantFloat
|
||||||
|
|
||||||
fun addPlatePressRecipes(provider: MatteryRecipeProvider) {
|
fun addPlatePressRecipes(provider: MatteryRecipeProvider) {
|
||||||
val baselineMetals = arrayOf("iron", "silver", "bronze", "lead", "constantan", "brass")
|
val baselineMetals = arrayOf("iron" to 0.2f, "silver" to 0.3f, "bronze" to 0.3f, "lead" to 0.3f, "constantan" to 0.4f, "brass" to 0.3f)
|
||||||
val softMetals = arrayOf("gold", "aluminum", "aluminium", "copper", "electrum", "zinc")
|
val softMetals = arrayOf("gold" to 0.4f, "aluminum" to 0.3f, "aluminium" to 0.3f, "copper" to 0.2f, "electrum" to 0.4f, "zinc" to 0.3f)
|
||||||
val hardMetals = arrayOf("tritanium", "steel", "tungsten", "uranium")
|
val hardMetals = arrayOf("tritanium" to 0.5f, "steel" to 0.5f, "tungsten" to 0.55f, "uranium" to 0.5f)
|
||||||
|
|
||||||
for (thing in baselineMetals) {
|
for ((thing, exp) in baselineMetals) {
|
||||||
provider.plate(thing)
|
provider.plate(thing, experience = ConstantFloat.of(exp), workTicks = 160)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (thing in softMetals) {
|
for ((thing, exp) in softMetals) {
|
||||||
provider.plate(thing, workTicks = 140)
|
provider.plate(thing, workTicks = 120, experience = ConstantFloat.of(exp))
|
||||||
}
|
}
|
||||||
|
|
||||||
for (thing in hardMetals) {
|
for ((thing, exp) in hardMetals) {
|
||||||
provider.plate(thing, workTicks = 300)
|
provider.plate(thing, workTicks = 240, experience = ConstantFloat.of(exp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ package ru.dbotthepony.mc.otm
|
|||||||
|
|
||||||
import net.minecraft.client.server.IntegratedServer
|
import net.minecraft.client.server.IntegratedServer
|
||||||
import net.minecraft.server.MinecraftServer
|
import net.minecraft.server.MinecraftServer
|
||||||
|
import net.minecraft.server.level.ServerLevel
|
||||||
import net.minecraft.world.level.Level
|
import net.minecraft.world.level.Level
|
||||||
import net.minecraftforge.api.distmarker.Dist
|
import net.minecraftforge.api.distmarker.Dist
|
||||||
import net.minecraftforge.event.TickEvent
|
import net.minecraftforge.event.TickEvent
|
||||||
@ -195,6 +196,8 @@ fun tickWhileServer(condition: () -> Boolean, ticker: () -> Unit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Level.once(ticker: ITickable) {
|
fun Level.once(ticker: ITickable) {
|
||||||
|
if (this.isClientSide) return
|
||||||
|
|
||||||
if (!SERVER_IS_LIVE) {
|
if (!SERVER_IS_LIVE) {
|
||||||
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
|
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
|
||||||
return
|
return
|
||||||
@ -204,6 +207,8 @@ fun Level.once(ticker: ITickable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Level.oncePre(ticker: ITickable) {
|
fun Level.oncePre(ticker: ITickable) {
|
||||||
|
if (this.isClientSide) return
|
||||||
|
|
||||||
if (!SERVER_IS_LIVE) {
|
if (!SERVER_IS_LIVE) {
|
||||||
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
|
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
|
||||||
return
|
return
|
||||||
@ -213,6 +218,8 @@ fun Level.oncePre(ticker: ITickable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Level.addTicker(ticker: IConditionalTickable) {
|
fun Level.addTicker(ticker: IConditionalTickable) {
|
||||||
|
if (this.isClientSide) return
|
||||||
|
|
||||||
if (!SERVER_IS_LIVE) {
|
if (!SERVER_IS_LIVE) {
|
||||||
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
|
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
|
||||||
return
|
return
|
||||||
@ -222,6 +229,8 @@ fun Level.addTicker(ticker: IConditionalTickable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Level.addTickerPre(ticker: IConditionalTickable) {
|
fun Level.addTickerPre(ticker: IConditionalTickable) {
|
||||||
|
if (this.isClientSide) return
|
||||||
|
|
||||||
if (!SERVER_IS_LIVE) {
|
if (!SERVER_IS_LIVE) {
|
||||||
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
|
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
|
||||||
return
|
return
|
||||||
@ -231,18 +240,22 @@ fun Level.addTickerPre(ticker: IConditionalTickable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Level.until(ticker: () -> Boolean) {
|
fun Level.until(ticker: () -> Boolean) {
|
||||||
|
if (this.isClientSide) return
|
||||||
addTicker(IConditionalTickable.wrap(ticker))
|
addTicker(IConditionalTickable.wrap(ticker))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Level.untilPre(ticker: () -> Boolean) {
|
fun Level.untilPre(ticker: () -> Boolean) {
|
||||||
|
if (this.isClientSide) return
|
||||||
addTickerPre(IConditionalTickable.wrap(ticker))
|
addTickerPre(IConditionalTickable.wrap(ticker))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Level.`while`(condition: () -> Boolean, ticker: () -> Unit) {
|
fun Level.`while`(condition: () -> Boolean, ticker: () -> Unit) {
|
||||||
|
if (this.isClientSide) return
|
||||||
addTicker(IConditionalTickable.wrap(condition, ticker))
|
addTicker(IConditionalTickable.wrap(condition, ticker))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Level.whilePre(condition: () -> Boolean, ticker: () -> Unit) {
|
fun Level.whilePre(condition: () -> Boolean, ticker: () -> Unit) {
|
||||||
|
if (this.isClientSide) return
|
||||||
addTickerPre(IConditionalTickable.wrap(condition, ticker))
|
addTickerPre(IConditionalTickable.wrap(condition, ticker))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,29 +32,34 @@ abstract class MatteryWorkerBlockEntity<JobType : MatteryWorkerBlockEntity.Job>(
|
|||||||
open class Job {
|
open class Job {
|
||||||
open val ticks: Double
|
open val ticks: Double
|
||||||
open val powerUsage: Decimal
|
open val powerUsage: Decimal
|
||||||
|
open val experience: Float
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
ticks: Double,
|
ticks: Double,
|
||||||
powerUsage: Decimal = Decimal.ZERO
|
powerUsage: Decimal = Decimal.ZERO,
|
||||||
|
experience: Float = 0f,
|
||||||
) {
|
) {
|
||||||
this.ticks = ticks
|
this.ticks = ticks
|
||||||
this.powerUsage = powerUsage
|
this.powerUsage = powerUsage
|
||||||
|
this.experience = experience
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
tag: CompoundTag
|
tag: CompoundTag
|
||||||
) : this(tag.getDouble(TICKS_KEY), tag.getDecimal(POWER_KEY))
|
) : this(tag.getDouble(TICKS_KEY), tag.getDecimal(POWER_KEY), tag.getFloat(EXPERIENCE_KEY))
|
||||||
|
|
||||||
open fun serializeNBT(): CompoundTag {
|
open fun serializeNBT(): CompoundTag {
|
||||||
return CompoundTag().also {
|
return CompoundTag().also {
|
||||||
it[TICKS_KEY] = ticks
|
it[TICKS_KEY] = ticks
|
||||||
it[POWER_KEY] = powerUsage
|
it[POWER_KEY] = powerUsage
|
||||||
|
it[EXPERIENCE_KEY] = experience
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TICKS_KEY = "ticks"
|
const val TICKS_KEY = "ticks"
|
||||||
const val POWER_KEY = "power"
|
const val POWER_KEY = "power"
|
||||||
|
const val EXPERIENCE_KEY = "power"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,8 +70,9 @@ abstract class MatteryWorkerBlockEntity<JobType : MatteryWorkerBlockEntity.Job>(
|
|||||||
constructor(
|
constructor(
|
||||||
itemStack: ItemStack,
|
itemStack: ItemStack,
|
||||||
ticks: Double,
|
ticks: Double,
|
||||||
power: Decimal = Decimal.ZERO
|
power: Decimal = Decimal.ZERO,
|
||||||
) : super(ticks, power) {
|
experience: Float = 0f,
|
||||||
|
) : super(ticks, power, experience) {
|
||||||
this.itemStack = itemStack
|
this.itemStack = itemStack
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,10 @@ import net.minecraft.core.BlockPos
|
|||||||
import net.minecraft.core.Direction
|
import net.minecraft.core.Direction
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
|
import net.minecraft.server.level.ServerLevel
|
||||||
|
import net.minecraft.server.level.ServerPlayer
|
||||||
import net.minecraft.world.Container
|
import net.minecraft.world.Container
|
||||||
|
import net.minecraft.world.entity.ExperienceOrb
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||||
@ -26,16 +29,27 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
|||||||
import ru.dbotthepony.mc.otm.registry.MRecipes
|
import ru.dbotthepony.mc.otm.registry.MRecipes
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.map
|
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
|
import ru.dbotthepony.mc.otm.once
|
||||||
|
import ru.dbotthepony.mc.otm.onceServer
|
||||||
|
|
||||||
class PlatePressBlockEntity(
|
class PlatePressBlockEntity(
|
||||||
p_155229_: BlockPos,
|
p_155229_: BlockPos,
|
||||||
p_155230_: BlockState
|
p_155230_: BlockState
|
||||||
) : MatteryWorkerBlockEntity<MatteryWorkerBlockEntity.ItemJob>(MBlockEntities.PLATE_PRESS, p_155229_, p_155230_,
|
) : MatteryWorkerBlockEntity<MatteryWorkerBlockEntity.ItemJob>(MBlockEntities.PLATE_PRESS, p_155229_, p_155230_, ::ItemJob), IDroppableContainer {
|
||||||
::ItemJob
|
|
||||||
), IDroppableContainer {
|
|
||||||
val container = MatteryContainer(this::setChangedLight, 2)
|
val container = MatteryContainer(this::setChangedLight, 2)
|
||||||
override val energy = WorkerEnergyStorage(this::setChangedLight, ServerConfig.PLATE_PRESS)
|
override val energy = WorkerEnergyStorage(this::setChangedLight, ServerConfig.PLATE_PRESS)
|
||||||
|
|
||||||
|
var experience = 0.0
|
||||||
|
|
||||||
|
fun popExperience(player: ServerPlayer) {
|
||||||
|
val whole = experience.toInt()
|
||||||
|
|
||||||
|
if (whole > 0) {
|
||||||
|
experience -= whole
|
||||||
|
ExperienceOrb.award(player.level as ServerLevel, player.position(), whole)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override val droppableContainer: Container
|
override val droppableContainer: Container
|
||||||
get() = container
|
get() = container
|
||||||
val itemHandler = container.handler(object : MatteryContainerHooks {
|
val itemHandler = container.handler(object : MatteryContainerHooks {
|
||||||
@ -68,11 +82,13 @@ class PlatePressBlockEntity(
|
|||||||
override fun saveAdditional(nbt: CompoundTag) {
|
override fun saveAdditional(nbt: CompoundTag) {
|
||||||
super.saveAdditional(nbt)
|
super.saveAdditional(nbt)
|
||||||
nbt[INVENTORY_KEY] = container.serializeNBT()
|
nbt[INVENTORY_KEY] = container.serializeNBT()
|
||||||
|
nbt["experience"] = experience
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun load(nbt: CompoundTag) {
|
override fun load(nbt: CompoundTag) {
|
||||||
super.load(nbt)
|
super.load(nbt)
|
||||||
nbt.map(INVENTORY_KEY, container::deserializeNBT)
|
nbt.map(INVENTORY_KEY, container::deserializeNBT)
|
||||||
|
experience = nbt.getDouble("experience")
|
||||||
}
|
}
|
||||||
|
|
||||||
override val defaultDisplayName: Component
|
override val defaultDisplayName: Component
|
||||||
@ -89,6 +105,7 @@ class PlatePressBlockEntity(
|
|||||||
if (!container.fullyAddItem(job.itemStack, start = SLOT_OUTPUT, end = SLOT_OUTPUT))
|
if (!container.fullyAddItem(job.itemStack, start = SLOT_OUTPUT, end = SLOT_OUTPUT))
|
||||||
return Status.FAILURE_ITEM
|
return Status.FAILURE_ITEM
|
||||||
|
|
||||||
|
experience = (experience + job.experience).coerceAtMost(100.0)
|
||||||
return Status.SUCCESS
|
return Status.SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +116,7 @@ class PlatePressBlockEntity(
|
|||||||
|
|
||||||
val recipe = level?.recipeManager?.getRecipeFor(MRecipes.PLATE_PRESS, container, level!!)?.orElse(null) ?: return null to IdleReason.ITEM
|
val recipe = level?.recipeManager?.getRecipeFor(MRecipes.PLATE_PRESS, container, level!!)?.orElse(null) ?: return null to IdleReason.ITEM
|
||||||
container[SLOT_INPUT].shrink(1)
|
container[SLOT_INPUT].shrink(1)
|
||||||
return ItemJob(recipe.resultItem, recipe.workTime.toDouble(), BASELINE_CONSUMPTION) to null
|
return ItemJob(recipe.resultItem, recipe.workTime.toDouble(), BASELINE_CONSUMPTION, experience = recipe.experience.sample(level!!.random)) to null
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -73,7 +73,7 @@ class EnergyCounterBlock : MatteryBlock(), EntityBlock {
|
|||||||
) {
|
) {
|
||||||
super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston)
|
super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston)
|
||||||
|
|
||||||
if (!level.isClientSide && SERVER_IS_LIVE) {
|
if (SERVER_IS_LIVE) {
|
||||||
level.once {
|
level.once {
|
||||||
(level.getBlockEntity(pos) as? EnergyCounterBlockEntity)?.checkSurroundings()
|
(level.getBlockEntity(pos) as? EnergyCounterBlockEntity)?.checkSurroundings()
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,12 @@ object PlatePressRecipeCategory : IRecipeCategory<PlatePressRecipe>, IDrawable {
|
|||||||
mouseY: Double
|
mouseY: Double
|
||||||
) {
|
) {
|
||||||
minecraft.font.drawAligned(stack, TranslatableComponent("otm.gui.recipe.ticks", recipe.workTime), TextAlign.TOP_CENTER, 40f, 30f, RGBAColor.BLACK)
|
minecraft.font.drawAligned(stack, TranslatableComponent("otm.gui.recipe.ticks", recipe.workTime), TextAlign.TOP_CENTER, 40f, 30f, RGBAColor.BLACK)
|
||||||
|
|
||||||
|
val average = recipe.experience.toString()
|
||||||
|
|
||||||
|
if (average != "0.0") {
|
||||||
|
minecraft.font.drawAligned(stack, TranslatableComponent("gui.jei.category.smelting.experience", average), TextAlign.TOP_CENTER, 40f, 1f, RGBAColor.BLACK)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getWidth(): Int {
|
override fun getWidth(): Int {
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
package ru.dbotthepony.mc.otm.core
|
package ru.dbotthepony.mc.otm.core
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement
|
||||||
|
import com.google.gson.JsonSyntaxException
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.JsonOps
|
||||||
|
import net.minecraft.nbt.NbtOps
|
||||||
|
import net.minecraft.nbt.Tag
|
||||||
import net.minecraft.network.FriendlyByteBuf
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
import net.minecraft.network.chat.MutableComponent
|
import net.minecraft.network.chat.MutableComponent
|
||||||
import net.minecraft.network.chat.contents.LiteralContents
|
import net.minecraft.network.chat.contents.LiteralContents
|
||||||
@ -11,6 +17,39 @@ import net.minecraft.world.level.block.Block
|
|||||||
import net.minecraftforge.registries.ForgeRegistries
|
import net.minecraftforge.registries.ForgeRegistries
|
||||||
import net.minecraftforge.registries.IForgeRegistry
|
import net.minecraftforge.registries.IForgeRegistry
|
||||||
|
|
||||||
|
// because doing it inline is ugly
|
||||||
|
fun <V : Any> Codec<V>.fromJson(value: JsonElement): V? {
|
||||||
|
return decode(JsonOps.INSTANCE, value).get().map({ left -> left.first }, { null })
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <V : Any> Codec<V>.fromJsonStrict(value: JsonElement): V {
|
||||||
|
return decode(JsonOps.INSTANCE, value).get().map({ left -> left.first }, { throw JsonSyntaxException("Error decoding element: ${it.message()}") })
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <V : Any> Codec<V>.toJson(value: V): JsonElement? {
|
||||||
|
return encode(value, JsonOps.INSTANCE, JsonOps.INSTANCE.empty()).get().map({ it }, { null })
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <V : Any> Codec<V>.toJsonStrict(value: V): JsonElement {
|
||||||
|
return encode(value, JsonOps.INSTANCE, JsonOps.INSTANCE.empty()).get().map({ it }, { throw RuntimeException("Error encoding element: ${it.message()}") })
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <V : Any> Codec<V>.fromNbt(value: Tag): V? {
|
||||||
|
return decode(NbtOps.INSTANCE, value).get().map({ left -> left.first }, { null })
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <V : Any> Codec<V>.fromNbtStrict(value: Tag): V {
|
||||||
|
return decode(NbtOps.INSTANCE, value).get().map({ left -> left.first }, { throw RuntimeException("Error decoding element: ${it.message()}") })
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <V : Any> Codec<V>.toNbt(value: V): Tag? {
|
||||||
|
return encode(value, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).get().map({ it }, { null })
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <V : Any> Codec<V>.toNbtStrict(value: V): Tag {
|
||||||
|
return encode(value, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).get().map({ it }, { throw RuntimeException("Error encoding element: ${it.message()}") })
|
||||||
|
}
|
||||||
|
|
||||||
// 1.19 being 1.19
|
// 1.19 being 1.19
|
||||||
fun TranslatableComponent(key: String, vararg values: Any): MutableComponent = MutableComponent.create(TranslatableContents(key, *values))
|
fun TranslatableComponent(key: String, vararg values: Any): MutableComponent = MutableComponent.create(TranslatableContents(key, *values))
|
||||||
fun TextComponent(value: String): MutableComponent = MutableComponent.create(LiteralContents(value))
|
fun TextComponent(value: String): MutableComponent = MutableComponent.create(LiteralContents(value))
|
||||||
|
@ -1,9 +1,19 @@
|
|||||||
package ru.dbotthepony.mc.otm.core.util
|
package ru.dbotthepony.mc.otm.core.util
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray
|
||||||
|
import com.google.gson.JsonElement
|
||||||
|
import com.google.gson.JsonNull
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.google.gson.JsonParseException
|
||||||
|
import com.google.gson.JsonPrimitive
|
||||||
|
import com.google.gson.JsonSyntaxException
|
||||||
|
import io.netty.buffer.ByteBufInputStream
|
||||||
|
import io.netty.buffer.ByteBufOutputStream
|
||||||
import io.netty.handler.codec.EncoderException
|
import io.netty.handler.codec.EncoderException
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.nbt.NbtAccounter
|
import net.minecraft.nbt.NbtAccounter
|
||||||
import net.minecraft.nbt.NbtIo
|
import net.minecraft.nbt.NbtIo
|
||||||
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
import net.minecraft.world.item.Item
|
import net.minecraft.world.item.Item
|
||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraftforge.registries.ForgeRegistries
|
import net.minecraftforge.registries.ForgeRegistries
|
||||||
@ -11,6 +21,7 @@ import net.minecraftforge.registries.ForgeRegistry
|
|||||||
import java.io.*
|
import java.io.*
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
// But seriously, Mojang, why would you need to derive from ByteBuf directly, when you can implement
|
// But seriously, Mojang, why would you need to derive from ByteBuf directly, when you can implement
|
||||||
// your own InputStream and OutputStream, since ByteBuf is meant to be operated on most time like a stream anyway?
|
// your own InputStream and OutputStream, since ByteBuf is meant to be operated on most time like a stream anyway?
|
||||||
@ -88,3 +99,137 @@ fun InputStream.readBigDecimal(): BigDecimal {
|
|||||||
return BigDecimal(BigInteger(bytes), scale)
|
return BigDecimal(BigInteger(bytes), scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const val TYPE_NULL = 0x01
|
||||||
|
private const val TYPE_DOUBLE = 0x02
|
||||||
|
private const val TYPE_BOOLEAN = 0x03
|
||||||
|
private const val TYPE_INT = 0x04
|
||||||
|
private const val TYPE_STRING = 0x05
|
||||||
|
private const val TYPE_ARRAY = 0x06
|
||||||
|
private const val TYPE_OBJECT = 0x07
|
||||||
|
|
||||||
|
private fun fixSignedInt(read: Long): Long {
|
||||||
|
val sign = read and 0x1L
|
||||||
|
@Suppress("name_shadowing")
|
||||||
|
val read = read ushr 1
|
||||||
|
|
||||||
|
if (sign == 1L) {
|
||||||
|
return -read - 1L
|
||||||
|
} else {
|
||||||
|
return read
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes binary json to stream in Starbound Object Notation format
|
||||||
|
*
|
||||||
|
* just copy pasted this code from my another project because i was lazy
|
||||||
|
*/
|
||||||
|
fun OutputStream.writeJson(element: JsonElement) {
|
||||||
|
if (element is JsonObject) {
|
||||||
|
write(TYPE_OBJECT)
|
||||||
|
writeVarIntLE(element.size())
|
||||||
|
|
||||||
|
for ((k, v) in element.entrySet()) {
|
||||||
|
writeBinaryString(k)
|
||||||
|
writeJson(v)
|
||||||
|
}
|
||||||
|
} else if (element is JsonArray) {
|
||||||
|
write(TYPE_ARRAY)
|
||||||
|
writeVarIntLE(element.size())
|
||||||
|
|
||||||
|
for (v in element) {
|
||||||
|
writeJson(v)
|
||||||
|
}
|
||||||
|
} else if (element is JsonPrimitive) {
|
||||||
|
if (element.isNumber) {
|
||||||
|
val num = element.asNumber
|
||||||
|
|
||||||
|
if (num is Int || num is Long) {
|
||||||
|
write(TYPE_INT)
|
||||||
|
var int = num.toLong()
|
||||||
|
|
||||||
|
if (int < 0) {
|
||||||
|
int = int.absoluteValue.shl(1).or(1)
|
||||||
|
} else {
|
||||||
|
int.shl(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
writeVarLongLE(int)
|
||||||
|
} else if (num is Float || num is Double) {
|
||||||
|
write(TYPE_DOUBLE)
|
||||||
|
writeDouble(num.toDouble())
|
||||||
|
} else {
|
||||||
|
throw IllegalArgumentException("Unknown number type: ${num::class.qualifiedName}")
|
||||||
|
}
|
||||||
|
} else if (element.isString) {
|
||||||
|
write(TYPE_STRING)
|
||||||
|
writeBinaryString(element.asString)
|
||||||
|
} else if (element.isBoolean) {
|
||||||
|
write(TYPE_BOOLEAN)
|
||||||
|
write(if (element.asBoolean) 1 else 0)
|
||||||
|
} else {
|
||||||
|
write(TYPE_NULL)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw IllegalArgumentException("Unknown element type: ${element::class.qualifiedName}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads binary json from stream in Starbound Object Notation format
|
||||||
|
*
|
||||||
|
* just copy pasted this code from my another project because i was lazy
|
||||||
|
*/
|
||||||
|
fun InputStream.readJson(): JsonElement {
|
||||||
|
return when (val id = read()) {
|
||||||
|
TYPE_NULL -> JsonNull.INSTANCE
|
||||||
|
TYPE_DOUBLE -> JsonPrimitive(readDouble())
|
||||||
|
TYPE_BOOLEAN -> JsonPrimitive(read() > 1)
|
||||||
|
TYPE_INT -> JsonPrimitive(fixSignedInt(readVarLongLE()))
|
||||||
|
TYPE_STRING -> JsonPrimitive(readBinaryString())
|
||||||
|
TYPE_ARRAY -> {
|
||||||
|
val values = readVarIntLE()
|
||||||
|
|
||||||
|
if (values == 0) return JsonArray()
|
||||||
|
if (values < 0) throw JsonSyntaxException("Tried to read json array with $values elements in it")
|
||||||
|
|
||||||
|
val build = JsonArray(values)
|
||||||
|
for (i in 0 until values) build.add(readJson())
|
||||||
|
return build
|
||||||
|
}
|
||||||
|
TYPE_OBJECT -> {
|
||||||
|
val values = readVarIntLE()
|
||||||
|
if (values == 0) return JsonObject()
|
||||||
|
if (values < 0) throw JsonSyntaxException("Tried to read json object with $values elements in it")
|
||||||
|
|
||||||
|
val build = JsonObject()
|
||||||
|
|
||||||
|
for (i in 0 until values) {
|
||||||
|
val key: String
|
||||||
|
|
||||||
|
try {
|
||||||
|
key = readBinaryString()
|
||||||
|
} catch(err: Throwable) {
|
||||||
|
throw JsonSyntaxException("Reading json object at $i", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
build.add(key, readJson())
|
||||||
|
} catch(err: Throwable) {
|
||||||
|
throw JsonSyntaxException("Reading json object at $i with name $key", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return build
|
||||||
|
}
|
||||||
|
else -> throw JsonParseException("Unknown element type $id")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun FriendlyByteBuf.readJson(): JsonElement {
|
||||||
|
return ByteBufInputStream(this).readJson()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun FriendlyByteBuf.writeJson(value: JsonElement) {
|
||||||
|
ByteBufOutputStream(this).writeJson(value)
|
||||||
|
}
|
||||||
|
@ -26,10 +26,20 @@ open class MatterySlot @JvmOverloads constructor(container: Container, index: In
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open class MachineOutputSlot @JvmOverloads constructor(container: Container, index: Int, x: Int = 0, y: Int = 0) : MatterySlot(container, index, x, y) {
|
open class MachineOutputSlot @JvmOverloads constructor(container: Container, index: Int, x: Int = 0, y: Int = 0, val onTake: () -> Unit = {}) : MatterySlot(container, index, x, y) {
|
||||||
override fun mayPlace(itemStack: ItemStack): Boolean {
|
override fun mayPlace(itemStack: ItemStack): Boolean {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onTake(pPlayer: Player, pStack: ItemStack) {
|
||||||
|
super.onTake(pPlayer, pStack)
|
||||||
|
this.onTake.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onQuickCraft(pStack: ItemStack, pAmount: Int) {
|
||||||
|
super.onQuickCraft(pStack, pAmount)
|
||||||
|
this.onTake.invoke()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open class BatterySlot @JvmOverloads constructor(container: Container, index: Int, x: Int = 0, y: Int = 0) : MatterySlot(container, index, x, y) {
|
open class BatterySlot @JvmOverloads constructor(container: Container, index: Int, x: Int = 0, y: Int = 0) : MatterySlot(container, index, x, y) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package ru.dbotthepony.mc.otm.menu.tech
|
package ru.dbotthepony.mc.otm.menu.tech
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
|
import net.minecraft.server.level.ServerPlayer
|
||||||
import net.minecraft.world.SimpleContainer
|
import net.minecraft.world.SimpleContainer
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import ru.dbotthepony.mc.otm.block.entity.tech.PlatePressBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.tech.PlatePressBlockEntity
|
||||||
@ -18,7 +19,7 @@ class PlatePressMenu @JvmOverloads constructor(
|
|||||||
val container = tile?.container ?: SimpleContainer(2)
|
val container = tile?.container ?: SimpleContainer(2)
|
||||||
|
|
||||||
val inputSlot = MatterySlot(container, PlatePressBlockEntity.SLOT_INPUT)
|
val inputSlot = MatterySlot(container, PlatePressBlockEntity.SLOT_INPUT)
|
||||||
val outputSlot = MachineOutputSlot(container, PlatePressBlockEntity.SLOT_OUTPUT)
|
val outputSlot = MachineOutputSlot(container, PlatePressBlockEntity.SLOT_OUTPUT) { tile?.popExperience(ply as ServerPlayer) }
|
||||||
|
|
||||||
override val storageSlots: List<MatterySlot> = ImmutableList.of(inputSlot, outputSlot)
|
override val storageSlots: List<MatterySlot> = ImmutableList.of(inputSlot, outputSlot)
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ import com.google.gson.JsonPrimitive
|
|||||||
import net.minecraft.core.NonNullList
|
import net.minecraft.core.NonNullList
|
||||||
import net.minecraft.network.FriendlyByteBuf
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
import net.minecraft.resources.ResourceLocation
|
import net.minecraft.resources.ResourceLocation
|
||||||
|
import net.minecraft.util.valueproviders.ConstantFloat
|
||||||
|
import net.minecraft.util.valueproviders.FloatProvider
|
||||||
import net.minecraft.world.Container
|
import net.minecraft.world.Container
|
||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraft.world.item.crafting.Ingredient
|
import net.minecraft.world.item.crafting.Ingredient
|
||||||
@ -16,16 +18,21 @@ import org.apache.logging.log4j.LogManager
|
|||||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||||
import ru.dbotthepony.mc.otm.block.entity.tech.PlatePressBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.tech.PlatePressBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.container.get
|
import ru.dbotthepony.mc.otm.container.get
|
||||||
|
import ru.dbotthepony.mc.otm.core.fromJsonStrict
|
||||||
import ru.dbotthepony.mc.otm.core.isActuallyEmpty
|
import ru.dbotthepony.mc.otm.core.isActuallyEmpty
|
||||||
import ru.dbotthepony.mc.otm.registry.MRecipes
|
import ru.dbotthepony.mc.otm.registry.MRecipes
|
||||||
import ru.dbotthepony.mc.otm.core.registryName
|
import ru.dbotthepony.mc.otm.core.registryName
|
||||||
|
import ru.dbotthepony.mc.otm.core.toJsonStrict
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.readJson
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.writeJson
|
||||||
|
|
||||||
class PlatePressRecipe(
|
class PlatePressRecipe(
|
||||||
private val id: ResourceLocation,
|
private val id: ResourceLocation,
|
||||||
val input: Ingredient,
|
val input: Ingredient,
|
||||||
val output: Ingredient,
|
val output: Ingredient,
|
||||||
val count: Int,
|
val count: Int,
|
||||||
val workTime: Int = 200
|
val workTime: Int = 200,
|
||||||
|
val experience: FloatProvider = ConstantFloat.ZERO
|
||||||
) : Recipe<Container> {
|
) : Recipe<Container> {
|
||||||
override fun matches(container: Container, p_44003_: Level): Boolean {
|
override fun matches(container: Container, p_44003_: Level): Boolean {
|
||||||
if (output.isActuallyEmpty || input.isActuallyEmpty)
|
if (output.isActuallyEmpty || input.isActuallyEmpty)
|
||||||
@ -103,11 +110,12 @@ object PlatePressRecipeFactory : RecipeSerializer<PlatePressRecipe> {
|
|||||||
|
|
||||||
val count = ((obj["result"] as JsonObject)["count"] as? JsonPrimitive)?.let { return@let try {it.asInt} catch(err: Throwable) {throw IllegalStateException("Invalid result.count")} } ?: 1
|
val count = ((obj["result"] as JsonObject)["count"] as? JsonPrimitive)?.let { return@let try {it.asInt} catch(err: Throwable) {throw IllegalStateException("Invalid result.count")} } ?: 1
|
||||||
|
|
||||||
return PlatePressRecipe(loc, input, result, count, workTime)
|
val experience = obj["experience"]?.let { FloatProvider.CODEC.fromJsonStrict(it) } ?: ConstantFloat.ZERO
|
||||||
|
return PlatePressRecipe(loc, input, result, count, workTime, experience)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun fromNetwork(loc: ResourceLocation, buff: FriendlyByteBuf): PlatePressRecipe {
|
override fun fromNetwork(loc: ResourceLocation, buff: FriendlyByteBuf): PlatePressRecipe {
|
||||||
return PlatePressRecipe(loc, Ingredient.fromNetwork(buff), Ingredient.fromNetwork(buff), buff.readInt(), buff.readInt())
|
return PlatePressRecipe(loc, Ingredient.fromNetwork(buff), Ingredient.fromNetwork(buff), buff.readInt(), buff.readInt(), FloatProvider.CODEC.fromJsonStrict(buff.readJson()))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toNetwork(buff: FriendlyByteBuf, recipe: PlatePressRecipe) {
|
override fun toNetwork(buff: FriendlyByteBuf, recipe: PlatePressRecipe) {
|
||||||
@ -115,5 +123,6 @@ object PlatePressRecipeFactory : RecipeSerializer<PlatePressRecipe> {
|
|||||||
recipe.output.toNetwork(buff)
|
recipe.output.toNetwork(buff)
|
||||||
buff.writeInt(recipe.count)
|
buff.writeInt(recipe.count)
|
||||||
buff.writeInt(recipe.workTime)
|
buff.writeInt(recipe.workTime)
|
||||||
|
buff.writeJson(FloatProvider.CODEC.toJsonStrict(recipe.experience))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user