Compare commits

...

17 Commits

Author SHA1 Message Date
305ddbd0d4
Merge branch 'player-improvements' into new-container-api 2025-03-14 12:14:36 +07:00
b42a503096
Merge branch '1.21' into new-container-api 2025-03-14 12:14:06 +07:00
5d8f2d5a4a
Add REGENERATE_ENERGY_EFFICIENCY_FOOD and REGENERATE_ENERGY_EFFICIENCY_SATURATION 2025-03-14 12:04:16 +07:00
e06928a4b5
Update mixin signature 2025-03-14 11:24:58 +07:00
d10b1b4ee1
Aeugh 2025-03-14 11:21:08 +07:00
922f94b9de
e 2025-03-14 11:02:08 +07:00
b23bda2f6a
Move android package to player package 2025-03-14 10:54:08 +07:00
c4d5ffefa5
Move all logic regarding food / regeneration to MatteryFoodData 2025-03-14 10:37:54 +07:00
a34b485e68
Base replacement for FoodData 2025-03-14 08:52:36 +07:00
c3b2681e89
Rename AndroidConfig to PlayerConfig 2025-03-12 20:57:57 +07:00
cfd6b101d8
Fix addEatEffect hook 2025-03-12 20:31:59 +07:00
0424dd1944
Rename mattery player reference in coremod 2025-03-12 19:34:26 +07:00
05a081d9cb
Move MatteryPlayer to player subpackage 2025-03-12 19:33:20 +07:00
b68b1d724a
Move IMatteryPlayer as well as shortcuts to player subpackage 2025-03-12 19:28:54 +07:00
4df51ce126
Add better random to recommended mods 2025-03-11 17:53:18 +07:00
a6ba428518
Remove custom random generators except for gjrand64 which is used for worldgen 2025-03-11 16:56:51 +07:00
5a016bef1b
Remove otmRandom 2025-03-11 16:55:55 +07:00
116 changed files with 743 additions and 835 deletions

View File

@ -11,6 +11,7 @@ Minecraft tech-oriented mod with science fiction style, about matter, and energy
* [Ferrite Core](https://www.curseforge.com/minecraft/mc-mods/ferritecore), reduces memory usage
* In case of Overdrive That Matters, ***greatly*** reduces JVM heap bloat caused by model data being duplicated
* Better Random
### Mods with special compatibility code

View File

@ -23,7 +23,7 @@ import net.neoforged.neoforge.common.data.DatapackBuiltinEntriesProvider
import net.neoforged.neoforge.data.event.GatherDataEvent
import net.neoforged.neoforge.registries.NeoForgeRegistries
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidResearchDataProvider
import ru.dbotthepony.mc.otm.player.android.AndroidResearchDataProvider
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.core.math.yRotationBlockstateNorth
import ru.dbotthepony.mc.otm.core.util.WriteOnce

View File

@ -4,9 +4,9 @@ import net.minecraft.tags.ItemTags
import net.minecraft.world.item.Items
import net.neoforged.neoforge.common.Tags
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidResearchDescriptions
import ru.dbotthepony.mc.otm.android.AndroidResearchResults
import ru.dbotthepony.mc.otm.android.AndroidResearchType
import ru.dbotthepony.mc.otm.player.android.AndroidResearchDescriptions
import ru.dbotthepony.mc.otm.player.android.AndroidResearchResults
import ru.dbotthepony.mc.otm.player.android.AndroidResearchType
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent

View File

@ -15,8 +15,8 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.Block
import net.neoforged.neoforge.common.data.LanguageProvider
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidFeatureType
import ru.dbotthepony.mc.otm.android.AndroidResearchType
import ru.dbotthepony.mc.otm.player.android.AndroidFeatureType
import ru.dbotthepony.mc.otm.player.android.AndroidResearchType
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.registry.objects.ColoredDecorativeBlock

View File

@ -19,7 +19,7 @@ import net.minecraft.world.level.block.Block
import net.neoforged.neoforge.common.Tags
import net.neoforged.neoforge.data.event.GatherDataEvent
import net.neoforged.neoforge.registries.NeoForgeRegistries
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.datagen.DataGen
import java.util.EnumMap

View File

@ -20,7 +20,7 @@ import net.minecraft.client.renderer.entity.player.PlayerRenderer;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.neoforge.client.event.RenderPlayerEvent;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.capability.IMatteryPlayer;
import ru.dbotthepony.mc.otm.player.IMatteryPlayer;
import javax.annotation.Nonnull;
import java.util.Set;

View File

@ -1,51 +0,0 @@
package ru.dbotthepony.mc.otm.mixin;
import net.minecraft.world.Difficulty;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.food.FoodData;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.dbotthepony.mc.otm.capability.IMatteryPlayer;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
@Mixin(FoodData.class)
public class FoodDataMixin {
@Shadow(remap = false)
private int lastFoodLevel;
@Shadow(remap = false)
private int tickTimer;
@Shadow(remap = false)
private int foodLevel;
@Shadow(remap = false)
private float exhaustionLevel;
@Inject(
method = "tick(Lnet/minecraft/world/entity/player/Player;)V",
at = @At("HEAD"),
remap = false,
cancellable = true
)
private void tick(Player player, CallbackInfo info) {
var it = ((IMatteryPlayer) player).getOtmPlayer();
if (it.isAndroid()) {
info.cancel();
// полностью подменяем логику если андроид
lastFoodLevel = foodLevel;
if (player.level().getDifficulty() == Difficulty.PEACEFUL) {
exhaustionLevel = 0f;
} else {
tickTimer = 0;
}
// не обновляем уровень истощения ибо он обнуляется логикой внутри MatteryPlayerCapability
// а так же не регенерируем
// ну и не получаем урон от "голодания"
}
}
}

View File

@ -1,19 +0,0 @@
package ru.dbotthepony.mc.otm.mixin;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.Level;
import net.neoforged.fml.ModList;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import ru.dbotthepony.mc.otm.core.IMatteryLevel;
import ru.dbotthepony.mc.otm.core.util.GJRAND64RandomSource;
@Mixin(Level.class)
public abstract class LevelMixin implements IMatteryLevel {
private final RandomSource otm_random = ModList.get().isLoaded("better_random") ? null : new GJRAND64RandomSource();
@Override
public @Nullable RandomSource getOtmRandom() {
return otm_random;
}
}

View File

@ -7,8 +7,7 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.dbotthepony.mc.otm.capability.IMatteryPlayer;
import ru.dbotthepony.mc.otm.core.IMatteryLevel;
import ru.dbotthepony.mc.otm.player.IMatteryPlayer;
import ru.dbotthepony.mc.otm.registry.game.MSoundEvents;
@Mixin(AbstractHurtingProjectile.class)
@ -25,7 +24,7 @@ public class MixinAbstractHurtingProjectile {
AbstractHurtingProjectile proj = (AbstractHurtingProjectile)(Object)this;
if (cap.isAndroid() && proj.getOwner() != entity) {
entity.level().playSound(entity, proj.blockPosition(), MSoundEvents.INSTANCE.getANDROID_PROJ_PARRY(), SoundSource.PLAYERS, 1.0f, 0.95f + ((IMatteryLevel) entity.level()).getOtmRandom().nextFloat() * 0.1f);
entity.level().playSound(entity, proj.blockPosition(), MSoundEvents.INSTANCE.getANDROID_PROJ_PARRY(), SoundSource.PLAYERS, 1.0f, 0.95f + entity.level().getRandom().nextFloat() * 0.1f);
}
}
}

View File

@ -17,8 +17,8 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import ru.dbotthepony.mc.otm.capability.IMatteryPlayer;
import ru.dbotthepony.mc.otm.capability.MatteryPlayer;
import ru.dbotthepony.mc.otm.player.IMatteryPlayer;
import ru.dbotthepony.mc.otm.player.MatteryPlayer;
import java.util.function.Predicate;

View File

@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.dbotthepony.mc.otm.capability.IMatteryPlayer;
import ru.dbotthepony.mc.otm.player.IMatteryPlayer;
import ru.dbotthepony.mc.otm.config.ServerConfig;
import ru.dbotthepony.mc.otm.core.util.ExperienceUtilsKt;
import ru.dbotthepony.mc.otm.registry.game.MItems;

View File

@ -6,7 +6,7 @@ import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import ru.dbotthepony.mc.otm.capability.MatteryPlayer;
import ru.dbotthepony.mc.otm.player.MatteryPlayer;
@Mixin(Minecraft.class)
public class MixinMinecraft {

View File

@ -3,8 +3,8 @@ package ru.dbotthepony.mc.otm.mixin;
import com.mojang.authlib.GameProfile;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.food.FoodData;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;
@ -12,15 +12,17 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import ru.dbotthepony.mc.otm.capability.IMatteryPlayer;
import ru.dbotthepony.mc.otm.capability.MatteryPlayer;
import ru.dbotthepony.mc.otm.player.IMatteryPlayer;
import ru.dbotthepony.mc.otm.player.MatteryFoodData;
import ru.dbotthepony.mc.otm.player.MatteryPlayer;
import java.util.Objects;
@Mixin(Player.class)
public class MixinPlayer implements IMatteryPlayer {
public abstract class MixinPlayer implements IMatteryPlayer {
private Player otmSelf() {
return (Player) (Object) this;
}
@ -87,4 +89,15 @@ public class MixinPlayer implements IMatteryPlayer {
private void readAdditionalSaveData(CompoundTag data, CallbackInfo ci) {
otmPlayer.deserializeNBT(data.getCompound("overdrive_that_matters_player"), otmSelf().registryAccess());
}
@Shadow
protected FoodData foodData;
@Inject(
method = "<init>",
at = @At("TAIL")
)
private void ctorMix(Level level, BlockPos pos, float yRot, GameProfile gameProfile, CallbackInfo info) {
foodData = new MatteryFoodData(otmSelf());
}
}

View File

@ -6,16 +6,15 @@ import net.neoforged.bus.api.EventPriority
import net.neoforged.fml.common.Mod
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent
import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent
import ru.dbotthepony.mc.otm.android.AndroidResearchDescription
import ru.dbotthepony.mc.otm.android.AndroidResearchDescriptions
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.android.AndroidResearchResult
import ru.dbotthepony.mc.otm.android.AndroidResearchResults
import ru.dbotthepony.mc.otm.android.feature.EnderTeleporterFeature
import ru.dbotthepony.mc.otm.player.android.AndroidResearchDescription
import ru.dbotthepony.mc.otm.player.android.AndroidResearchDescriptions
import ru.dbotthepony.mc.otm.player.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.player.android.AndroidResearchResult
import ru.dbotthepony.mc.otm.player.android.AndroidResearchResults
import ru.dbotthepony.mc.otm.player.android.feature.EnderTeleporterFeature
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.block.entity.decorative.DevChestBlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.drive.DrivePool
import ru.dbotthepony.mc.otm.client.AndroidAbilityKeyMapping
import ru.dbotthepony.mc.otm.client.AndroidMenuKeyMapping
@ -45,7 +44,7 @@ import ru.dbotthepony.mc.otm.compat.curios.isCuriosLoaded
import ru.dbotthepony.mc.otm.compat.curios.onCuriosSlotModifiersUpdated
import ru.dbotthepony.mc.otm.compat.vanilla.MatteryChestMenu
import ru.dbotthepony.mc.otm.compat.vanilla.VanillaMenuTypes
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.config.PlayerConfig
import ru.dbotthepony.mc.otm.config.CablesConfig
import ru.dbotthepony.mc.otm.config.ClientConfig
import ru.dbotthepony.mc.otm.config.ExopackConfig
@ -172,7 +171,7 @@ object OverdriveThatMatters {
ClientConfig.register(container)
ServerConfig.register(container)
CablesConfig.register(container)
AndroidConfig.register(container)
PlayerConfig.register(container)
ExopackConfig.register(container)
ItemsConfig.register(container)
MachinesConfig.register(container)

View File

@ -44,7 +44,7 @@ import ru.dbotthepony.mc.otm.core.math.getSphericalBlockPositions
import ru.dbotthepony.mc.otm.core.math.times
import ru.dbotthepony.mc.otm.core.nbt.map
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.random
import ru.dbotthepony.mc.otm.isClient
import ru.dbotthepony.mc.otm.matter.MatterManager
import ru.dbotthepony.mc.otm.registry.MDamageTypes
@ -271,7 +271,7 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mattery
}
// шанс 1% что черная дыра потеряет 0.1 MtU каждую секунду * силу гравитации дыры ^ -1
if (level.otmRandom.nextDouble() < 0.01 * 0.05 * (1 / gravitationStrength)) {
if (level.random.nextDouble() < 0.01 * 0.05 * (1 / gravitationStrength)) {
this.mass += HAWKING_MASS_LOSE_STEP
}

View File

@ -34,7 +34,7 @@ import ru.dbotthepony.mc.otm.core.math.times
import ru.dbotthepony.mc.otm.core.multiblock.BlockEntityTag
import ru.dbotthepony.mc.otm.core.multiblock.MultiblockStatus
import ru.dbotthepony.mc.otm.core.multiblock.shapedMultiblock
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.random
import ru.dbotthepony.mc.otm.core.util.InvalidableLazy
import ru.dbotthepony.mc.otm.menu.tech.BlackHoleGeneratorMenu
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
@ -86,8 +86,8 @@ class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
multiblock?.blockEntities(MatterHatchBlockEntity.INPUT_TAG)?.iterator()?.map { it.matter }?.toList() ?: listOf()
}
val energy = CombinedProfiledEnergyStorage(FlowDirection.NONE, energyTarget::value, { level?.otmRandom })
val matter = CombinedProfiledMatterStorage(FlowDirection.NONE, matterTarget::value, { level?.otmRandom })
val energy = CombinedProfiledEnergyStorage(FlowDirection.NONE, energyTarget::value, { level?.random })
val matter = CombinedProfiledMatterStorage(FlowDirection.NONE, matterTarget::value, { level?.random })
enum class Mode(val label: Component, val tooltip: Component) {
TARGET_MASS(TranslatableComponent("otm.gui.black_hole_generator.sustain.mode"), TranslatableComponent("otm.gui.black_hole_generator.sustain.desc")),

View File

@ -14,7 +14,7 @@ import ru.dbotthepony.mc.otm.core.collect.map
import ru.dbotthepony.mc.otm.core.collect.reduce
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.RelativeSide
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.random
import ru.dbotthepony.mc.otm.core.shuffle
import ru.dbotthepony.mc.otm.graph.GraphNodeList
import ru.dbotthepony.mc.otm.onceServer
@ -627,7 +627,7 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
}
fun receiveEnergy(howMuch: Decimal, simulate: Boolean, fromNode: EnergyCableBlockEntity.Node, fromSide: RelativeSide): Decimal {
livelyNodesList.shuffle(fromNode.blockEntity.level!!.otmRandom)
livelyNodesList.shuffle(fromNode.blockEntity.level!!.random)
val itr = livelyNodesList.iterator()
var received = Decimal.ZERO

View File

@ -34,7 +34,7 @@ import ru.dbotthepony.mc.otm.container.HandlerFilter
import ru.dbotthepony.mc.otm.container.slotted.FilteredContainerSlot
import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.random
import ru.dbotthepony.mc.otm.menu.decorative.CargoCrateMenu
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
import ru.dbotthepony.mc.otm.registry.game.MSoundEvents
@ -77,7 +77,7 @@ class CargoCrateBlockEntity(
if (interactingPlayers++ == 0 && level != null && !isRemoved && level.getBlockState(blockPos).block is CargoCrateBlock) {
level.setBlock(blockPos, blockState.setValue(CargoCrateBlock.IS_OPEN, true), Block.UPDATE_CLIENTS)
level.playSound(null, blockPos, MSoundEvents.CARGO_CRATE_OPEN, SoundSource.BLOCKS, 1f, 0.8f + level.otmRandom.nextFloat() * 0.2f)
level.playSound(null, blockPos, MSoundEvents.CARGO_CRATE_OPEN, SoundSource.BLOCKS, 1f, 0.8f + level.random.nextFloat() * 0.2f)
level.gameEvent(GameEvent.CONTAINER_OPEN, blockPos, GameEvent.Context.of(blockState))
}
}

View File

@ -28,7 +28,7 @@ import ru.dbotthepony.mc.otm.container.slotted.ContainerSlot
import ru.dbotthepony.mc.otm.container.slotted.FilteredContainerSlot
import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.random
import ru.dbotthepony.mc.otm.data.codec.DecimalCodec
import ru.dbotthepony.mc.otm.data.codec.minRange
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
@ -131,7 +131,7 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
return JobContainer.success(
DecomposerJob(
(level?.otmRandom?.nextDouble() ?: 1.0) <= 0.2 * upgrades.failureMultiplier,
(level?.random?.nextDouble() ?: 1.0) <= 0.2 * upgrades.failureMultiplier,
matter.matter,
matter.complexity * MachinesConfig.MATTER_DECOMPOSER.workTimeMultiplier
)

View File

@ -29,7 +29,7 @@ import ru.dbotthepony.mc.otm.container.UpgradeContainer
import ru.dbotthepony.mc.otm.container.slotted.FilteredContainerSlot
import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.random
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
import ru.dbotthepony.mc.otm.matter.IMatterValue
@ -263,7 +263,7 @@ class MatterReconstructorBlockEntity(blockPos: BlockPos, blockState: BlockState)
return
}
if (failureChance * upgrades.failureMultiplier <= 0.0 || level!!.otmRandom.nextDouble() >= failureChance * upgrades.failureMultiplier)
if (failureChance * upgrades.failureMultiplier <= 0.0 || level!!.random.nextDouble() >= failureChance * upgrades.failureMultiplier)
repairProgress += progressPerTick
energy.extractEnergy(energyConsumption * (progressPerTick / thisProgressPerTick), false)

View File

@ -24,7 +24,7 @@ import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.container.slotted.ContainerSlot
import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.random
import ru.dbotthepony.mc.otm.graph.matter.MatterGraph
import ru.dbotthepony.mc.otm.item.matter.MatterDustItem
import ru.dbotthepony.mc.otm.menu.matter.MatterRecyclerMenu
@ -117,7 +117,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma
stack.shrink(1)
container.setChanged(0)
val actualMatter = dustMatter.matter * (0.4 + level!!.otmRandom.nextDouble() * 0.6)
val actualMatter = dustMatter.matter * (0.4 + level!!.random.nextDouble() * 0.6)
return JobContainer.success(
RecyclerJob(

View File

@ -30,7 +30,7 @@ import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.slotted.AutomationFilters
import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.random
import ru.dbotthepony.mc.otm.data.codec.DecimalCodec
import ru.dbotthepony.mc.otm.data.codec.minRange
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
@ -186,7 +186,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
task = allocation.task.id,
matterValue = matter.matter,
pattern = Optional.ofNullable(allocation.pattern),
asDust = (level?.otmRandom?.nextDouble() ?: 1.0) * upgrades.failureMultiplier > (allocation.pattern?.researchPercent ?: 2.0),
asDust = (level?.random?.nextDouble() ?: 1.0) * upgrades.failureMultiplier > (allocation.pattern?.researchPercent ?: 2.0),
ticks = ticks,
))
}

View File

@ -23,7 +23,7 @@ import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.IGUIRenderable
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
import ru.dbotthepony.mc.otm.client.render.Widgets8

View File

@ -35,7 +35,6 @@ import ru.dbotthepony.mc.otm.container.slotted.FilteredContainerSlot
import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer
import ru.dbotthepony.mc.otm.core.SimpleCache
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.util.ItemStackKey
import ru.dbotthepony.mc.otm.core.util.asKey
import ru.dbotthepony.mc.otm.menu.tech.PoweredFurnaceMenu
@ -180,7 +179,7 @@ sealed class AbstractPoweredFurnaceBlockEntity<P : AbstractCookingRecipe, S : Ma
recipe.getResultItem(level.registryAccess()).copyWithCount(toProcess),
recipe.workTime * config.workTimeMultiplier,
config.energyConsumption * toProcess,
experience = recipe.experience.sample(level.otmRandom) * toProcess))
experience = recipe.experience.sample(level.random) * toProcess))
}
}

