mirror of
https://github.com/chylex/Hardcore-Ender-Expansion-2.git
synced 2025-04-11 03:15:44 +02:00
Fix several issues with Potions (typos in recipes, compatibility with old worlds)
This commit is contained in:
parent
005e467373
commit
bab34fd36f
src/main/java/chylex/hee
game/mechanics/potion/brewing
init
@ -2,6 +2,7 @@ package chylex.hee.game.mechanics.potion.brewing
|
||||
import chylex.hee.game.mechanics.potion.PotionPurity.PURITY
|
||||
import chylex.hee.game.mechanics.potion.brewing.PotionTypeInfo.Duration
|
||||
import chylex.hee.init.ModItems.DRAGON_SCALE
|
||||
import chylex.hee.system.util.floorToInt
|
||||
import net.minecraft.init.Items.BLAZE_POWDER
|
||||
import net.minecraft.init.Items.FERMENTED_SPIDER_EYE
|
||||
import net.minecraft.init.Items.FISH
|
||||
@ -35,27 +36,27 @@ import net.minecraft.potion.PotionUtils
|
||||
object PotionBrewing{
|
||||
val INFO = arrayOf(
|
||||
PotionTypeInfo(INSTANT_HEALTH, maxLevel = 2),
|
||||
PotionTypeInfo(FIRE_RESISTANCE, Duration(baseTicks = 3 min 20, stepTicks = 3 min 10, maxSteps = 4), maxLevel = 1),
|
||||
PotionTypeInfo(REGENERATION, Duration(baseTicks = 0 min 30, stepTicks = 0 min 30, maxSteps = 3), maxLevel = 3),
|
||||
PotionTypeInfo(STRENGTH, Duration(baseTicks = 2 min 30, stepTicks = 2 min 15, maxSteps = 4), maxLevel = 3),
|
||||
PotionTypeInfo(SPEED, Duration(baseTicks = 2 min 30, stepTicks = 2 min 15, maxSteps = 4), maxLevel = 3),
|
||||
PotionTypeInfo(NIGHT_VISION, Duration(baseTicks = 3 min 20, stepTicks = 3 min 10, maxSteps = 4), maxLevel = 1),
|
||||
PotionTypeInfo(WATER_BREATHING, Duration(baseTicks = 3 min 20, stepTicks = 3 min 10, maxSteps = 4), maxLevel = 1),
|
||||
PotionTypeInfo(JUMP_BOOST, Duration(baseTicks = 2 min 30, stepTicks = 2 min 15, maxSteps = 4), maxLevel = 3),
|
||||
PotionTypeInfo(POISON, Duration(baseTicks = 0 min 30, stepTicks = 0 min 30, maxSteps = 3), maxLevel = 2),
|
||||
// UPDATE PotionTypeInfo(TURTLE_MASTER, Duration(baseTicks = 0 min 20, stepTicks = 13 s 7, maxSteps = 3), maxLevel = 2),
|
||||
// UPDATE PotionTypeInfo(SLOW_FALLING, Duration(baseTicks = 1 min 15, stepTicks = 1 min 15, maxSteps = 3), maxLevel = 1),
|
||||
PotionTypeInfo(LEVITATION, Duration(baseTicks = 0 min 30, stepTicks = 0 min 30, maxSteps = 3), maxLevel = 2),
|
||||
PotionTypeInfo(PURITY, Duration(baseTicks = 2 min 30, stepTicks = 2 min 15, maxSteps = 4), maxLevel = 3),
|
||||
// TODO PotionTypeInfo(CORRUPTION, Duration(baseTicks = 0 min 20, stepTicks = 13 s 7, maxSteps = 3), maxLevel = 1),
|
||||
PotionTypeInfo(BLINDNESS, Duration(baseTicks = 0 min 20, stepTicks = 13 s 7, maxSteps = 3), maxLevel = 1),
|
||||
PotionTypeInfo(WEAKNESS, Duration(baseTicks = 1 min 15, stepTicks = 1 min 15, maxSteps = 3), maxLevel = 3),
|
||||
PotionTypeInfo(FIRE_RESISTANCE, Duration(baseTicks = 3 min 20, stepTicks = 3 min 10, maxSteps = 4), maxLevel = 1),
|
||||
PotionTypeInfo(REGENERATION, Duration(baseTicks = 0 min 30, stepTicks = 0 min 30, maxSteps = 3), maxLevel = 3),
|
||||
PotionTypeInfo(STRENGTH, Duration(baseTicks = 2 min 30, stepTicks = 2 min 15, maxSteps = 4), maxLevel = 3),
|
||||
PotionTypeInfo(SPEED, Duration(baseTicks = 2 min 30, stepTicks = 2 min 15, maxSteps = 4), maxLevel = 3),
|
||||
PotionTypeInfo(NIGHT_VISION, Duration(baseTicks = 3 min 20, stepTicks = 3 min 10, maxSteps = 4), maxLevel = 1),
|
||||
PotionTypeInfo(WATER_BREATHING, Duration(baseTicks = 3 min 20, stepTicks = 3 min 10, maxSteps = 4), maxLevel = 1),
|
||||
PotionTypeInfo(JUMP_BOOST, Duration(baseTicks = 2 min 30, stepTicks = 2 min 15, maxSteps = 4), maxLevel = 3),
|
||||
PotionTypeInfo(POISON, Duration(baseTicks = 0 min 30, stepTicks = 0 min 30, maxSteps = 3), maxLevel = 2),
|
||||
// PotionTypeInfo(TURTLE_MASTER, Duration(baseTicks = 0 min 20, stepTicks = 0 min 13.34, maxSteps = 3), maxLevel = 2), // UPDATE
|
||||
// PotionTypeInfo(SLOW_FALLING, Duration(baseTicks = 1 min 15, stepTicks = 1 min 15, maxSteps = 3), maxLevel = 1), // UPDATE
|
||||
PotionTypeInfo(LEVITATION, Duration(baseTicks = 0 min 30, stepTicks = 0 min 30, maxSteps = 3), maxLevel = 2),
|
||||
PotionTypeInfo(PURITY, Duration(baseTicks = 2 min 30, stepTicks = 2 min 15, maxSteps = 4), maxLevel = 3),
|
||||
// PotionTypeInfo(CORRUPTION, Duration(baseTicks = 0 min 20, stepTicks = 0 min 13.34, maxSteps = 3), maxLevel = 1), // TODO
|
||||
PotionTypeInfo(BLINDNESS, Duration(baseTicks = 0 min 20, stepTicks = 0 min 13.34, maxSteps = 3), maxLevel = 1),
|
||||
PotionTypeInfo(WEAKNESS, Duration(baseTicks = 1 min 15, stepTicks = 1 min 15, maxSteps = 3), maxLevel = 3),
|
||||
|
||||
PotionTypeInfo(INSTANT_DAMAGE, maxLevel = 2),
|
||||
PotionTypeInfo(SPEED, Duration(baseTicks = 1 min 15, stepTicks = 1 min 7 s 10, maxSteps = 4), maxLevel = 3),
|
||||
PotionTypeInfo(INVISIBILITY, Duration(baseTicks = 1 min 20, stepTicks = 1 min 16, maxSteps = 4), maxLevel = 1),
|
||||
// TODO PotionTypeInfo(BANISHMENT, Duration(baseTicks = 0 min 15, stepTicks = 10 s 0, maxSteps = 3), maxLevel = 1),
|
||||
PotionTypeInfo(GLOWING, Duration(baseTicks = 0 min 12, stepTicks = 8 s 0, maxSteps = 3), maxLevel = 1)
|
||||
PotionTypeInfo(SLOWNESS, Duration(baseTicks = 1 min 15, stepTicks = 1 min 7.5, maxSteps = 4), maxLevel = 3),
|
||||
PotionTypeInfo(INVISIBILITY, Duration(baseTicks = 1 min 20, stepTicks = 1 min 16, maxSteps = 4), maxLevel = 1),
|
||||
// PotionTypeInfo(BANISHMENT, Duration(baseTicks = 0 min 15, stepTicks = 0 min 10, maxSteps = 3), maxLevel = 1), // TODO
|
||||
PotionTypeInfo(GLOWING, Duration(baseTicks = 0 min 12, stepTicks = 0 min 8, maxSteps = 3), maxLevel = 1)
|
||||
).associateBy { it.potion }
|
||||
|
||||
// TODO register levitation type and other custom potions
|
||||
@ -115,7 +116,7 @@ object PotionBrewing{
|
||||
return ((this * 60) + seconds) * 20
|
||||
}
|
||||
|
||||
private infix fun Int.s(ticks: Int): Int{
|
||||
return (this * 20) + ticks
|
||||
private infix fun Int.min(seconds: Double): Int{
|
||||
return (((this * 60) + seconds) * 20).floorToInt()
|
||||
}
|
||||
}
|
||||
|
@ -42,15 +42,30 @@ object PotionItems{
|
||||
MobEffects.WEAKNESS to PotionTypes.WEAKNESS
|
||||
)
|
||||
|
||||
val VANILLA_TYPES
|
||||
private val TYPE_NO_EFFECT_OVERRIDES = mutableMapOf<PotionType, PotionType>()
|
||||
|
||||
val ALTERED_TYPES
|
||||
get() = TYPE_MAPPING.values
|
||||
|
||||
fun registerNoEffectOverride(original: PotionType, override: PotionType){
|
||||
TYPE_NO_EFFECT_OVERRIDES[original] = override
|
||||
}
|
||||
|
||||
fun findNoEffectOverride(type: PotionType): PotionType{
|
||||
return TYPE_NO_EFFECT_OVERRIDES[type] ?: type
|
||||
}
|
||||
|
||||
fun getBottle(item: Item, type: PotionType): ItemStack{
|
||||
return PotionUtils.addPotionToItemStack(ItemStack(item), type)
|
||||
}
|
||||
|
||||
fun getBottle(item: Item, potion: Potion): ItemStack{
|
||||
return getBottle(item, TYPE_MAPPING.getOrDefault(potion, PotionTypes.WATER))
|
||||
fun getBottle(item: Item, potion: Potion, withBaseEffect: Boolean): ItemStack{
|
||||
val type = TYPE_MAPPING.getOrDefault(potion, PotionTypes.WATER)
|
||||
|
||||
return if (withBaseEffect)
|
||||
getBottle(item, type)
|
||||
else
|
||||
getBottle(item, findNoEffectOverride(type))
|
||||
}
|
||||
|
||||
fun checkBottle(stack: ItemStack, type: PotionType): Boolean{
|
||||
|
@ -1,44 +1,61 @@
|
||||
package chylex.hee.game.mechanics.potion.brewing
|
||||
import chylex.hee.system.util.floorToInt
|
||||
import chylex.hee.system.util.getIntegerOrNull
|
||||
import chylex.hee.system.util.heeTag
|
||||
import chylex.hee.system.util.heeTagOrNull
|
||||
import chylex.hee.system.util.nbt
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.potion.Potion
|
||||
import net.minecraft.potion.PotionEffect
|
||||
import net.minecraft.potion.PotionUtils
|
||||
import kotlin.math.abs
|
||||
|
||||
class PotionTypeInfo(
|
||||
val potion: Potion,
|
||||
private val duration: Duration? = null,
|
||||
private val maxLevel: Int
|
||||
){
|
||||
fun getBasePotion(item: Item): ItemStack{
|
||||
return PotionUtils.appendEffects(PotionItems.getBottle(item, potion), listOf(PotionEffect(potion, duration?.baseTicks ?: 0, 0)))
|
||||
}
|
||||
val baseEffect
|
||||
get() = PotionEffect(potion, duration?.baseTicks ?: 0, 0)
|
||||
|
||||
val vanillaOverrideStrongEffect
|
||||
get() = PotionEffect(potion, duration?.getDuration(0, 1) ?: 0, 1)
|
||||
|
||||
val vanillaOverrideLongEffect
|
||||
get() = PotionEffect(potion, duration?.getDuration(1, 0) ?: 0, 0)
|
||||
|
||||
class Duration(val baseTicks: Int, val stepTicks: Int, val maxSteps: Int){
|
||||
fun calculate(steps: Int, amplifier: Int): Int{
|
||||
var ticks = baseTicks + (stepTicks * steps)
|
||||
private fun getBaseDuration(steps: Int): Int{
|
||||
return baseTicks + (stepTicks * steps)
|
||||
}
|
||||
|
||||
private fun mp(amplifier: Int): Double{
|
||||
return if (amplifier == 0)
|
||||
0.4
|
||||
else
|
||||
0.5
|
||||
}
|
||||
|
||||
fun getDuration(steps: Int, amplifier: Int): Int{
|
||||
var ticks = getBaseDuration(steps)
|
||||
|
||||
repeat(amplifier){
|
||||
val mp = if (it == 0)
|
||||
0.4
|
||||
else
|
||||
0.5
|
||||
|
||||
ticks = (ticks * mp).floorToInt()
|
||||
ticks = (ticks * mp(it)).floorToInt()
|
||||
}
|
||||
|
||||
return ticks
|
||||
}
|
||||
|
||||
fun getSteps(duration: Int, amplifier: Int): Int{
|
||||
var unrolled = duration.toDouble()
|
||||
|
||||
repeat(amplifier){
|
||||
unrolled /= mp(it)
|
||||
}
|
||||
|
||||
return (0..maxSteps).minBy { abs(getBaseDuration(it) - unrolled) } ?: 0
|
||||
}
|
||||
}
|
||||
|
||||
inner class Instance(private val stack: ItemStack, private val effect: PotionEffect){
|
||||
private val durationSteps
|
||||
get() = stack.heeTagOrNull?.getIntegerOrNull("DurationSteps") ?: 0
|
||||
private val durationSteps = duration?.getSteps(effect.duration, amplifier) ?: 0
|
||||
|
||||
private val amplifier
|
||||
get() = effect.amplifier
|
||||
@ -63,21 +80,26 @@ class PotionTypeInfo(
|
||||
val reversed = PotionBrewing.REVERSAL[potion] ?: return null
|
||||
val info = PotionBrewing.INFO[reversed] ?: return null
|
||||
|
||||
val baseItem = info.getBasePotion(stack.item)
|
||||
val baseEffect = PotionEffect(reversed, 0, 0, effect.isAmbient, effect.doesShowParticles())
|
||||
if (durationSteps == 0 && amplifier == 0){
|
||||
return PotionItems.getBottle(stack.item, potion, withBaseEffect = true)
|
||||
}
|
||||
|
||||
return info.Instance(baseItem, baseEffect).createNewEffect(durationSteps, baseEffect.amplifier)
|
||||
val newItem = PotionItems.getBottle(stack.item, potion, withBaseEffect = false)
|
||||
val newEffect = PotionEffect(reversed, 0, 0, effect.isAmbient, effect.doesShowParticles())
|
||||
|
||||
return info.Instance(newItem, newEffect).createNewEffect(durationSteps, newEffect.amplifier)
|
||||
}
|
||||
|
||||
private fun createNewEffect(durationSteps: Int, amplifier: Int): ItemStack{
|
||||
val newDuration = duration?.calculate(durationSteps, amplifier) ?: 0
|
||||
val newDuration = duration?.getDuration(durationSteps, amplifier) ?: 0
|
||||
val newEffect = PotionEffect(potion, newDuration, amplifier, effect.isAmbient, effect.doesShowParticles())
|
||||
val newStack = stack.copy()
|
||||
|
||||
newStack.heeTag.setInteger("DurationSteps", durationSteps)
|
||||
newStack.nbt.removeTag(PotionItems.CUSTOM_EFFECTS_TAG)
|
||||
|
||||
return PotionUtils.appendEffects(newStack, listOf(newEffect))
|
||||
return with(stack.copy()){
|
||||
nbt.removeTag(PotionItems.CUSTOM_EFFECTS_TAG)
|
||||
|
||||
PotionUtils.addPotionToItemStack(this, PotionItems.findNoEffectOverride(PotionUtils.getPotionFromItem(this)))
|
||||
PotionUtils.appendEffects(this, listOf(newEffect))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,9 @@ sealed class BrewBasicEffects(private val base: PotionType, private val registry
|
||||
|
||||
override fun brew(input: ItemStack, ingredient: ItemStack): ItemStack{
|
||||
val entry = registry.entries.first { matchesReagent(ingredient, it.key) }
|
||||
return PotionBrewing.INFO[entry.value]?.getBasePotion(input.item) ?: ItemStack.EMPTY
|
||||
val info = PotionBrewing.INFO[entry.value] ?: return ItemStack.EMPTY
|
||||
|
||||
return PotionItems.getBottle(input.item, info.potion, withBaseEffect = true)
|
||||
}
|
||||
|
||||
private fun matchesReagent(ingredient: ItemStack, key: Pair<Item, Int>): Boolean{
|
||||
|
@ -2,6 +2,7 @@ package chylex.hee.init
|
||||
import chylex.hee.HEE
|
||||
import chylex.hee.game.mechanics.potion.PotionLifeless
|
||||
import chylex.hee.game.mechanics.potion.PotionPurity
|
||||
import chylex.hee.game.mechanics.potion.brewing.PotionBrewing
|
||||
import chylex.hee.game.mechanics.potion.brewing.PotionItems
|
||||
import chylex.hee.game.mechanics.potion.brewing.recipes.BrewBasicEffects
|
||||
import chylex.hee.game.mechanics.potion.brewing.recipes.BrewUnalteredPotions
|
||||
@ -10,9 +11,9 @@ import chylex.hee.game.mechanics.potion.brewing.recipes.BrewWaterToMundane
|
||||
import chylex.hee.game.mechanics.potion.brewing.recipes.BrewWaterToThick
|
||||
import chylex.hee.game.mechanics.potion.brewing.recipes.ReinsertPotionItems
|
||||
import chylex.hee.system.Resource
|
||||
import chylex.hee.system.util.getIfExists
|
||||
import com.google.common.collect.ImmutableList
|
||||
import net.minecraft.potion.Potion
|
||||
import net.minecraft.potion.PotionEffect
|
||||
import net.minecraft.potion.PotionType
|
||||
import net.minecraftforge.common.brewing.BrewingRecipeRegistry
|
||||
import net.minecraftforge.common.brewing.IBrewingRecipe
|
||||
@ -25,13 +26,56 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
|
||||
object ModPotions{
|
||||
@JvmStatic
|
||||
@SubscribeEvent
|
||||
fun onRegister(e: RegistryEvent.Register<Potion>){
|
||||
fun onRegisterPotions(e: RegistryEvent.Register<Potion>){
|
||||
with(e.registry){
|
||||
register(PotionLifeless named "lifeless")
|
||||
register(PotionPurity named "purity")
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@SubscribeEvent
|
||||
fun onRegisterTypes(e: RegistryEvent.Register<PotionType>){
|
||||
with(e.registry){
|
||||
val alteredTypes = PotionItems.ALTERED_TYPES.map { it.registryName!!.path }.toSet()
|
||||
|
||||
for(type in this){
|
||||
val location = type.registryName!!
|
||||
val domain = location.namespace
|
||||
val path = location.path
|
||||
|
||||
if ((domain == Resource.Vanilla.domain || domain == Resource.Custom.domain) && alteredTypes.contains(path) && type.baseName == null && type.effects.isNotEmpty()){
|
||||
val info = PotionBrewing.INFO[type.effects[0].potion]
|
||||
|
||||
if (info != null){
|
||||
|
||||
// custom brewing system uses NBT to apply duration/level modifiers
|
||||
// to disable the original effect, each potion type is duplicated with no base effects
|
||||
|
||||
val override = PotionType(path) named "${path}_no_effect_override"
|
||||
register(override) // TODO the duplicates still show up in creative menu etc
|
||||
|
||||
// change base effects for vanilla potions to avoid breaking creative menu and compatibility w/ original items
|
||||
// register type overrides so that brewing recipes can convert them
|
||||
|
||||
type.effects = ImmutableList.of(info.baseEffect)
|
||||
PotionItems.registerNoEffectOverride(type, override)
|
||||
|
||||
getIfExists(Resource.Vanilla("strong_$path"))?.let {
|
||||
it.effects = ImmutableList.of(info.vanillaOverrideStrongEffect)
|
||||
PotionItems.registerNoEffectOverride(it, override)
|
||||
}
|
||||
|
||||
getIfExists(Resource.Vanilla("long_$path"))?.let {
|
||||
it.effects = ImmutableList.of(info.vanillaOverrideLongEffect)
|
||||
PotionItems.registerNoEffectOverride(it, override)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recipes
|
||||
|
||||
fun setupVanillaOverrides(){
|
||||
@ -53,19 +97,6 @@ object ModPotions{
|
||||
BrewUnalteredPotions
|
||||
))
|
||||
}
|
||||
|
||||
val vanillaTypes = PotionItems.VANILLA_TYPES.map { it.registryName!!.path }.toSet()
|
||||
val emptyEffects = ImmutableList.of<PotionEffect>()
|
||||
|
||||
for(type in PotionType.REGISTRY){
|
||||
val location = type.registryName!!
|
||||
|
||||
if (location.namespace == Resource.Vanilla.domain && (vanillaTypes.contains(location.path) || type.baseName?.let(vanillaTypes::contains) == true)){
|
||||
type.effects = emptyEffects // removes duplicate effects when using custom effects in NBT
|
||||
}
|
||||
|
||||
// TODO fix creative tab & tipped arrows, might be better to just ASM something
|
||||
}
|
||||
}
|
||||
|
||||
// Utilities
|
||||
@ -74,4 +105,8 @@ object ModPotions{
|
||||
setPotionName("effect.hee.$registryName")
|
||||
setRegistryName(Resource.Custom(registryName))
|
||||
}
|
||||
|
||||
private infix fun PotionType.named(registryName: String) = apply {
|
||||
setRegistryName(Resource.Custom(registryName))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user