View File

@ -14,10 +14,9 @@ import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.ProxiedEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.core.getEntitiesInEllipsoid
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.shuffle
import ru.dbotthepony.mc.otm.menu.tech.AndroidChargerMenu
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
@ -58,7 +57,7 @@ class AndroidChargerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma
val ents = level.getEntitiesInEllipsoid(blockPos.center, Vec3(MachinesConfig.AndroidCharger.RADIUS_WIDTH, MachinesConfig.AndroidCharger.RADIUS_HEIGHT, MachinesConfig.AndroidCharger.RADIUS_WIDTH)) { it is Player }
ents.shuffle(level.otmRandom)
ents.shuffle(level.random)
for ((ent) in ents) {
val ply = (ent as Player).matteryPlayer

View File

@ -13,11 +13,10 @@ import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.capability.moveEnergy
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.shuffle
import ru.dbotthepony.mc.otm.core.util.countingLazy
import ru.dbotthepony.mc.otm.menu.tech.AndroidStationMenu
@ -90,7 +89,7 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Ma
val y = blockPos.y.toDouble()
val z = blockPos.z.toDouble()
for (ent in level.getEntitiesOfClass(ServerPlayer::class.java, AABB(x, y, z, x + 1.0, y + 2.0, z + 1.0)).shuffle(level.otmRandom)) {
for (ent in level.getEntitiesOfClass(ServerPlayer::class.java, AABB(x, y, z, x + 1.0, y + 2.0, z + 1.0)).shuffle(level.random)) {
if (ent.matteryPlayer.isAndroid)
moveEnergy(energy, ent.matteryPlayer.androidEnergy, amount = energy.batteryLevel, simulate = false, ignoreFlowRestrictions = true)
}

View File

@ -26,7 +26,7 @@ import ru.dbotthepony.mc.otm.container.slotted.FilteredContainerSlot
import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.random
import ru.dbotthepony.mc.otm.core.shuffle
import ru.dbotthepony.mc.otm.menu.tech.BatteryBankMenu
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
@ -72,7 +72,7 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
if (!howMuch.isPositive)
return Decimal.ZERO
containerSlotIndices.shuffle(level!!.otmRandom)
containerSlotIndices.shuffle(level!!.random)
var summ = Decimal.ZERO
var remaining = howMuch

View File

@ -26,7 +26,7 @@ import ru.dbotthepony.mc.otm.core.math.RelativeSide
import ru.dbotthepony.mc.otm.core.multiblock.BlockEntityTag
import ru.dbotthepony.mc.otm.core.multiblock.IMultiblockAccess
import ru.dbotthepony.mc.otm.core.multiblock.IMultiblockListener
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.random
import ru.dbotthepony.mc.otm.core.util.InvalidableLazy
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
@ -45,7 +45,7 @@ class EnergyInterfaceBlockEntity(
multiblocks.keys.iterator().flatMap { it.blockEntities(TARGET).iterator() }.map { it.energyInterfaceTarget }.toList()
}
val energy = CombinedProfiledEnergyStorage(FlowDirection.input(isInput), targets::value, { level?.otmRandom })
val energy = CombinedProfiledEnergyStorage(FlowDirection.input(isInput), targets::value, { level?.random })
override fun onAddedToMultiblock(multiblock: IMultiblockAccess) {
check(!isRemoved) { "Block was removed" }

View File

@ -32,7 +32,7 @@ import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer
import ru.dbotthepony.mc.otm.core.getEntitiesInEllipsoid
import ru.dbotthepony.mc.otm.core.lookupOrThrow
import ru.dbotthepony.mc.otm.core.math.Vector
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.random
import ru.dbotthepony.mc.otm.core.util.countingLazy
import ru.dbotthepony.mc.otm.item.consumables.EssenceCapsuleItem
import ru.dbotthepony.mc.otm.item.EssenceServoItem
@ -183,7 +183,7 @@ class EssenceStorageBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma
val diff = dmgPerExp - repairPoints.toFloat()
if (diff > 0f) {
repairPoints += if ((level?.otmRandom?.nextFloat() ?: 1f) <= diff) 1 else 0
repairPoints += if ((level?.random?.nextFloat() ?: 1f) <= diff) 1 else 0
}
experienceStored -= 1
@ -212,7 +212,7 @@ class EssenceStorageBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma
level!!.playSound(null, ent.x, ent.y, ent.z,
SoundEvents.EXPERIENCE_ORB_PICKUP, SoundSource.BLOCKS,
0.1F, 0.5F + level!!.otmRandom.nextFloat() * 0.25F
0.1F, 0.5F + level!!.random.nextFloat() * 0.25F
)
}

View File

@ -28,7 +28,6 @@ import ru.dbotthepony.mc.otm.core.SimpleCache
import ru.dbotthepony.mc.otm.core.collect.any
import ru.dbotthepony.mc.otm.core.collect.filter
import ru.dbotthepony.mc.otm.core.collect.maybe
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.util.ItemStackKey
import ru.dbotthepony.mc.otm.core.util.asKey
import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu
@ -120,7 +119,7 @@ class PlatePressBlockEntity(
recipe.getResultItem(level.registryAccess()).copyWithCount(toProcess),
recipe.workTime * MachinesConfig.PLATE_PRESS.workTimeMultiplier,
MachinesConfig.PLATE_PRESS.energyConsumption * toProcess,
experience = recipe.experience.sample(level.otmRandom) * toProcess))
experience = recipe.experience.sample(level.random) * toProcess))
}
override fun tick() {

View File

@ -20,7 +20,7 @@ import ru.dbotthepony.mc.otm.block.MatteryBlock
import ru.dbotthepony.mc.otm.block.addSimpleDescription
import ru.dbotthepony.mc.otm.block.entity.tech.AndroidStationBlockEntity
import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
import ru.dbotthepony.mc.otm.shapes.BlockShapes

View File

@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.capability
import com.google.common.collect.Streams
import net.minecraft.ChatFormatting
import net.minecraft.network.chat.Component
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.neoforged.neoforge.capabilities.Capabilities
@ -34,13 +33,11 @@ import ru.dbotthepony.mc.otm.core.collect.map
import ru.dbotthepony.mc.otm.core.isNotEmpty
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.util.formatFluidLevel
import ru.dbotthepony.mc.otm.player.matteryPlayer
import java.util.stream.Stream
private val LOGGER = LogManager.getLogger()
val Player.matteryPlayer: MatteryPlayer get() = (this as IMatteryPlayer).otmPlayer
val LivingEntity.matteryPlayer: MatteryPlayer? get() = (this as? IMatteryPlayer)?.otmPlayer
/**
* Does a checked energy receive, calls [IMatteryEnergyStorage.receiveEnergyChecked] if possible
*/

View File

@ -8,8 +8,8 @@ import net.neoforged.neoforge.client.event.RenderLevelStageEvent
import net.neoforged.neoforge.client.settings.KeyConflictContext
import net.neoforged.neoforge.network.PacketDistributor
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidActiveFeature
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.android.AndroidActiveFeature
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.Widgets18
import ru.dbotthepony.mc.otm.client.render.is3DContext

View File

@ -11,12 +11,11 @@ import net.neoforged.neoforge.client.event.RenderGuiEvent
import net.neoforged.neoforge.client.settings.KeyConflictContext
import net.neoforged.neoforge.network.PacketDistributor
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidFeature
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.android.AndroidFeature
import ru.dbotthepony.mc.otm.player.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.RenderGravity
import ru.dbotthepony.mc.otm.client.render.drawArc
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.angleDifference
import ru.dbotthepony.mc.otm.core.math.normalizeAngle

View File

@ -18,9 +18,9 @@ import net.neoforged.neoforge.client.event.ScreenEvent
import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent
import net.neoforged.neoforge.network.PacketDistributor
import ru.dbotthepony.mc.otm.config.ClientConfig
import ru.dbotthepony.mc.otm.android.feature.JumpBoostFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.android.feature.JumpBoostFeature
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
import ru.dbotthepony.mc.otm.client.render.Widgets18
import ru.dbotthepony.mc.otm.client.screen.ExopackInventoryScreen

View File

@ -23,10 +23,10 @@ import net.neoforged.neoforge.client.event.RenderGuiLayerEvent
import net.neoforged.neoforge.client.event.ScreenEvent
import net.neoforged.neoforge.client.gui.VanillaGuiLayers
import net.neoforged.neoforge.common.ItemAbilities
import ru.dbotthepony.mc.otm.android.feature.NanobotsArmorFeature
import ru.dbotthepony.mc.otm.player.android.feature.NanobotsArmorFeature
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.*
import ru.dbotthepony.mc.otm.client.render.sprites.MatteryAtlas
import ru.dbotthepony.mc.otm.client.render.sprites.MatterySprite

View File

@ -11,8 +11,8 @@ import net.minecraft.client.renderer.GameRenderer
import net.minecraft.world.level.levelgen.XoroshiroRandomSource
import net.minecraft.world.level.material.FogType
import org.joml.Matrix4f
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.math.linearInterpolation
import ru.dbotthepony.mc.otm.milliTime

View File

@ -7,7 +7,7 @@ import com.mojang.blaze3d.vertex.VertexFormat
import net.minecraft.client.renderer.GameRenderer
import net.neoforged.neoforge.client.event.RenderLevelStageEvent
import org.lwjgl.opengl.GL11.GL_LESS
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.config.PlayerConfig
import ru.dbotthepony.mc.otm.core.math.Vector
import ru.dbotthepony.mc.otm.core.math.component1
import ru.dbotthepony.mc.otm.core.math.component2
@ -74,6 +74,6 @@ object ShockwaveRenderer {
}
fun handle(packet: ShockwaveEffectPacket) {
State(packet.pos, AndroidConfig.Shockwave.RADIUS_HORIZONTAL.toFloat())
State(packet.pos, PlayerConfig.Shockwave.RADIUS_HORIZONTAL.toFloat())
}
}

View File

@ -15,7 +15,7 @@ import org.lwjgl.opengl.GL30
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.tech.GravitationStabilizerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.ShiftPressedCond
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.render.*

View File

@ -14,7 +14,7 @@ import net.minecraft.world.item.ItemStack
import net.neoforged.neoforge.client.event.ContainerScreenEvent
import net.neoforged.neoforge.common.NeoForge
import org.lwjgl.opengl.GL11
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.moveMousePosScaled
import ru.dbotthepony.mc.otm.client.render.WidgetLocation

View File

@ -6,8 +6,8 @@ import net.minecraft.client.gui.screens.inventory.InventoryScreen
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.neoforged.neoforge.network.PacketDistributor
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.Widgets8
import ru.dbotthepony.mc.otm.client.render.sprites.sprite

View File

@ -11,11 +11,10 @@ import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.item.ItemStack
import net.neoforged.neoforge.network.PacketDistributor
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.android.AndroidResearch
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.android.AndroidResearchType
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.player.android.AndroidResearch
import ru.dbotthepony.mc.otm.player.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.player.android.AndroidResearchType
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.client.CursorType
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.minecraft
@ -33,9 +32,8 @@ import ru.dbotthepony.mc.otm.client.screen.panels.util.DraggableCanvasPanel
import ru.dbotthepony.mc.otm.client.screen.widget.WideProfiledPowerGaugePanel
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.screen.panels.button.BooleanButtonPanel
import ru.dbotthepony.mc.otm.core.RandomSource2Generator
import ru.dbotthepony.mc.otm.menu.tech.AndroidStationMenu
import ru.dbotthepony.mc.otm.network.AndroidResearchRequestPacket
import java.util.*

View File

@ -12,7 +12,7 @@ import net.neoforged.fml.ModList
import net.neoforged.fml.loading.FMLEnvironment
import net.neoforged.neoforge.network.PacketDistributor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.sprites.MatterySprite
import ru.dbotthepony.mc.otm.client.render.sprites.sprite

View File

@ -18,8 +18,8 @@ import net.minecraft.world.item.Items
import net.neoforged.neoforge.network.handling.IPayloadContext
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.MatteryMenuSlot

View File

@ -0,0 +1,9 @@
package ru.dbotthepony.mc.otm.config
interface IFoodRegenerationValues {
val foodLimit: Int
val requiresSaturation: Boolean
val ticks: Int
val regenerationSlowdown: Boolean
val upperSlowdownBound: Double
}

View File

@ -4,16 +4,31 @@ import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.defineDecimal
object AndroidConfig : AbstractConfig("androids") {
object PlayerConfig : AbstractConfig("player") {
init {
builder.push("Android")
}
val REGENERATE_ENERGY: Boolean by builder
.comment("If (technically) hunger is above threshold, it turns into energy")
.comment("This setting controls whenever to regenerate small amount of energy while eating as Android")
.comment("And also whenever to regenerate energy while in peaceful")
.comment("If this is disabled, any (technically) excess hunger will be nullified, unless playing on peaceful difficulty.")
.define("REGENERATE_ENERGY", true)
val REGENERATE_ENERGY_EFFICIENCY_FOOD: Double by builder
.comment("How much % of food points to convert to energy")
.defineInRange("REGENERATE_ENERGY_EFFICIENCY_FOOD", 0.75, 0.0)
val REGENERATE_ENERGY_EFFICIENCY_SATURATION: Double by builder
.comment("How much % of food saturation points to convert to energy")
.defineInRange("REGENERATE_ENERGY_EFFICIENCY_SATURATION", 0.4, 0.0)
val REGENERATE_ENERGY_IN_PEACEFUL: Boolean by builder
.comment("Regenerate energy while in peaceful")
.comment("This is disabled by default because this is easily exploitable")
.define("REGENERATE_ENERGY_IN_PEACEFUL", false)
val TIME_BETWEEN_NATURAL_REGENERATION: Int by builder
.comment("Time in ticks between natural health regeneration ticks")
.comment("Time in ticks between natural health regeneration ticks for Android")
.comment("Default value is meant to be one of downsides of being an android,")
.comment("so please, don't blindly buff it, players have ability to research into Nanobots Regeneration,")
.comment("which provide superior regeneration on average than human players.")
@ -24,6 +39,10 @@ object AndroidConfig : AbstractConfig("androids") {
.comment("for android players, since 'hunger' (for compatibility) is managed by mod in such case")
.defineInRange("TIME_BETWEEN_NATURAL_REGENERATION", 120, 0, Int.MAX_VALUE)
init {
builder.pop()
}
object NanobotsRegeneration {
init {
builder.push("NanobotsRegeneration")
@ -148,4 +167,103 @@ object AndroidConfig : AbstractConfig("androids") {
Magnet
Shockwave
}
object Food {
init {
builder
.comment("Food related tweaks")
.comment("Since OTM overrides FoodData logic (to make room for Android logic)")
.comment("these settings are provided for tweaking FoodData behavior")
.push("Food")
}
val SOFT_FOOD_LIMIT: Int by builder
.comment("Soft food points limit, which dictate upper bound where player is considered 'hungry',")
.comment("e.g. they can eat food which is not marked as 'can always eat'")
.defineInRange("SOFT_FOOD_LIMIT", 20, 0)
val HARD_FOOD_LIMIT: Int by builder
.comment("Hard food points limit, which dictate upper bound of food points,")
.comment("e.g. hunger can not go above this value")
.comment("This is extremely buffed in OTM by default to remove annoyance regarding consuming foodstuffs")
.comment("when you are running low on food, so you can eat high-quality food without fear")
.comment("that food points will go to waste (especially when you need to regenerate lots of HP)")
.defineInRange("HARD_FOOD_LIMIT", 40, 1)
val OVERSATURATION_LIMIT: Double by builder
.comment("Controls how much 'saturation' can be stored above hunger level.")
.comment("Negative values will decrease maximum saturation achievable.")
.defineInRange("OVERSATURATION_LIMIT", 0.0, -Float.MAX_VALUE.toDouble() + 1.0, Float.MAX_VALUE.toDouble() - 1.0)
val EXHAUSTION_LIMIT: Double by builder
.comment("Controls technical aspect how much 'exhaustion' player can accumulate")
.comment("This should not be confused with how much 'exhaustion' is considered as 1 hunger point")
.comment("Usually, this should not be changed, since it is a very technical detail;")
.comment("but if you have a mod installed which easily hits this limit (and somehow hunger system can't keep up,)")
.comment("e.g. it pushes exhaustion over its limit in one call), you can increase this value")
.defineInRange("EXHAUSTION_LIMIT", 40.0, 4.0, Float.MAX_VALUE.toDouble() - 1.0)
private fun defineRegeneration(
threshold: Int,
requiresSaturation: Boolean,
ticks: Int,
): IFoodRegenerationValues {
return object : IFoodRegenerationValues {
override val foodLimit: Int by builder
.defineInRange("FOOD_THRESHOLD", threshold, 1)
override val requiresSaturation: Boolean by builder
.define("REQUIRES_SATURATION", requiresSaturation)
override val ticks: Int by builder
.defineInRange("TICKS", ticks, 0)
override val regenerationSlowdown: Boolean by builder
.comment("Slowdown regeneration based on remaining saturation (given REQUIRES_SATURATION is true)")
.comment("This replicates vanilla behavior where fast regeneration speed linearly slowdowns the moment")
.comment("saturation falls below 6 hunger points (configurable through SATURATION_SLOWDOWN_BOUND)")
.comment("This is disabled in OTM by default to buff humans compared to androids when it comes to regeneration")
.define("SATURATION_SLOWDOWN", false)
override val upperSlowdownBound: Double by builder
.defineInRange("SATURATION_SLOWDOWN_BOUND", 6.0, 1.0, Float.MAX_VALUE - 1.0)
}
}
val FAST_REGEN: IFoodRegenerationValues
val SLOW_REGEN: IFoodRegenerationValues
init {
builder.push("FAST_REGENERATION")
FAST_REGEN = defineRegeneration(20, true, 10)
builder.pop()
builder.push("SLOW_REGENERATION")
SLOW_REGEN = defineRegeneration(18, false, 80)
builder.pop()
}
val ENABLE_STARVATION: Boolean by builder
.define("ENABLE_STARVATION", true)
val STARVATION_TICKS: Int by builder
.defineInRange("STARVATION_TICKS", 80, 1)
val STARVATION_HEALTH_LIMIT_EASY: Double by builder
.defineInRange("STARVATION_HEALTH_LIMIT_EASY", 10.0, 0.0)
val STARVATION_HEALTH_LIMIT_NORMAL: Double by builder
.defineInRange("STARVATION_HEALTH_LIMIT_NORMAL", 1.0, 0.0)
val STARVATION_HEALTH_LIMIT_HARD: Double by builder
.defineInRange("STARVATION_HEALTH_LIMIT_HARD", 0.0, 0.0)
init {
builder.pop()
}
}
init {
Food
}
}

View File

@ -1,17 +0,0 @@
package ru.dbotthepony.mc.otm.core
import net.minecraft.util.RandomSource
import net.minecraft.world.level.Level
import net.neoforged.fml.ModList
interface IMatteryLevel {
/**
* OTM provided [RandomSource], which has better statistical parameters
*
* Original Minecraft use LCG, which may show bad behavior when repeatedly sampled *a lot*,
* which is what [Level]'s random is used for. OTM provided PRNG should behave better in this scenario.
*/
val otmRandom: RandomSource?
}
val Level.otmRandom: RandomSource get() = (this as IMatteryLevel).otmRandom ?: random

View File

@ -1,117 +0,0 @@
package ru.dbotthepony.mc.otm.core.util
import net.minecraft.util.Mth
import net.minecraft.util.RandomSource
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian
import net.minecraft.world.level.levelgen.PositionalRandomFactory
import net.minecraft.world.level.levelgen.RandomSupport
import ru.dbotthepony.kommons.random.PCG32Random
import java.lang.StringBuilder
import java.util.random.RandomGenerator
/**
* Random number generator with insane period of at least 2^511
*/
class CMWCRandom(seed: Long = RandomSupport.generateUniqueSeed()) : RandomGenerator, RandomSource {
private val state = IntArray(CMWC_STATE_SIZE)
private var carry = 0
private var stateIndex = 0
private val gaussian = MarsagliaPolarGaussian(this)
init {
setSeed(seed)
}
override fun setSeed(seed: Long) {
val rng = PCG32Random(seed)
// init state with regular LCG produced values
for (i in 1 until state.size) {
state[i] = rng.nextInt()
}
do {
carry = rng.nextInt()
} while(carry !in 0 until CMWC_CARRY_MAX)
stateIndex = state.size - 1
gaussian.reset()
}
override fun nextInt(): Int {
stateIndex = (stateIndex + 1).and(CMWC_STATE_SIZE - 1)
val t = 18782L * state[stateIndex] + carry
carry = t.ushr(32).toInt()
var x = t.toInt() + carry
if (x < carry) {
x++
carry++
}
state[stateIndex] = 0xfffffffe.toInt() - x
return state[stateIndex]
}
override fun nextLong(): Long {
val a = nextInt().toLong() and 0xFFFFFFFFL
val b = nextInt().toLong() and 0xFFFFFFFFL
return a.shl(32) or b
}
override fun nextInt(bound: Int): Int {
return super<RandomGenerator>.nextInt(bound)
}
override fun nextInt(origin: Int, bound: Int): Int {
return super<RandomGenerator>.nextInt(origin, bound)
}
override fun nextBoolean(): Boolean {
return super.nextBoolean()
}
override fun nextFloat(): Float {
return super.nextFloat()
}
override fun nextDouble(): Double {
return super.nextDouble()
}
override fun nextGaussian(): Double {
return gaussian.nextGaussian()
}
override fun fork(): RandomSource {
return CMWCRandom(nextLong())
}
override fun forkPositional(): PositionalRandomFactory {
return Positional(nextLong())
}
class Positional(private val seed: Long) : PositionalRandomFactory {
override fun at(x: Int, y: Int, z: Int): RandomSource {
return CMWCRandom(Mth.getSeed(x, y, z).xor(seed))
}
override fun fromHashOf(name: String): RandomSource {
return CMWCRandom(name.hashCode().toLong().xor(seed))
}
override fun fromSeed(seed: Long): RandomSource {
return CMWCRandom(seed)
}
override fun parityConfigString(builder: StringBuilder) {
throw UnsupportedOperationException()
}
}
companion object {
const val CMWC_STATE_SIZE = 32 // 4096
const val CMWC_CARRY_MAX = 809430660
}
}

View File

@ -1,59 +0,0 @@
package ru.dbotthepony.mc.otm.core.util
import net.minecraft.util.Mth
import net.minecraft.util.RandomSource
import net.minecraft.world.level.levelgen.LegacyRandomSource
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian
import net.minecraft.world.level.levelgen.PositionalRandomFactory
import net.minecraft.world.level.levelgen.RandomSupport
import ru.dbotthepony.kommons.random.LCG64Random
import java.lang.StringBuilder
/**
* Simple and insanely fast random number generator, which can be used for seeding (initializing internal state) of other number generators.
*
* While can be used on its own, it probably shouldn't.
*
* Differs from [LegacyRandomSource] (also LCG, created by [RandomSource.create]) Minecraft uses in:
* * Different constants (with supposedly/expected better statistical properties)
* * Always use upper 32 bits instead of implementing BitRandomSource and sampling some upper bits
* * Uses all bits from provided seed
*/
class LCG64RandomSource(seed: Long = RandomSupport.generateUniqueSeed()) : LCG64Random(seed), IRandomSourceGenerator {
private val gaussian = MarsagliaPolarGaussian(this)
override fun setSeed(seed: Long) {
this.seed = seed
gaussian.reset()
}
override fun nextGaussian(): Double {
return gaussian.nextGaussian()
}
override fun fork(): RandomSource {
return LCG64RandomSource(nextLong())
}
override fun forkPositional(): PositionalRandomFactory {
return Positional(nextLong())
}
class Positional(private val seed: Long) : PositionalRandomFactory {
override fun at(x: Int, y: Int, z: Int): RandomSource {
return LCG64RandomSource(Mth.getSeed(x, y, z).xor(seed))
}
override fun fromHashOf(name: String): RandomSource {
return LCG64RandomSource(name.hashCode().toLong().xor(seed))
}
override fun fromSeed(seed: Long): RandomSource {
return LCG64RandomSource(seed)
}
override fun parityConfigString(builder: StringBuilder) {
throw UnsupportedOperationException()
}
}
}

View File

@ -1,51 +0,0 @@
package ru.dbotthepony.mc.otm.core.util
import net.minecraft.util.Mth
import net.minecraft.util.RandomSource
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian
import net.minecraft.world.level.levelgen.PositionalRandomFactory
import net.minecraft.world.level.levelgen.RandomSupport
import ru.dbotthepony.kommons.random.PCG32Random
import java.lang.StringBuilder
/**
* @see PCG32Random
*/
class PCG32RandomSource(seed: Long = RandomSupport.generateUniqueSeed()) : PCG32Random(seed), IRandomSourceGenerator {
private val gaussian = MarsagliaPolarGaussian(this)
override fun setSeed(seed: Long) {
this.seed = seed
gaussian.reset()
}
override fun nextGaussian(): Double {
return gaussian.nextGaussian()
}
override fun fork(): RandomSource {
return PCG32RandomSource(nextLong())
}
override fun forkPositional(): PositionalRandomFactory {
return Positional(nextLong())
}
class Positional(private val seed: Long) : PositionalRandomFactory {
override fun at(x: Int, y: Int, z: Int): RandomSource {
return PCG32RandomSource(Mth.getSeed(x, y, z).xor(seed))
}
override fun fromHashOf(name: String): RandomSource {
return PCG32RandomSource(name.hashCode().toLong().xor(seed))
}
override fun fromSeed(seed: Long): RandomSource {
return PCG32RandomSource(seed)
}
override fun parityConfigString(builder: StringBuilder) {
throw UnsupportedOperationException()
}
}
}

View File

@ -1,93 +0,0 @@
package ru.dbotthepony.mc.otm.core.util
import it.unimi.dsi.fastutil.HashCommon
import net.minecraft.util.Mth
import net.minecraft.util.RandomSource
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian
import net.minecraft.world.level.levelgen.PositionalRandomFactory
import net.minecraft.world.level.levelgen.RandomSupport
import ru.dbotthepony.kommons.random.LCG64Random
import ru.dbotthepony.kommons.random.Xoshiro256StarStarRandom
/**
* Excellent number generator with guaranteed period of 2^255
*/
class Xoshiro256Random : Xoshiro256StarStarRandom, IRandomSourceGenerator {
private val gaussian = MarsagliaPolarGaussian(this)
// raw
private constructor(s0: Long, s1: Long, s2: Long, s3: Long, marker: Nothing?): super(s0, s1, s2, s3, null)
// normal
constructor(s0: Long, s1: Long, s2: Long, s3: Long) : super(s0, s1, s2, s3)
// 64-bit seeded
constructor(seed: Long) : super(1L, 2L, 3L, 4L, null) {
setSeed(seed)
}
// completely random
constructor() : super(RandomSupport.generateUniqueSeed(), RandomSupport.generateUniqueSeed(), RandomSupport.generateUniqueSeed(), RandomSupport.generateUniqueSeed(), null)
override fun setSeed(seed: Long) {
val rng = LCG64Random(seed)
s0 = rng.nextLong()
s1 = rng.nextLong()
s2 = rng.nextLong()
s3 = rng.nextLong()
gaussian.reset()
}
override fun nextInt(): Int {
// sample upper bits
return nextLong().ushr(32).toInt()
}
override fun nextGaussian(): Double {
return gaussian.nextGaussian()
}
override fun fork(): RandomSource {
return Xoshiro256Random(nextLong(), nextLong(), nextLong(), nextLong(), null)
}
override fun forkPositional(): PositionalRandomFactory {
return Positional(nextLong(), nextLong(), nextLong(), nextLong())
}
class Positional(
private val s0: Long,
private val s1: Long,
private val s2: Long,
private val s3: Long,
) : PositionalRandomFactory {
override fun at(x: Int, y: Int, z: Int): RandomSource {
val rng = LCG64RandomSource(Mth.getSeed(x, y, z))
return Xoshiro256Random(
s0.rotateLeft(11).xor(rng.nextLong()),
s1.rotateLeft(22).xor(rng.nextLong()),
s2.rotateLeft(33).xor(rng.nextLong()),
s3.rotateLeft(44).xor(rng.nextLong()),
)
}
override fun fromHashOf(name: String): RandomSource {
return Xoshiro256Random(s0, HashCommon.murmurHash3(name.hashCode().toLong()).xor(s1), s2, s3)
}
override fun fromSeed(seed: Long): RandomSource {
return Xoshiro256Random(seed)
}
override fun parityConfigString(builder: StringBuilder) {
throw UnsupportedOperationException()
}
}
companion object {
@JvmStatic
fun raw(s0: Long, s1: Long, s2: Long, s3: Long): Xoshiro256Random {
return Xoshiro256Random(s0, s1, s2, s3, null)
}
}
}

View File

@ -7,7 +7,7 @@ import net.minecraft.world.level.storage.loot.LootContext
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.data.get
import ru.dbotthepony.mc.otm.registry.data.MLootItemConditions

View File

@ -5,7 +5,7 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams
import net.minecraft.world.level.storage.loot.predicates.InvertedLootItemCondition
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.data.get
import ru.dbotthepony.mc.otm.registry.data.MLootItemConditions

View File

@ -19,7 +19,7 @@ import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.gameevent.GameEvent
import ru.dbotthepony.mc.otm.block.decorative.CargoCrateBlock
import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.random
import ru.dbotthepony.mc.otm.core.position
import ru.dbotthepony.mc.otm.menu.decorative.MinecartCargoCrateMenu
import ru.dbotthepony.mc.otm.registry.game.MItems
@ -90,7 +90,7 @@ class MinecartCargoCrate(
if (interactingPlayers++ == 0) {
if (!isRemoved) {
level().playSound(null, this, MSoundEvents.CARGO_CRATE_OPEN, SoundSource.BLOCKS, 1f, 0.8f + level().otmRandom.nextFloat() * 0.2f)
level().playSound(null, this, MSoundEvents.CARGO_CRATE_OPEN, SoundSource.BLOCKS, 1f, 0.8f + level().random.nextFloat() * 0.2f)
this.gameEvent(GameEvent.CONTAINER_OPEN, player)
PiglinAi.angerNearbyPiglins(player, true)
}

View File

@ -7,7 +7,7 @@ import net.minecraft.world.item.Items
import net.neoforged.bus.api.SubscribeEvent
import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent
import ru.dbotthepony.mc.otm.config.ServerConfig
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.random
import ru.dbotthepony.mc.otm.registry.game.MItems
@ -17,8 +17,8 @@ object WitheredSkeletonSpawnHandler {
val entity = event.entity
if (entity is WitherSkeleton) {
val giveHelmet = event.level.otmRandom.nextFloat() < ServerConfig.WITHER_SKELETON_HELMET_CHANCE
val giveSword = event.level.otmRandom.nextFloat() < ServerConfig.WITHER_SKELETON_SWORD_CHANCE
val giveHelmet = event.level.random.nextFloat() < ServerConfig.WITHER_SKELETON_HELMET_CHANCE
val giveSword = event.level.random.nextFloat() < ServerConfig.WITHER_SKELETON_SWORD_CHANCE
if (giveHelmet) {
if (!entity.hasItemInSlot(EquipmentSlot.HEAD))

View File

@ -21,6 +21,7 @@ import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.config.ItemsConfig
import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.registry.CapabilitiesRegisterListener
import ru.dbotthepony.mc.otm.registry.MDamageTypes
import ru.dbotthepony.mc.otm.registry.game.MDataComponentTypes
@ -184,7 +185,7 @@ class CrudeBatteryItem : BatteryItem(ItemsConfig.Batteries.CRUDE) {
if (player is ServerPlayer) {
if (!mattery.androidEnergy.item.isEmpty) {
mattery.androidEnergy.item.getCapability(Capabilities.EnergyStorage.ITEM)?.let {
it.extractEnergy((it.maxEnergyStored * level.otmRandom.nextFloat() * .2f).roundToInt(), false)
it.extractEnergy((it.maxEnergyStored * level.random.nextFloat() * .2f).roundToInt(), false)
}
mattery.dropBattery()
@ -194,7 +195,7 @@ class CrudeBatteryItem : BatteryItem(ItemsConfig.Batteries.CRUDE) {
copyStack.count = 1
mattery.androidEnergy.item = copyStack
val extraDamageMult = level.otmRandom.nextFloat()
val extraDamageMult = level.random.nextFloat()
player.hurt(MatteryDamageSource(level.registryAccess().damageType(MDamageTypes.EMP), inflictor = itemStack), 1.5f + extraDamageMult * 3.5f)
val debuffDuration = 100 + (100 * (1f - extraDamageMult)).roundToInt()

View File

@ -13,11 +13,10 @@ import net.minecraft.world.item.*
import net.minecraft.world.item.alchemy.PotionContents
import net.minecraft.world.item.alchemy.Potions
import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.isShiftDown
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.util.getLevelFromXp
import ru.dbotthepony.mc.otm.item.MatteryItem
import ru.dbotthepony.mc.otm.registry.game.MDataComponentTypes
@ -81,7 +80,7 @@ class EssenceCapsuleItem(private val digital: Boolean) : MatteryItem(Properties(
} else {
if (level is ServerLevel) {
level.levelEvent(2002, player.blockPosition(), PotionContents.getColor(Potions.WATER))
ExperienceOrb.award(level, player.position(), (exp * (.5 + level.otmRandom.nextFloat() * .25)).toInt())
ExperienceOrb.award(level, player.position(), (exp * (.5 + level.random.nextFloat() * .25)).toInt())
}
}

View File

@ -11,7 +11,7 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Rarity
import net.minecraft.world.item.UseAnim
import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.item.MatteryItem

View File

@ -9,7 +9,7 @@ import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.random
import ru.dbotthepony.mc.otm.core.position
import ru.dbotthepony.mc.otm.entity.BreadMonster
import ru.dbotthepony.mc.otm.item.MatteryItem
@ -39,7 +39,7 @@ class ImperfectBreadItem(properties: Properties) : MatteryItem(properties) {
// roll multiple times so multiple bread monsters can spawn on tick
// and also chance be less biased
for (i in 0 until stack.count.coerceAtMost(16)) {
if (entity.level().otmRandom.nextFloat() < 0.001f) {
if (entity.level().random.nextFloat() < 0.001f) {
val ent = BreadMonster(entity.level())
ent.position = entity.position
entity.level().addFreshEntity(ent)

View File

@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.item.consumables
import net.minecraft.ChatFormatting
import net.minecraft.core.component.DataComponentMap
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.Style
import net.minecraft.tags.TagKey
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResult
@ -18,7 +17,7 @@ import net.minecraft.world.item.UseAnim
import net.minecraft.world.level.Level
import net.minecraft.world.level.gameevent.GameEvent
import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent.EntityInteract
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.isShiftDown
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.TranslatableComponent

View File

@ -8,7 +8,7 @@ import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.*
import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.core.damageType
import ru.dbotthepony.mc.otm.item.MatteryItem
import ru.dbotthepony.mc.otm.registry.MDamageTypes

View File

@ -10,7 +10,7 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Rarity
import net.minecraft.world.item.UseAnim
import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.item.MatteryItem

View File

@ -15,7 +15,7 @@ import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.item.UseAnim
import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.config.ServerConfig
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.isExplosion

View File

@ -11,7 +11,7 @@ import net.minecraft.world.item.*
import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.onceServer
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.damageType
import ru.dbotthepony.mc.otm.registry.MDamageTypes

View File

@ -13,8 +13,8 @@ import net.minecraft.world.item.Rarity
import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.item.UseAnim
import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.runIfClient

View File

@ -84,7 +84,7 @@ class ExplosiveHammerItem(durability: Int = 512) : Item(Properties().stacksTo(1)
itemStack.hurtAndBreak(8, level, player) {}
if (isPrimed(itemStack)) {
itemStack.hurtAndBreak(level.otmRandom.nextInt(1, 20), level, player) {}
itemStack.hurtAndBreak(level.random.nextInt(1, 20), level, player) {}
unprime(itemStack)
val (ex, ey, ez) = Vector.atCenterOf(player.blockPosition())
@ -226,7 +226,7 @@ class ExplosiveHammerItem(durability: Int = 512) : Item(Properties().stacksTo(1)
val copy = itemStack.copy()
itemStack.hurtAndBreak(level.otmRandom.nextInt(1, 20), attacker, EquipmentSlot.MAINHAND)
itemStack.hurtAndBreak(level.random.nextInt(1, 20), attacker, EquipmentSlot.MAINHAND)
if (!itemStack.isEmpty && attacker.random.nextDouble() <= ToolsConfig.ExplosiveHammer.FLY_OFF_CHANCE) {
attacker.setItemInHand(hand, ItemStack.EMPTY)

View File

@ -1,7 +1,6 @@
package ru.dbotthepony.mc.otm.item.weapon
import net.minecraft.core.BlockPos
import net.minecraft.core.component.DataComponents
import net.minecraft.tags.BlockTags
import net.minecraft.world.entity.EquipmentSlotGroup
import net.minecraft.world.entity.LivingEntity
@ -26,14 +25,13 @@ import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.capability.energy.getBarColor
import ru.dbotthepony.mc.otm.capability.energy.getBarWidth
import ru.dbotthepony.mc.otm.capability.matteryEnergy
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.core.damageType
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.DecimalConfigValue
import ru.dbotthepony.mc.otm.core.math.defineDecimal
import ru.dbotthepony.mc.otm.core.math.nextVariance
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.util.WriteOnce
import ru.dbotthepony.mc.otm.item.MatteryItem
import ru.dbotthepony.mc.otm.item.addSimpleDescription
@ -98,10 +96,10 @@ class EnergySwordItem : MatteryItem(Properties().stacksTo(1).rarity(Rarity.RARE)
itemStack.getCapability(MatteryCapability.ITEM_ENERGY)?.let {
if (it.extractEnergyExact(ENERGY_PER_SWING, false)) {
it.extractEnergy(attacker.level().otmRandom.nextVariance(ENERGY_PER_SWING_VARIANCE), false)
it.extractEnergy(attacker.level().random.nextVariance(ENERGY_PER_SWING_VARIANCE), false)
victim.matteryPlayer?.let {
if (it.isAndroid && it.androidEnergy.extractEnergyExact(ENERGY_ZAP, false)) {
it.androidEnergy.extractEnergy(attacker.level().otmRandom.nextVariance(ENERGY_ZAP_VARIANCE), false)
it.androidEnergy.extractEnergy(attacker.level().random.nextVariance(ENERGY_ZAP_VARIANCE), false)
victim.hurt(MatteryDamageSource(attacker.level().registryAccess().damageType(MDamageTypes.EMP), attacker, itemStack), 8f)
}
}
@ -144,12 +142,12 @@ class EnergySwordItem : MatteryItem(Properties().stacksTo(1).rarity(Rarity.RARE)
if (blockState.`is`(BlockTags.SWORD_EFFICIENT)) {
if (energy?.extractEnergyExact(PLANT_POWER_COST, false) == true)
energy.extractEnergyExact(user.level().otmRandom.nextVariance(PLANT_POWER_COST_VARIANCE), false)
energy.extractEnergyExact(user.level().random.nextVariance(PLANT_POWER_COST_VARIANCE), false)
}
if (blockState.`is`(Blocks.COBWEB)) {
if (energy?.extractEnergyExact(COBWEB_POWER_COST, false) == true)
energy.extractEnergyExact(user.level().otmRandom.nextVariance(COBWEB_POWER_COST_VARIANCE), false)
energy.extractEnergyExact(user.level().random.nextVariance(COBWEB_POWER_COST_VARIANCE), false)
}
}

View File

@ -1,7 +1,6 @@
package ru.dbotthepony.mc.otm.item.weapon
import net.minecraft.core.BlockPos
import net.minecraft.core.component.DataComponents
import net.minecraft.tags.BlockTags
import net.minecraft.world.entity.EquipmentSlotGroup
import net.minecraft.world.entity.LivingEntity
@ -26,14 +25,13 @@ import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.capability.energy.getBarColor
import ru.dbotthepony.mc.otm.capability.energy.getBarWidth
import ru.dbotthepony.mc.otm.capability.matteryEnergy
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.core.damageType
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.DecimalConfigValue
import ru.dbotthepony.mc.otm.core.math.defineDecimal
import ru.dbotthepony.mc.otm.core.math.nextVariance
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.util.WriteOnce
import ru.dbotthepony.mc.otm.item.MatteryItem
import ru.dbotthepony.mc.otm.item.addSimpleDescription
@ -98,10 +96,10 @@ class FallingSunItem : MatteryItem(Properties().stacksTo(1).rarity(Rarity.EPIC))
itemStack.getCapability(MatteryCapability.ITEM_ENERGY)?.let {
if (it.extractEnergyExact(ENERGY_PER_SWING, false)) {
it.extractEnergy(attacker.level().otmRandom.nextVariance(ENERGY_PER_SWING_VARIANCE), false)
it.extractEnergy(attacker.level().random.nextVariance(ENERGY_PER_SWING_VARIANCE), false)
victim.matteryPlayer?.let {
if (it.isAndroid && it.androidEnergy.extractEnergyExact(ENERGY_ZAP, false)) {
it.androidEnergy.extractEnergy(attacker.level().otmRandom.nextVariance(ENERGY_ZAP_VARIANCE), false)
it.androidEnergy.extractEnergy(attacker.level().random.nextVariance(ENERGY_ZAP_VARIANCE), false)
victim.hurt(MatteryDamageSource(attacker.level().registryAccess().damageType(MDamageTypes.EMP), attacker, itemStack), 8f)
}
}
@ -144,12 +142,12 @@ class FallingSunItem : MatteryItem(Properties().stacksTo(1).rarity(Rarity.EPIC))
if (blockState.`is`(BlockTags.SWORD_EFFICIENT)) {
if (energy?.extractEnergyExact(PLANT_POWER_COST, false) == true)
energy.extractEnergyExact(user.level().otmRandom.nextVariance(PLANT_POWER_COST_VARIANCE), false)
energy.extractEnergyExact(user.level().random.nextVariance(PLANT_POWER_COST_VARIANCE), false)
}
if (blockState.`is`(Blocks.COBWEB)) {
if (energy?.extractEnergyExact(COBWEB_POWER_COST, false) == true)
energy.extractEnergyExact(user.level().otmRandom.nextVariance(COBWEB_POWER_COST_VARIANCE), false)
energy.extractEnergyExact(user.level().random.nextVariance(COBWEB_POWER_COST_VARIANCE), false)
}
}

View File

@ -17,7 +17,7 @@ import net.minecraft.world.inventory.Slot
import net.minecraft.world.inventory.TransientCraftingContainer
import net.minecraft.world.item.ItemStack
import net.neoforged.neoforge.network.PacketDistributor
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.compat.curios.curiosSlots
import ru.dbotthepony.mc.otm.container.util.slotIterator
import ru.dbotthepony.mc.otm.menu.input.InstantBooleanInput

View File

@ -35,7 +35,7 @@ import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.compat.cos.cosmeticArmorSlots
import ru.dbotthepony.mc.otm.compat.curios.curiosSlots
import ru.dbotthepony.mc.otm.compat.curios.isCurioSlot

View File

@ -15,7 +15,7 @@ import ru.dbotthepony.kommons.util.ListenableDelegate
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.block.entity.decorative.PainterBlockEntity
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer

View File

@ -8,8 +8,8 @@ import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.neoforged.neoforge.capabilities.Capabilities
import ru.dbotthepony.mc.otm.block.entity.tech.AndroidStationBlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
import ru.dbotthepony.mc.otm.menu.MatteryMenuSlot

View File

@ -10,17 +10,17 @@ import net.minecraft.server.level.ServerPlayer
import net.minecraft.sounds.SoundSource
import net.neoforged.neoforge.network.handling.IPayloadContext
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidActiveFeature
import ru.dbotthepony.mc.otm.android.AndroidFeatureType
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.android.AndroidResearchType
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.player.android.AndroidActiveFeature
import ru.dbotthepony.mc.otm.player.android.AndroidFeatureType
import ru.dbotthepony.mc.otm.player.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.player.android.AndroidResearchType
import ru.dbotthepony.mc.otm.player.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.MatteryGUI
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.render.GlitchRenderer
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.config.PlayerConfig
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.core.readComponent
import ru.dbotthepony.mc.otm.core.writeComponent
@ -366,7 +366,7 @@ object TriggerJumpBoostPacket : CustomPacketPayload {
val feature = mattery.getFeature(AndroidFeatures.JUMP_BOOST) ?: return
if (feature.isActive && feature.cooldown <= 4 && mattery.androidEnergy.extractEnergyExact(AndroidConfig.JumpBoost.ENERGY_COST, false)) {
if (feature.isActive && feature.cooldown <= 4 && mattery.androidEnergy.extractEnergyExact(PlayerConfig.JumpBoost.ENERGY_COST, false)) {
feature.putOnCooldown()
context.player().level().playSound(

View File

@ -14,8 +14,8 @@ import net.neoforged.neoforge.network.handling.IPayloadContext
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.container.get
import ru.dbotthepony.mc.otm.container.set
@ -24,7 +24,6 @@ import ru.dbotthepony.mc.otm.core.math.component1
import ru.dbotthepony.mc.otm.core.math.component2
import ru.dbotthepony.mc.otm.core.math.component3
import ru.dbotthepony.mc.otm.core.math.toRadians
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.position
import ru.dbotthepony.mc.otm.core.readItem
import ru.dbotthepony.mc.otm.core.writeItem
@ -446,7 +445,7 @@ class ExopackSmokePacket(val player: UUID) : CustomPacketPayload {
z += kotlin.math.sin(deg) * -0.4
val level = ply.level()
val random = level.otmRandom
val random = level.random
for (i in 0 .. random.nextInt(2, 4))
level.addParticle(

View File

@ -1,18 +1,15 @@
package ru.dbotthepony.mc.otm.network
import it.unimi.dsi.fastutil.bytes.ByteArrayList
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.codec.StreamCodec
import net.minecraft.network.protocol.common.custom.CustomPacketPayload
import net.neoforged.neoforge.network.handling.IPayloadContext
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.menu.ExopackInventoryMenu
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import java.io.ByteArrayInputStream
class MenuDataPacket(val containerId: Int, val bytes: ByteArrayList) : CustomPacketPayload {
fun write(buff: FriendlyByteBuf) {

View File

@ -2,8 +2,8 @@ package ru.dbotthepony.mc.otm.network
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent
import net.neoforged.neoforge.network.registration.HandlerThread
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.android.feature.ItemEntityDataPacket
import ru.dbotthepony.mc.otm.player.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.player.android.feature.ItemEntityDataPacket
import ru.dbotthepony.mc.otm.compat.vanilla.InventoryScrollPacket
import ru.dbotthepony.mc.otm.data.FlywheelMaterials
import ru.dbotthepony.mc.otm.item.QuantumBatteryItem

View File

@ -13,7 +13,7 @@ import net.neoforged.neoforge.network.handling.IPayloadContext
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.random
class SmokeParticlesPacket(val x: Double, val y: Double, val z: Double) : CustomPacketPayload {
fun write(buff: FriendlyByteBuf) {
@ -24,7 +24,7 @@ class SmokeParticlesPacket(val x: Double, val y: Double, val z: Double) : Custom
fun play(context: IPayloadContext) {
minecraft.player?.level()?.let {
makeSmoke(x, y, z, it.otmRandom, it)
makeSmoke(x, y, z, it.random, it)
}
}

View File

@ -0,0 +1,7 @@
package ru.dbotthepony.mc.otm.player
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
val Player.matteryPlayer: MatteryPlayer get() = (this as IMatteryPlayer).otmPlayer
val LivingEntity.matteryPlayer: MatteryPlayer? get() = (this as? IMatteryPlayer)?.otmPlayer

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.capability
package ru.dbotthepony.mc.otm.player
interface IMatteryPlayer {
// since new capabilities dont get to live through getCapability calls by design

View File

@ -0,0 +1,202 @@
package ru.dbotthepony.mc.otm.player
import net.minecraft.nbt.CompoundTag
import net.minecraft.world.Difficulty
import net.minecraft.world.damagesource.DamageSource
import net.minecraft.world.effect.MobEffectInstance
import net.minecraft.world.effect.MobEffects
import net.minecraft.world.entity.player.Player
import net.minecraft.world.food.FoodConstants
import net.minecraft.world.food.FoodData
import net.minecraft.world.food.FoodProperties
import net.minecraft.world.level.GameRules
import ru.dbotthepony.mc.otm.config.IFoodRegenerationValues
import ru.dbotthepony.mc.otm.config.PlayerConfig
import ru.dbotthepony.mc.otm.core.damageType
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.getDecimal
import ru.dbotthepony.mc.otm.core.math.set
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.registry.MDamageTypes
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
class MatteryFoodData(private var player: Player) : FoodData() {
private fun add(foodLevel: Int, saturation: Float) {
if (player.matteryPlayer.isAndroid && PlayerConfig.REGENERATE_ENERGY) {
energyToDrain -= PlayerConfig.ANDROID_ENERGY_PER_HUNGER_POINT * foodLevel * PlayerConfig.REGENERATE_ENERGY_EFFICIENCY_FOOD
energyToDrain -= PlayerConfig.ANDROID_ENERGY_PER_HUNGER_POINT * saturation.coerceAtMost(PlayerConfig.Food.SOFT_FOOD_LIMIT.toFloat()) * PlayerConfig.REGENERATE_ENERGY_EFFICIENCY_SATURATION
} else if (!player.matteryPlayer.isAndroid) {
this.foodLevel = min(this.foodLevel + foodLevel, PlayerConfig.Food.HARD_FOOD_LIMIT)
this.saturationLevel = min(this.saturationLevel + saturation, this.foodLevel + PlayerConfig.Food.OVERSATURATION_LIMIT.toFloat()).coerceAtLeast(0f)
}
}
override fun eat(foodLevelModifier: Int, saturationLevelModifier: Float) {
add(foodLevelModifier, FoodConstants.saturationByModifier(foodLevelModifier, saturationLevelModifier))
}
override fun eat(foodProperties: FoodProperties) {
add(foodProperties.nutrition(), foodProperties.saturation())
}
override fun needsFood(): Boolean {
return player.matteryPlayer.isAndroid || foodLevel < PlayerConfig.Food.SOFT_FOOD_LIMIT
}
override fun addExhaustion(exhaustion: Float) {
// store exhaustion as usual, and handle its reduction in tick for both humans and androids
this.exhaustionLevel = min(this.exhaustionLevel + exhaustion, PlayerConfig.Food.EXHAUSTION_LIMIT.toFloat()).coerceAtLeast(0f)
}
override fun readAdditionalSaveData(compoundTag: CompoundTag) {
super.readAdditionalSaveData(compoundTag)
if ("lastFoodLevel" in compoundTag)
lastFoodLevel = compoundTag.getInt("lastFoodLevel")
if ("foodAndroidEnergyToDrain" in compoundTag)
energyToDrain = compoundTag.getDecimal("foodAndroidEnergyToDrain")
}
override fun addAdditionalSaveData(compoundTag: CompoundTag) {
super.addAdditionalSaveData(compoundTag)
compoundTag["lastFoodLevel"] = lastFoodLevel
compoundTag["foodAndroidEnergyToDrain"] = energyToDrain
}
private var energyToDrain = Decimal.ZERO
private fun tickExhaustion() {
if (exhaustionLevel >= EXHAUSTION_PER_HUNGER_POINT) {
var points = (exhaustionLevel / EXHAUSTION_PER_HUNGER_POINT).toInt()
exhaustionLevel %= EXHAUSTION_PER_HUNGER_POINT
if (player.matteryPlayer.isAndroid) {
energyToDrain += PlayerConfig.ANDROID_ENERGY_PER_HUNGER_POINT * points
} else {
if (saturationLevel > 0f) {
val satisfied = min(saturationLevel.roundToInt(), points)
points -= satisfied
saturationLevel -= satisfied
}
foodLevel = max(0, foodLevel - points)
}
}
}
private fun tickRegeneration(values: IFoodRegenerationValues): Boolean {
if (!player.isHurt || foodLevel < values.foodLimit || values.requiresSaturation && saturationLevel <= 0f)
return false
while (player.isHurt && foodLevel >= values.foodLimit && (!values.requiresSaturation || saturationLevel > 0f) && ++tickTimer >= values.ticks) {
tickTimer = 0
val healAmount = if (values.requiresSaturation && values.regenerationSlowdown) min(saturationLevel, values.upperSlowdownBound.toFloat()) / values.upperSlowdownBound.toFloat() else 1f
player.heal(healAmount)
addExhaustion(healAmount * 6f)
tickExhaustion()
}
return tickTimer != 0
}
override fun tick(player: Player) {
this.player = player
tickExhaustion()
if (player.matteryPlayer.isAndroid) {
if (energyToDrain > Decimal.ZERO)
energyToDrain -= player.matteryPlayer.androidEnergy.extractEnergy(energyToDrain, false)
else if (energyToDrain < Decimal.ZERO)
energyToDrain += player.matteryPlayer.androidEnergy.receiveEnergy(-energyToDrain, false)
if (player.level().difficulty == Difficulty.PEACEFUL && PlayerConfig.REGENERATE_ENERGY_IN_PEACEFUL)
player.matteryPlayer.androidEnergy.receiveEnergy(PlayerConfig.ANDROID_ENERGY_PER_HUNGER_POINT, false)
if (!player.matteryPlayer.androidHasEnergy) {
if (++tickTimer >= 20 && player.hurt(DamageSource(player.level().registryAccess().damageType(MDamageTypes.ANDROID_DISCHARGE)), 1f)) {
tickTimer = 0
}
val effect = player.activeEffectsMap[MobEffects.MOVEMENT_SLOWDOWN]
if (effect == null || effect.duration < 40 || effect.amplifier < 2) {
player.addEffect(MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, effect?.duration?.coerceAtLeast(60) ?: 60, effect?.amplifier?.coerceAtLeast(2) ?: 2, false, false))
}
} else {
if (player.isHurt && player.level().gameRules.getBoolean(GameRules.RULE_NATURAL_REGENERATION)) {
if (++tickTimer >= PlayerConfig.TIME_BETWEEN_NATURAL_REGENERATION) {
player.heal(1f)
addExhaustion(6f)
tickTimer = 0
}
} else {
tickTimer = 0
}
}
} else {
lastFoodLevel = foodLevel
energyToDrain = Decimal.ZERO
if (
player.level().gameRules.getBoolean(GameRules.RULE_NATURAL_REGENERATION) &&
(tickRegeneration(PlayerConfig.Food.FAST_REGEN) || tickRegeneration(PlayerConfig.Food.SLOW_REGEN))
) {
// do nothing
} else if (PlayerConfig.Food.ENABLE_STARVATION && foodLevel <= 0) {
if (++tickTimer >= PlayerConfig.Food.STARVATION_TICKS) {
tickTimer = 0
val threshold = when (player.level().difficulty) {
Difficulty.PEACEFUL -> Float.POSITIVE_INFINITY
Difficulty.EASY -> PlayerConfig.Food.STARVATION_HEALTH_LIMIT_EASY.toFloat()
Difficulty.NORMAL -> PlayerConfig.Food.STARVATION_HEALTH_LIMIT_NORMAL.toFloat()
Difficulty.HARD -> PlayerConfig.Food.STARVATION_HEALTH_LIMIT_HARD.toFloat()
}
if (player.health > threshold) {
player.hurt(player.damageSources().starve(), 1.0f)
}
}
} else {
tickTimer = 0
}
}
}
override fun getFoodLevel(): Int {
if (player.matteryPlayer.isAndroid)
return if (player.matteryPlayer.androidHasEnergy) PlayerConfig.Food.SOFT_FOOD_LIMIT else 0
return super.getFoodLevel()
}
override fun getLastFoodLevel(): Int {
if (player.matteryPlayer.isAndroid)
return getFoodLevel()
return super.getLastFoodLevel()
}
override fun getExhaustionLevel(): Float {
if (player.matteryPlayer.isAndroid && player.matteryPlayer.androidHasEnergy)
return 0f
return super.getExhaustionLevel()
}
override fun getSaturationLevel(): Float {
if (player.matteryPlayer.isAndroid)
return if (player.matteryPlayer.androidHasEnergy) player.matteryPlayer.androidEnergy.batteryLevel.percentage(player.matteryPlayer.androidEnergy.maxBatteryLevel) * PlayerConfig.Food.SOFT_FOOD_LIMIT else 0f
return super.getSaturationLevel()
}
companion object {
const val EXHAUSTION_PER_HUNGER_POINT = 4f
}
}

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.capability
package ru.dbotthepony.mc.otm.player
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack
@ -20,22 +20,19 @@ import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.tags.TagKey
import net.minecraft.world.Container
import net.minecraft.world.Difficulty
import net.minecraft.world.damagesource.DamageSource
import net.minecraft.world.effect.MobEffect
import net.minecraft.world.effect.MobEffectInstance
import net.minecraft.world.effect.MobEffects
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.boss.wither.WitherBoss
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.food.FoodProperties
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.ProjectileWeaponItem
import net.minecraft.world.item.crafting.RecipeManager
import net.minecraft.world.item.crafting.RecipeType
import net.minecraft.world.item.crafting.SingleRecipeInput
import net.minecraft.world.level.GameRules
import net.minecraft.world.level.Level
import net.minecraft.world.phys.Vec3
import net.neoforged.bus.api.Event
@ -59,22 +56,23 @@ import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.kommons.util.value
import ru.dbotthepony.mc.otm.*
import ru.dbotthepony.mc.otm.android.AndroidFeature
import ru.dbotthepony.mc.otm.android.AndroidFeatureType
import ru.dbotthepony.mc.otm.android.AndroidResearch
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.android.AndroidResearchType
import ru.dbotthepony.mc.otm.player.android.AndroidFeature
import ru.dbotthepony.mc.otm.player.android.AndroidFeatureType
import ru.dbotthepony.mc.otm.player.android.AndroidResearch
import ru.dbotthepony.mc.otm.player.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.player.android.AndroidResearchType
import ru.dbotthepony.mc.otm.block.entity.ItemJob
import ru.dbotthepony.mc.otm.block.entity.JobContainer
import ru.dbotthepony.mc.otm.block.entity.JobStatus
import ru.dbotthepony.mc.otm.block.entity.MachineJobEventLoop
import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade
import ru.dbotthepony.mc.otm.capability.energy
import ru.dbotthepony.mc.otm.capability.energy.BatteryBackedEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.capability.energy.receiveEnergyExact
import ru.dbotthepony.mc.otm.capability.receiveEnergy
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.config.PlayerConfig
import ru.dbotthepony.mc.otm.config.ExopackConfig
import ru.dbotthepony.mc.otm.container.CombinedContainer
import ru.dbotthepony.mc.otm.container.DynamicallyProxiedContainer
@ -442,8 +440,6 @@ class MatteryPlayer(val ply: Player) {
private var shouldPlaySound = false
private val research = IdentityHashMap<AndroidResearchType, AndroidResearch>()
private var nextDischargeHurt = 20
private var nextHealTick = 0
/**
* This returns if player is an Android or will become one on death/sleep/etc
@ -542,7 +538,7 @@ class MatteryPlayer(val ply: Player) {
override fun onJobTick(status: JobStatus<ItemJob>) {
super.onJobTick(status)
if (isExopackVisible && ply.level().otmRandom.nextFloat() <= 0.05f) {
if (isExopackVisible && ply.level().random.nextFloat() <= 0.05f) {
PacketDistributor.sendToPlayersTrackingEntityAndSelf(ply, ExopackSmokePacket(ply.uuid))
}
}
@ -567,7 +563,10 @@ class MatteryPlayer(val ply: Player) {
/**
* [IMatteryEnergyStorage] instance, representing Android' battery charge
*/
val androidEnergy = BatteryBackedEnergyStorage(ply, syncher, AndroidConfig.ANDROID_MAX_ENERGY, AndroidConfig.ANDROID_MAX_ENERGY, true)
val androidEnergy = BatteryBackedEnergyStorage(ply, syncher, PlayerConfig.ANDROID_MAX_ENERGY, PlayerConfig.ANDROID_MAX_ENERGY, true)
val androidHasEnergy: Boolean
get() = androidEnergy.batteryLevel > Decimal.TEN
/**
* [IMatteryEnergyStorage] instance, representing Exopack battery charge
@ -590,8 +589,6 @@ class MatteryPlayer(val ply: Player) {
savetables.bool(::isExopackCraftingUpgraded, "isExoSuitCraftingUpgraded")
savetables.bool(::isExopackEnderAccessInstalled, "isExopackEnderAccessUpgraded")
savetables.bool(::acceptExopackChargeFromWirelessCharger)
savetables.int(::nextDischargeHurt)
savetables.int(::nextHealTick)
savetables.vector(::lastLiquidPosition)
savetables.codec(::lastDimension, ResourceLocation.CODEC)
@ -665,8 +662,8 @@ class MatteryPlayer(val ply: Player) {
shouldPlaySound = false
iteration = 0
deathLog.clear()
androidEnergy.batteryLevel = AndroidConfig.ANDROID_MAX_ENERGY
androidEnergy.maxBatteryLevel = AndroidConfig.ANDROID_MAX_ENERGY
androidEnergy.batteryLevel = PlayerConfig.ANDROID_MAX_ENERGY
androidEnergy.maxBatteryLevel = PlayerConfig.ANDROID_MAX_ENERGY
lastLiquidPosition = ply.position()
wasInLiquid = false
@ -720,7 +717,7 @@ class MatteryPlayer(val ply: Player) {
iteration = 0
deathLog.clear()
androidEnergy.batteryLevel = Decimal.ZERO
androidEnergy.maxBatteryLevel = AndroidConfig.ANDROID_MAX_ENERGY
androidEnergy.maxBatteryLevel = PlayerConfig.ANDROID_MAX_ENERGY
dropBattery()
lastLiquidPosition = ply.position()
@ -1219,81 +1216,6 @@ class MatteryPlayer(val ply: Player) {
lastLiquidPosition = ply.position
}
val stats = ply.foodData
val fourTimesTheHunger = AndroidConfig.ANDROID_ENERGY_PER_HUNGER_POINT * 4
// истощение
if (stats.exhaustionLevel > 0f) {
val extracted = androidEnergy.extractEnergy(AndroidConfig.ANDROID_ENERGY_PER_HUNGER_POINT * (stats.exhaustionLevel / 4f), false)
stats.setExhaustion(stats.exhaustionLevel - (extracted / AndroidConfig.ANDROID_ENERGY_PER_HUNGER_POINT).toFloat() * 4f)
}
// Обычный голод
while (
stats.foodLevel < 18 &&
androidEnergy.batteryLevel >= fourTimesTheHunger &&
androidEnergy.extractEnergyExact(AndroidConfig.ANDROID_ENERGY_PER_HUNGER_POINT, false)
) {
stats.foodLevel++
}
// "поглощение" излишек голода, как при мирном режиме, так и при поедании обычной еды
if (AndroidConfig.REGENERATE_ENERGY) {
while (stats.foodLevel > 18 && androidEnergy.receiveEnergyExact(AndroidConfig.ANDROID_ENERGY_PER_HUNGER_POINT / 2, false)) {
stats.foodLevel--
}
} else if (ply.level().difficulty != Difficulty.PEACEFUL) {
stats.foodLevel = stats.foodLevel.coerceAtMost(18)
}
val foodLevel = stats.foodLevel.toFloat()
// насыщение
if (stats.saturationLevel < foodLevel && androidEnergy.batteryLevel >= fourTimesTheHunger) {
val extracted = androidEnergy.extractEnergy(AndroidConfig.ANDROID_ENERGY_PER_HUNGER_POINT * (foodLevel - stats.saturationLevel), false)
stats.setSaturation(stats.saturationLevel + (extracted / AndroidConfig.ANDROID_ENERGY_PER_HUNGER_POINT).toFloat())
}
if (androidEnergy.batteryLevel <= Decimal.TEN && !ply.isCreative && ply.level().difficulty != Difficulty.PEACEFUL) {
if (stats.saturationLevel > 1f) {
if (androidEnergy.receiveEnergyExact(AndroidConfig.ANDROID_ENERGY_PER_HUNGER_POINT, false)) {
stats.setSaturation(stats.saturationLevel - 1f)
}
} else if (stats.saturationLevel > 0f) {
val received = androidEnergy.receiveEnergy(AndroidConfig.ANDROID_ENERGY_PER_HUNGER_POINT * stats.saturationLevel, false)
stats.setSaturation(stats.saturationLevel - (received / AndroidConfig.ANDROID_ENERGY_PER_HUNGER_POINT).toFloat())
} else if (stats.foodLevel > 0) {
// так как голод не тикает для андроидов, "умереть с голоду" мы не можем
// но со стороны будет выглядеть как будто мы умираем с голода
if (androidEnergy.receiveEnergyExact(AndroidConfig.ANDROID_ENERGY_PER_HUNGER_POINT, false)) {
stats.foodLevel--
}
}
if (androidEnergy.batteryLevel <= Decimal.TEN) {
if (--nextDischargeHurt <= 0 && ply.hurt(DamageSource(ply.level().registryAccess().damageType(MDamageTypes.ANDROID_DISCHARGE)), 1f)) {
nextDischargeHurt = 20
}
val effect = ply.activeEffectsMap[MobEffects.MOVEMENT_SLOWDOWN]
if (effect == null || effect.duration < 40 || effect.amplifier < 2) {
ply.addEffect(MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, effect?.duration?.coerceAtLeast(60) ?: 60, effect?.amplifier?.coerceAtLeast(2) ?: 2, false, false))
}
}
} else {
nextDischargeHurt = 20
if (ply.isHurt && ply.level().gameRules.getBoolean(GameRules.RULE_NATURAL_REGENERATION)) {
if (--nextHealTick <= 0) {
nextHealTick = if (ply.level().difficulty == Difficulty.PEACEFUL) 10 else AndroidConfig.TIME_BETWEEN_NATURAL_REGENERATION
ply.heal(1f)
}
} else {
nextHealTick = if (ply.level().difficulty == Difficulty.PEACEFUL) 10 else AndroidConfig.TIME_BETWEEN_NATURAL_REGENERATION
}
}
}
for (feature in featureMap.values) {
@ -1407,7 +1329,7 @@ class MatteryPlayer(val ply: Player) {
pos.mul(RenderSystem.getProjectionMatrix())
pos.mul(poseStack.last().pose())
makeSmoke(cam.x + pos.x, cam.y + pos.y, cam.z + pos.z, ply.level().otmRandom, ply.level())
makeSmoke(cam.x + pos.x, cam.y + pos.y, cam.z + pos.z, ply.level().random, ply.level())
}
}
@ -1482,8 +1404,8 @@ class MatteryPlayer(val ply: Player) {
ply.matteryPlayer.shouldSendIteration = true
ply.matteryPlayer.deathLog.addLast(ply.tickCount to ply.combatTracker.deathMessage)
if (ply.matteryPlayer.androidEnergy.batteryLevel < AndroidConfig.ANDROID_MAX_ENERGY * Decimal("0.2"))
ply.matteryPlayer.androidEnergy.batteryLevel = AndroidConfig.ANDROID_MAX_ENERGY * Decimal("0.2") // если смерть была от разряда батареи, то предотвращаем софтлок
if (ply.matteryPlayer.androidEnergy.batteryLevel < PlayerConfig.ANDROID_MAX_ENERGY * Decimal("0.2"))
ply.matteryPlayer.androidEnergy.batteryLevel = PlayerConfig.ANDROID_MAX_ENERGY * Decimal("0.2") // если смерть была от разряда батареи, то предотвращаем софтлок
while (ply.matteryPlayer.deathLog.size > 6) {
ply.matteryPlayer.deathLog.removeFirst()
@ -1528,14 +1450,14 @@ class MatteryPlayer(val ply: Player) {
* hooked into LivingEntity through coremod script
*/
@JvmStatic
fun addEatEffectHook(iterator: Iterator<com.mojang.datafixers.util.Pair<MobEffectInstance, Float>>, entity: LivingEntity): Iterator<com.mojang.datafixers.util.Pair<MobEffectInstance, Float>> {
fun addEatEffectHook(iterator: Iterator<FoodProperties.PossibleEffect>, entity: LivingEntity): Iterator<FoodProperties.PossibleEffect> {
if (entity !is Player) {
return iterator
}
if (entity.matteryPlayer.isAndroid) {
return iterator.filter {
it.first.effect != MobEffects.HUNGER
it.effect().effect != MobEffects.HUNGER
}
}

View File

@ -1,9 +1,9 @@
package ru.dbotthepony.mc.otm.android
package ru.dbotthepony.mc.otm.player.android
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.client.Camera
import net.neoforged.neoforge.client.event.RenderLevelStageEvent
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.client.render.DynamicBufferSource
abstract class AndroidActiveFeature(type: AndroidFeatureType<*>, android: MatteryPlayer) : AndroidSwitchableFeature(type, android) {

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.android
package ru.dbotthepony.mc.otm.player.android
import net.minecraft.core.HolderLookup
import net.minecraft.nbt.CompoundTag
@ -7,7 +7,7 @@ import net.neoforged.neoforge.event.entity.living.LivingIncomingDamageEvent
import ru.dbotthepony.mc.otm.network.syncher.SynchableGroup
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.core.nbt.set
abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: MatteryPlayer) : INBTSerializable<CompoundTag> {

View File

@ -1,10 +1,10 @@
package ru.dbotthepony.mc.otm.android
package ru.dbotthepony.mc.otm.player.android
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.ComponentContents
import net.minecraft.network.chat.MutableComponent
import net.minecraft.network.chat.contents.TranslatableContents
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.core.getKeyNullable
import ru.dbotthepony.mc.otm.registry.MRegistry

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.android
package ru.dbotthepony.mc.otm.player.android
import net.minecraft.ChatFormatting
import net.minecraft.core.HolderLookup
@ -13,7 +13,7 @@ import ru.dbotthepony.mc.otm.network.syncher.SynchableGroup
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.awareItemsStream
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.android
package ru.dbotthepony.mc.otm.player.android
import com.google.gson.JsonObject
import it.unimi.dsi.fastutil.objects.ObjectArraySet

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.android
package ru.dbotthepony.mc.otm.player.android
import com.mojang.serialization.Codec
import com.mojang.serialization.MapCodec
@ -9,7 +9,7 @@ import net.minecraft.network.chat.ComponentSerialization
import net.neoforged.bus.api.IEventBus
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.client.ShiftPressedCond
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.config.PlayerConfig
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.util.formatPower
@ -29,35 +29,76 @@ object AndroidResearchDescriptions {
val ENDER_TELEPORTER: AndroidResearchDescription.Singleton by registrar.register("ender_teleporter") {
AndroidResearchDescription.singleton {
TranslatableComponent("otm.gui.power_cost_per_use", AndroidConfig.EnderTeleporter.ENERGY_COST.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW)) }
TranslatableComponent(
"otm.gui.power_cost_per_use",
PlayerConfig.EnderTeleporter.ENERGY_COST.formatPower(formatAsReadable = ShiftPressedCond).copy()
.withStyle(ChatFormatting.YELLOW)
)
}
}
val FALL_DAMPENERS: AndroidResearchDescription.Leveled by registrar.register("fall_dampeners") {
AndroidResearchDescription.Leveled { _, list, level ->
list.add(TranslatableComponent("otm.fall_dampeners.description",
TextComponent("%.1f".format((AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_P * level).toFloat().coerceIn(0f, 1f) * 100f)).withStyle(ChatFormatting.YELLOW),
TextComponent("%.1f".format((AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_F * level).toFloat())).withStyle(ChatFormatting.YELLOW),
)) }
list.add(
TranslatableComponent(
"otm.fall_dampeners.description",
TextComponent(
"%.1f".format(
(PlayerConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_P * level).toFloat().coerceIn(0f, 1f) * 100f
)
).withStyle(ChatFormatting.YELLOW),
TextComponent("%.1f".format((PlayerConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_F * level).toFloat())).withStyle(
ChatFormatting.YELLOW
),
)
)
}
}
val SWIM_BOOSTERS: AndroidResearchDescription.Leveled by registrar.register("swim_boosters") {
AndroidResearchDescription.Leveled { _, list, level ->
list.add(TranslatableComponent(
"android_research.overdrive_that_matters.swim_boosters.description",
TextComponent("%.1f".format(AndroidConfig.SWIM_BOOSTERS * (1 + level) * 100.0)).withStyle(ChatFormatting.YELLOW)
)) }
list.add(
TranslatableComponent(
"android_research.overdrive_that_matters.swim_boosters.description",
TextComponent("%.1f".format(PlayerConfig.SWIM_BOOSTERS * (1 + level) * 100.0)).withStyle(
ChatFormatting.YELLOW
)
)
)
}
}
val ITEM_MAGNET: AndroidResearchDescription.Singleton by registrar.register("item_magnet") {
AndroidResearchDescription.singleton { TranslatableComponent("otm.gui.power_cost_per_tick", AndroidConfig.Magnet.POWER_DRAW.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW)) }
AndroidResearchDescription.singleton {
TranslatableComponent(
"otm.gui.power_cost_per_tick",
PlayerConfig.Magnet.POWER_DRAW.formatPower(
formatAsReadable = ShiftPressedCond
).copy().withStyle(ChatFormatting.YELLOW)
)
}
}
val JUMP_BOOST: AndroidResearchDescription.Singleton by registrar.register("jump_boost") {
AndroidResearchDescription.singleton { TranslatableComponent("otm.gui.power_cost_per_use", AndroidConfig.JumpBoost.ENERGY_COST.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW)) }
AndroidResearchDescription.singleton {
TranslatableComponent(
"otm.gui.power_cost_per_use",
PlayerConfig.JumpBoost.ENERGY_COST.formatPower(
formatAsReadable = ShiftPressedCond
).copy().withStyle(ChatFormatting.YELLOW)
)
}
}
val SHOCKWAVE: AndroidResearchDescription.Singleton by registrar.register("shockwave") {
AndroidResearchDescription.singleton { TranslatableComponent("otm.gui.power_cost_per_use", AndroidConfig.Shockwave.ENERGY_COST.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW)) }
AndroidResearchDescription.singleton {
TranslatableComponent(
"otm.gui.power_cost_per_use",
PlayerConfig.Shockwave.ENERGY_COST.formatPower(
formatAsReadable = ShiftPressedCond
).copy().withStyle(ChatFormatting.YELLOW)
)
}
}
}
@ -138,7 +179,7 @@ object PlainAndroidResearchDescription : AndroidResearchDescription.Type<PlainAn
RecordCodecBuilder.mapCodec {
it.group(
ComponentSerialization.CODEC.fieldOf("line").forGetter { it.line }
).apply(it, ::Instance)
).apply(it, PlainAndroidResearchDescription::Instance)
}
}
}

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.android
package ru.dbotthepony.mc.otm.player.android
import com.google.common.collect.ImmutableMap
import com.google.gson.GsonBuilder
@ -23,8 +23,7 @@ import ru.dbotthepony.mc.otm.MINECRAFT_SERVER
import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.SERVER_IS_LIVE
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.core.fromJsonStrict
import ru.dbotthepony.mc.otm.core.fromNetwork
@ -109,7 +108,10 @@ object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().s
}
val SYNC_TYPE = CustomPacketPayload.Type<SyncPacket>(ResourceLocation(OverdriveThatMatters.MOD_ID, "research_sync"))
val SYNC_CODEC: StreamCodec<FriendlyByteBuf, SyncPacket> = StreamCodec.ofMember(SyncPacket::write, ::readSyncPacket)
val SYNC_CODEC: StreamCodec<FriendlyByteBuf, SyncPacket> = StreamCodec.ofMember(
SyncPacket::write,
AndroidResearchManager::readSyncPacket
)
class SyncPacket(val collection: Collection<AndroidResearchType>) : CustomPacketPayload {
fun write(buff: FriendlyByteBuf) {

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.android
package ru.dbotthepony.mc.otm.player.android
import com.mojang.serialization.Codec
import com.mojang.serialization.MapCodec
@ -16,8 +16,8 @@ object AndroidResearchResults {
private val registrar = MDeferredRegister(AndroidResearchResult.registryKey, OverdriveThatMatters.MOD_ID)
init {
registrar.register("feature") { AndroidResearchResult.Feature.Companion }
registrar.register("feature_level") { AndroidResearchResult.FeatureLevel.Companion }
registrar.register("feature") { AndroidResearchResult.Feature }
registrar.register("feature_level") { AndroidResearchResult.FeatureLevel }
}
private object NanobotsArmorStrength : AndroidResearchResult.Singleton<NanobotsArmorStrength> {
@ -90,7 +90,7 @@ interface AndroidResearchResult {
it.group(
ResourceLocation.CODEC.fieldOf("id").forGetter(Feature::id),
Codec.BOOL.optionalFieldOf("optional", false).forGetter(Feature::optional)
).apply(it, ::Feature)
).apply(it, AndroidResearchResult::Feature)
}
}
}
@ -99,7 +99,8 @@ interface AndroidResearchResult {
/**
* Increases level of specific android feature [id] by specified amount [levels]
*/
class FeatureLevel(val id: ResourceLocation, val optional: Boolean = false, val levels: Int = 1) : AndroidResearchResult {
class FeatureLevel(val id: ResourceLocation, val optional: Boolean = false, val levels: Int = 1) :
AndroidResearchResult {
val feature = MRegistry.ANDROID_FEATURES.get(id) ?: if (optional) null else throw NoSuchElementException("Unknown android feature $id")
override val type: Type<*>
@ -132,7 +133,7 @@ interface AndroidResearchResult {
ResourceLocation.CODEC.fieldOf("id").forGetter(FeatureLevel::id),
Codec.BOOL.optionalFieldOf("optional", false).forGetter(FeatureLevel::optional),
Codec.INT.optionalFieldOf("levels", 1).forGetter(FeatureLevel::levels),
).apply(it, ::FeatureLevel)
).apply(it, AndroidResearchResult::FeatureLevel)
}
}
}

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.android
package ru.dbotthepony.mc.otm.player.android
import com.google.common.collect.ImmutableList
import com.google.gson.JsonObject
@ -131,10 +131,10 @@ class AndroidResearchType(
it.group(
ResourceLocation.CODEC.fieldOf("id").forGetter(Reference::id),
Codec.BOOL.optionalFieldOf("optional", false).forGetter(Reference::optional)
).apply(it, ::Reference)
).apply(it, AndroidResearchType::Reference)
})
.xmap(
{ c -> c.map(::Reference, Function.identity()) },
{ c -> c.map(AndroidResearchType::Reference, Function.identity()) },
{ c -> if (c.optional) Either.right(c) else Either.left(c.id) }
)
}

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.android
package ru.dbotthepony.mc.otm.player.android
import net.minecraft.client.multiplayer.ClientLevel
import net.minecraft.core.HolderLookup
@ -7,7 +7,7 @@ import net.minecraft.server.level.ServerPlayer
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.nbt.set

View File

@ -1,10 +1,10 @@
package ru.dbotthepony.mc.otm.android.feature
package ru.dbotthepony.mc.otm.player.android.feature
import net.minecraft.world.entity.ai.attributes.AttributeModifier
import net.minecraft.world.entity.ai.attributes.Attributes
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.player.android.AndroidFeature
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.registry.game.AndroidFeatures

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.android.feature
package ru.dbotthepony.mc.otm.player.android.feature
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack
@ -25,16 +25,16 @@ import net.neoforged.neoforge.event.entity.living.LivingDeathEvent
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidActiveFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.player.android.AndroidActiveFeature
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.DynamicBufferSource
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.client.render.linesIgnoreZRenderType
import ru.dbotthepony.mc.otm.client.render.sprites.sprite
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.config.PlayerConfig
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.core.genericPositions
import ru.dbotthepony.mc.otm.core.holder
@ -49,7 +49,6 @@ import ru.dbotthepony.mc.otm.core.math.rotateXDegrees
import ru.dbotthepony.mc.otm.core.math.rotateYDegrees
import ru.dbotthepony.mc.otm.core.math.shortestDistanceBetween
import ru.dbotthepony.mc.otm.core.math.times
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.milliTime
import ru.dbotthepony.mc.otm.registry.game.AndroidFeatures
import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger
@ -61,10 +60,10 @@ class EnderTeleporterFeature(capability: MatteryPlayer) : AndroidActiveFeature(A
private set
override val maxCooldown: Int
get() = AndroidConfig.EnderTeleporter.COOLDOWN
get() = PlayerConfig.EnderTeleporter.COOLDOWN
private fun canUse(): Boolean {
return !isOnCooldown && android.androidEnergy.extractEnergyExact(AndroidConfig.EnderTeleporter.ENERGY_COST, true)
return !isOnCooldown && android.androidEnergy.extractEnergyExact(PlayerConfig.EnderTeleporter.ENERGY_COST, true)
}
private fun isValidGround(blockPos: BlockPos): Boolean {
@ -113,14 +112,14 @@ class EnderTeleporterFeature(capability: MatteryPlayer) : AndroidActiveFeature(A
}
private fun tryToPhaseThroughWall(blockPos: BlockPos, normal: Vec3i): TraceResult? {
val phasedBlocks = ArrayList<BlockPos>(AndroidConfig.EnderTeleporter.MAX_PHASE_DISTANCE)
val phasedBlocks = ArrayList<BlockPos>(PlayerConfig.EnderTeleporter.MAX_PHASE_DISTANCE)
phasedBlocks.add(blockPos)
for (extend in 1 .. AndroidConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
for (extend in 1 .. PlayerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
val pos = blockPos + normal * extend
if (isAirGap(pos)) {
for (y in 0 .. AndroidConfig.EnderTeleporter.MAX_PHASE_DISTANCE - extend) {
for (y in 0 .. PlayerConfig.EnderTeleporter.MAX_PHASE_DISTANCE - extend) {
val newPos = BlockPos(pos.x, pos.y - y, pos.z)
if (isValidPosition(newPos)) {
@ -143,7 +142,7 @@ class EnderTeleporterFeature(capability: MatteryPlayer) : AndroidActiveFeature(A
val result = ply.level().clip(ClipContext(
headPosition,
headPosition + aimVector * (AndroidConfig.EnderTeleporter.MAX_DISTANCE * 2.0),
headPosition + aimVector * (PlayerConfig.EnderTeleporter.MAX_DISTANCE * 2.0),
ClipContext.Block.COLLIDER,
ClipContext.Fluid.NONE,
ply
@ -159,7 +158,7 @@ class EnderTeleporterFeature(capability: MatteryPlayer) : AndroidActiveFeature(A
!ply.isShiftKeyDown &&
result.direction == Direction.UP &&
isValidPosition(result.blockPos.above()) &&
shortestDistanceBetween(testPositions, result.blockPos.above().asVector()) <= AndroidConfig.EnderTeleporter.MAX_DISTANCE
shortestDistanceBetween(testPositions, result.blockPos.above().asVector()) <= PlayerConfig.EnderTeleporter.MAX_DISTANCE
) {
return TraceResult(result.blockPos.above())
}
@ -217,14 +216,14 @@ class EnderTeleporterFeature(capability: MatteryPlayer) : AndroidActiveFeature(A
if (!isAirGap(pos)) {
phasedBlocks++
if (phasedBlocks >= AndroidConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
if (phasedBlocks >= PlayerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
break
}
phasedBlocksList.add(pos)
}
if (shortestDistanceBetween(testPositions, pos.asVector()) > AndroidConfig.EnderTeleporter.MAX_DISTANCE) {
if (shortestDistanceBetween(testPositions, pos.asVector()) > PlayerConfig.EnderTeleporter.MAX_DISTANCE) {
break
}
@ -271,14 +270,14 @@ class EnderTeleporterFeature(capability: MatteryPlayer) : AndroidActiveFeature(A
if (!isAirGap(pos)) {
phasedBlocks++
if (phasedBlocks >= AndroidConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
if (phasedBlocks >= PlayerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
break
}
phasedBlocksList.add(pos)
}
if (shortestDistanceBetween(testPositions, pos.asVector()) > AndroidConfig.EnderTeleporter.MAX_DISTANCE) {
if (shortestDistanceBetween(testPositions, pos.asVector()) > PlayerConfig.EnderTeleporter.MAX_DISTANCE) {
break
}
@ -303,17 +302,17 @@ class EnderTeleporterFeature(capability: MatteryPlayer) : AndroidActiveFeature(A
val event = EventHooks.onEnderTeleport(ply, blockPos.x + 0.5, blockPos.y.toDouble(), blockPos.z + 0.5)
if (event.isCanceled) {
(ply as ServerPlayer).connection.send(ClientboundSoundEntityPacket(SoundEvents.ITEM_BREAK.holder, SoundSource.PLAYERS, ply, 0.3f, 0.5f, ply.level().otmRandom.nextLong()))
(ply as ServerPlayer).connection.send(ClientboundSoundEntityPacket(SoundEvents.ITEM_BREAK.holder, SoundSource.PLAYERS, ply, 0.3f, 0.5f, ply.level().random.nextLong()))
return false
}
putOnCooldown()
lastTeleport = ply.server!!.tickCount
android.androidEnergy.extractEnergy(AndroidConfig.EnderTeleporter.ENERGY_COST, false)
android.androidEnergy.extractEnergy(PlayerConfig.EnderTeleporter.ENERGY_COST, false)
ply.level().playSound(null, ply, SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 0.3f, 0.8f + ply.level().otmRandom.nextFloat() * 0.4f)
ply.level().playSound(null, ply, SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 0.3f, 0.8f + ply.level().random.nextFloat() * 0.4f)
ply.teleportTo(event.targetX, event.targetY, event.targetZ)
ply.level().playSound(null, ply, SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 1f, 0.8f + ply.level().otmRandom.nextFloat() * 0.4f)
ply.level().playSound(null, ply, SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 1f, 0.8f + ply.level().random.nextFloat() * 0.4f)
ply.deltaMovement = Vector(0.0, 0.0, 0.0)
ply.resetFallDistance()

View File

@ -1,10 +1,10 @@
package ru.dbotthepony.mc.otm.android.feature
package ru.dbotthepony.mc.otm.player.android.feature
import net.minecraft.world.entity.ai.attributes.AttributeModifier
import net.minecraft.world.entity.ai.attributes.Attributes
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.player.android.AndroidFeature
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.registry.game.AndroidFeatures

View File

@ -1,10 +1,10 @@
package ru.dbotthepony.mc.otm.android.feature
package ru.dbotthepony.mc.otm.player.android.feature
import net.minecraft.server.level.ServerPlayer
import net.neoforged.neoforge.event.entity.living.LivingIncomingDamageEvent
import ru.dbotthepony.mc.otm.android.AndroidFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.player.android.AndroidFeature
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.config.PlayerConfig
import ru.dbotthepony.mc.otm.core.isFall
import ru.dbotthepony.mc.otm.registry.game.AndroidFeatures
import ru.dbotthepony.mc.otm.triggers.FallDampenersSaveTrigger
@ -12,8 +12,8 @@ import ru.dbotthepony.mc.otm.triggers.FallDampenersSaveTrigger
class FallDampenersFeature(capability: MatteryPlayer) : AndroidFeature(AndroidFeatures.FALL_DAMPENERS, capability) {
override fun onHurt(event: LivingIncomingDamageEvent) {
if (event.source.isFall) {
val reduction = (AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_P * (level + 1)).toFloat().coerceIn(0f, 1f)
val flat = (AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_F * (level + 1)).toFloat().coerceIn(0f, Float.MAX_VALUE)
val reduction = (PlayerConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_P * (level + 1)).toFloat().coerceIn(0f, 1f)
val flat = (PlayerConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_F * (level + 1)).toFloat().coerceIn(0f, Float.MAX_VALUE)
val old = event.amount
event.amount = ((event.amount - flat) * (1f - reduction)).coerceAtLeast(0f)

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.android.feature
package ru.dbotthepony.mc.otm.player.android.feature
import net.minecraft.client.multiplayer.ClientLevel
import net.minecraft.network.FriendlyByteBuf
@ -11,9 +11,9 @@ import net.neoforged.neoforge.network.PacketDistributor
import net.neoforged.neoforge.network.handling.IPayloadContext
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.config.PlayerConfig
import ru.dbotthepony.mc.otm.player.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.minecraft
@ -60,7 +60,10 @@ class ItemEntityDataPacket(val itemUUID: Int, val owner: UUID? = null, val age:
companion object {
val TYPE = CustomPacketPayload.Type<ItemEntityDataPacket>(ResourceLocation(OverdriveThatMatters.MOD_ID, "item_entity_data"))
val CODEC: StreamCodec<FriendlyByteBuf, ItemEntityDataPacket> = StreamCodec.ofMember(ItemEntityDataPacket::write, ::read)
val CODEC: StreamCodec<FriendlyByteBuf, ItemEntityDataPacket> = StreamCodec.ofMember(
ItemEntityDataPacket::write,
Companion::read
)
fun read(buff: FriendlyByteBuf): ItemEntityDataPacket {
return ItemEntityDataPacket(buff.readVarInt(), if (buff.readBoolean()) buff.readUUID() else null, buff.readVarInt(), buff.readVarInt(), buff.readBoolean())
@ -76,13 +79,13 @@ class ItemMagnetFeature(capability: MatteryPlayer) : AndroidSwitchableFeature(An
private val clientPredicate = Predicate<Entity> { it is ItemEntity && (datatable[it] ?: SharedItemEntityData.EMPTY).let { !it.hasPickupDelay && (it.owner == null || it.owner != ply.uuid || it.lifespan - it.age <= 200) } }
private fun doTick(server: Boolean) {
if (ply.isSpectator || server && !android.androidEnergy.extractEnergyExact(AndroidConfig.Magnet.POWER_DRAW, true)) {
if (ply.isSpectator || server && !android.androidEnergy.extractEnergyExact(PlayerConfig.Magnet.POWER_DRAW, true)) {
return
}
val entities = ply.level().getEntitiesInEllipsoid(
ply.position,
Vector(AndroidConfig.Magnet.RADIUS_HORIZONTAL, AndroidConfig.Magnet.RADIUS_VERTICAL, AndroidConfig.Magnet.RADIUS_HORIZONTAL),
Vector(PlayerConfig.Magnet.RADIUS_HORIZONTAL, PlayerConfig.Magnet.RADIUS_VERTICAL, PlayerConfig.Magnet.RADIUS_HORIZONTAL),
if (server) Predicate<Entity> { it is ItemEntity } else clientPredicate
)
@ -101,7 +104,7 @@ class ItemMagnetFeature(capability: MatteryPlayer) : AndroidSwitchableFeature(An
if (data.position.distanceToSqr(ent.position) < 1.0) {
data.ticksSinceActivity++
} else {
if (!android.androidEnergy.extractEnergyExact(AndroidConfig.Magnet.POWER_DRAW, false)) {
if (!android.androidEnergy.extractEnergyExact(PlayerConfig.Magnet.POWER_DRAW, false)) {
return
}
@ -117,7 +120,7 @@ class ItemMagnetFeature(capability: MatteryPlayer) : AndroidSwitchableFeature(An
override fun tickClient() {
super.tickClient()
if (!ply.isSpectator && isActive && android.androidEnergy.extractEnergyExact(AndroidConfig.Magnet.POWER_DRAW, true)) {
if (!ply.isSpectator && isActive && android.androidEnergy.extractEnergyExact(PlayerConfig.Magnet.POWER_DRAW, true)) {
doTick(false)
}
}

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.android.feature
package ru.dbotthepony.mc.otm.player.android.feature
import net.minecraft.server.level.ServerPlayer
import net.minecraft.sounds.SoundSource
@ -6,12 +6,12 @@ import net.neoforged.neoforge.network.PacketDistributor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.player.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.config.PlayerConfig
import ru.dbotthepony.mc.otm.config.ClientConfig
import ru.dbotthepony.mc.otm.core.math.Vector
import ru.dbotthepony.mc.otm.core.math.plus
@ -24,7 +24,7 @@ class JumpBoostFeature(capability: MatteryPlayer) : AndroidSwitchableFeature(And
private var tickCooldownClient = false
override val maxCooldown: Int
get() = (AndroidConfig.JumpBoost.BASE_COOLDOWN - AndroidConfig.JumpBoost.COOLDOWN_REDUCTION * level).coerceAtLeast(0)
get() = (PlayerConfig.JumpBoost.BASE_COOLDOWN - PlayerConfig.JumpBoost.COOLDOWN_REDUCTION * level).coerceAtLeast(0)
override var cooldown by syncher.int(setter = setter@{ access, value ->
access.accept(value)
@ -46,8 +46,8 @@ class JumpBoostFeature(capability: MatteryPlayer) : AndroidSwitchableFeature(And
val old = lastGround
lastGround = ply.onGround()
if (isActive && cooldown <= 0 && old != lastGround && !lastGround && isJumping && isShifting && ply.xRot <= ClientConfig.JUMP_BOOST_LOOK_ANGLE && android.androidEnergy.extractEnergyExact(AndroidConfig.JumpBoost.ENERGY_COST, true)) {
ply.deltaMovement += Vector(0.0, AndroidConfig.JumpBoost.POWER * (level + 1) / 20.0, 0.0)
if (isActive && cooldown <= 0 && old != lastGround && !lastGround && isJumping && isShifting && ply.xRot <= ClientConfig.JUMP_BOOST_LOOK_ANGLE && android.androidEnergy.extractEnergyExact(PlayerConfig.JumpBoost.ENERGY_COST, true)) {
ply.deltaMovement += Vector(0.0, PlayerConfig.JumpBoost.POWER * (level + 1) / 20.0, 0.0)
putOnCooldown()
PacketDistributor.sendToServer(TriggerJumpBoostPacket)

View File

@ -1,13 +1,13 @@
package ru.dbotthepony.mc.otm.android.feature
package ru.dbotthepony.mc.otm.player.android.feature
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.attributes.AttributeModifier
import net.minecraft.world.entity.ai.attributes.Attributes
import net.minecraft.world.entity.player.Player
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.player.android.AndroidFeature
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.registry.game.AndroidFeatures
@ -17,7 +17,7 @@ class LimbOverclockingFeature(android: MatteryPlayer) : AndroidFeature(AndroidFe
if (speed != null) {
speed.removeModifier(MODIFIER_ID)
speed.addPermanentModifier(AttributeModifier(MODIFIER_ID,(level + 1) * 0.08, AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL))
speed.addPermanentModifier(AttributeModifier(MODIFIER_ID, (level + 1) * 0.08, AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL))
}
val attackSpeed = ply.getAttribute(Attributes.ATTACK_SPEED)

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.android.feature
package ru.dbotthepony.mc.otm.player.android.feature
import net.minecraft.core.HolderLookup
import net.minecraft.nbt.CompoundTag
@ -7,8 +7,8 @@ import net.minecraft.tags.DamageTypeTags
import net.neoforged.neoforge.event.entity.living.LivingIncomingDamageEvent
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.android.AndroidFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.player.android.AndroidFeature
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.core.isBypassArmor
import ru.dbotthepony.mc.otm.core.math.Decimal

View File

@ -1,13 +1,13 @@
package ru.dbotthepony.mc.otm.android.feature
package ru.dbotthepony.mc.otm.player.android.feature
import net.minecraft.core.HolderLookup
import net.minecraft.nbt.CompoundTag
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.level.GameRules
import net.neoforged.neoforge.event.entity.living.LivingIncomingDamageEvent
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.android.AndroidFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.config.PlayerConfig
import ru.dbotthepony.mc.otm.player.android.AndroidFeature
import ru.dbotthepony.mc.otm.player.MatteryPlayer
import ru.dbotthepony.mc.otm.registry.game.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.StatNames
import ru.dbotthepony.mc.otm.core.nbt.set
@ -21,16 +21,16 @@ class NanobotsRegenerationFeature(android: MatteryPlayer) : AndroidFeature(Andro
if (ply.isHurt && ply.level().gameRules.getBoolean(GameRules.RULE_NATURAL_REGENERATION)) {
ticksPassed++
val waitTime = AndroidConfig.NanobotsRegeneration.COOLDOWN.getOrElse(healTicks) { AndroidConfig.NanobotsRegeneration.COOLDOWN.last() }
val waitTime = PlayerConfig.NanobotsRegeneration.COOLDOWN.getOrElse(healTicks) { PlayerConfig.NanobotsRegeneration.COOLDOWN.last() }
if (ticksPassed > waitTime) {
val missingHealth = (ply.maxHealth - ply.health).coerceAtMost(2f)
val power = AndroidConfig.NanobotsRegeneration.ENERGY_PER_HITPOINT * missingHealth
val power = PlayerConfig.NanobotsRegeneration.ENERGY_PER_HITPOINT * missingHealth
val extracted = android.androidEnergy.extractEnergy(power, false)
if (extracted.isPositive) {
healTicks = (healTicks + 1).coerceAtMost(level)
val healed = (extracted / AndroidConfig.NanobotsRegeneration.ENERGY_PER_HITPOINT).toFloat()
val healed = (extracted / PlayerConfig.NanobotsRegeneration.ENERGY_PER_HITPOINT).toFloat()
ply.heal(healed)
(ply as ServerPlayer?)?.awardStat(StatNames.HEALTH_REGENERATED, (healed * 10f).roundToInt())
ticksPassed = 0

Some files were not shown because too many files have changed in this diff Show More