командная работа

- вычленение команд в отдельные файлы
- команда /android теперь может выдавать/забирать исследования
This commit is contained in:
YuRaNnNzZZ 2024-10-11 22:21:13 +03:00
parent 04b71b7cc8
commit 35b8652161
Signed by: YuRaNnNzZZ
GPG Key ID: 5F71738C85A6006D
11 changed files with 264 additions and 98 deletions

View File

@ -395,6 +395,7 @@ private fun misc(provider: MatteryLanguageProvider) {
misc("android_station.research.low_power", "Android Station is low on power! Can't research!")
misc("android_station.research.researched", "Researched!")
misc("android_station.research.can_be_researched", "Ready to research!")
misc("android_station.research.can_not_afford", "Missing required items!")
misc("android_station.research.can_not_be_researched", "Can't research!")
misc("android_station.research.xp_cost", "Experience cost: %s levels")
misc("android_station.research.item", "Requires %s x%s")

View File

@ -403,6 +403,7 @@ private fun misc(provider: MatteryLanguageProvider) {
misc("android_station.research.low_power", "Мало питания у станции андроидов! Исследования недоступны!")
misc("android_station.research.researched", "Исследовано!")
misc("android_station.research.can_be_researched", "Готово к исследованию!")
misc("android_station.research.can_not_afford", "Не хватает предметов!")
misc("android_station.research.can_not_be_researched", "Нельзя исследовать!")
misc("android_station.research.xp_cost", "Требуется %s уровней Опыта")
misc("android_station.research.item", "Требует %s %s шт.")

View File

@ -58,6 +58,7 @@ import ru.dbotthepony.mc.otm.matter.IMatterFunction;
import ru.dbotthepony.mc.otm.matter.MatterManager;
import ru.dbotthepony.mc.otm.network.*;
import ru.dbotthepony.mc.otm.registry.*;
import ru.dbotthepony.mc.otm.server.MCommands;
import ru.dbotthepony.mc.otm.storage.StorageStack;
import ru.dbotthepony.mc.otm.triggers.KillAsAndroidTrigger;
import top.theillusivec4.curios.api.CuriosApi;
@ -127,6 +128,7 @@ public final class OverdriveThatMatters {
MArmorMaterials.INSTANCE.register(bus);
MCriteriaTriggers.INSTANCE.register(bus);
MStats.INSTANCE.register(bus);
CommandArgumentTypes.INSTANCE.register(bus);
StorageStack.Companion.register(bus);
MatteryChestMenu.Companion.register(bus);
@ -197,7 +199,6 @@ public final class OverdriveThatMatters {
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayer.Companion::onPlayerSpawnPhantoms);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayer.Companion::onStartTracking);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayer.Companion::onStopTracking);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayer.Companion::addCommands);
EVENT_BUS.addListener(EventPriority.NORMAL, QuantumBatteryItem.Companion::tick);
EVENT_BUS.addListener(EventPriority.LOWEST, PortableCondensationDriveItem.Companion::onPickupEvent);
@ -228,6 +229,8 @@ public final class OverdriveThatMatters {
EVENT_BUS.addListener(EventPriority.NORMAL, DevChestBlockEntity.Companion::mappingsChanged);
EVENT_BUS.addListener(EventPriority.NORMAL, MCommands.INSTANCE::register);
if (ModList.get().isLoaded(CuriosApi.MODID)) {
EVENT_BUS.addListener(EventPriority.NORMAL, CuriosCompatKt::onCuriosSlotModifiersUpdated);
}

View File

@ -173,17 +173,9 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
return true
}
val canResearch: Boolean get() {
if (!consumeResearchCost(simulate = true)) {
return false
}
if (!isPrerequisitesResearched || (!ply.isCreative && isAnyBlockerResearched)) {
return false
}
return true
}
val canResearch: Boolean get() = !(!isPrerequisitesResearched || (!ply.isCreative && isAnyBlockerResearched))
val canAfford: Boolean get() = consumeResearchCost(simulate = true)
val readyToResearch: Boolean get() = canResearch && canAfford
/**
* Determines if this research is already blocked directly by another research.
@ -246,12 +238,12 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
return true
}
fun research(force: Boolean = false): Boolean {
fun research(force: Boolean = false, free: Boolean = false): Boolean {
if (isResearched) {
return false
}
if (force || canResearch && consumeResearchCost(false)) {
if (force || canResearch && (free || canAfford && consumeResearchCost(false))) {
onResearched()
isResearched = true

View File

@ -8,8 +8,6 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
import net.minecraft.ChatFormatting
import net.minecraft.client.model.PlayerModel
import net.minecraft.client.player.AbstractClientPlayer
import net.minecraft.commands.Commands
import net.minecraft.commands.arguments.EntityArgument
import net.minecraft.core.HolderLookup
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.nbt.CompoundTag
@ -46,7 +44,6 @@ import net.neoforged.bus.api.Event
import net.neoforged.bus.api.ICancellableEvent
import net.neoforged.neoforge.common.CommonHooks
import net.neoforged.neoforge.common.NeoForge
import net.neoforged.neoforge.event.RegisterCommandsEvent
import net.neoforged.neoforge.event.entity.living.LivingDeathEvent
import net.neoforged.neoforge.event.entity.living.LivingIncomingDamageEvent
import net.neoforged.neoforge.event.entity.living.MobEffectEvent
@ -54,7 +51,6 @@ import net.neoforged.neoforge.event.entity.player.PlayerEvent
import net.neoforged.neoforge.event.entity.player.PlayerSpawnPhantomsEvent
import net.neoforged.neoforge.event.tick.PlayerTickEvent
import net.neoforged.neoforge.network.PacketDistributor
import net.neoforged.neoforge.server.command.EnumArgument
import org.apache.logging.log4j.LogManager
import org.joml.Vector4f
import ru.dbotthepony.kommons.collect.ListenableMap
@ -1412,76 +1408,6 @@ class MatteryPlayer(val ply: Player) {
companion object {
private val offhandSlotRange = IntSet.of(40)
private fun setExoPack(players: Collection<Player>, hasExoPack: Boolean): Int {
for (player in players) {
player.matteryPlayer.hasExopack = hasExoPack
player.matteryPlayer._exoPackMenu = null
}
return players.size
}
private fun makeAndroid(players: Collection<Player>): Int {
for (player in players) {
player.matteryPlayer.becomeAndroid()
}
return players.size
}
private fun makeHuman(players: Collection<Player>): Int {
for (player in players) {
player.matteryPlayer.becomeHumane()
}
return players.size
}
private fun setUpgrade(players: Collection<Player>, type: UpgradeType, state: Boolean): Int {
for (player in players) {
player.matteryPlayer.let { type.prop.set(it, state) }
}
return players.size
}
fun addCommands(event: RegisterCommandsEvent) {
event.dispatcher.register(
Commands.literal("exopack")
.requires { it.hasPermission(Commands.LEVEL_GAMEMASTERS) }
.then(Commands.literal("add")
.executes { setExoPack(listOf(it.source.playerOrException), true) }
.then(Commands.argument("targets", EntityArgument.players()).executes { setExoPack(EntityArgument.getPlayers(it, "targets"), true) })
)
.then(Commands.literal("remove")
.executes { setExoPack(listOf(it.source.playerOrException), false) }
.then(Commands.argument("targets", EntityArgument.players()).executes { setExoPack(EntityArgument.getPlayers(it, "targets"), false) })
)
.then(Commands.literal("upgrade")
.then(Commands.argument("type", EnumArgument.enumArgument(UpgradeType::class.java))
.then(Commands.literal("add")
.executes { setUpgrade(listOf(it.source.playerOrException), it.getArgument("type", UpgradeType::class.java), true) }
.then(Commands.argument("targets", EntityArgument.players()).executes { setUpgrade(EntityArgument.getPlayers(it, "targets"), it.getArgument("type", UpgradeType::class.java), true) }))
.then(Commands.literal("remove")
.executes { setUpgrade(listOf(it.source.playerOrException), it.getArgument("type", UpgradeType::class.java), false) }
.then(Commands.argument("targets", EntityArgument.players()).executes { setUpgrade(EntityArgument.getPlayers(it, "targets"), it.getArgument("type", UpgradeType::class.java), false) })))
)
)
event.dispatcher.register(
Commands.literal("android")
.requires { it.hasPermission(Commands.LEVEL_GAMEMASTERS) }
.then(Commands.literal("on")
.executes { makeAndroid(listOf(it.source.playerOrException)) }
.then(Commands.argument("targets", EntityArgument.players()).executes { makeAndroid(EntityArgument.getPlayers(it, "targets")) })
)
.then(Commands.literal("off")
.executes { makeHuman(listOf(it.source.playerOrException)) }
.then(Commands.argument("targets", EntityArgument.players()).executes { makeHuman(EntityArgument.getPlayers(it, "targets")) })
)
)
}
init {
WitherBoss.TARGETING_CONDITIONS.selector(WitherBoss.TARGETING_CONDITIONS.selector!!.and { it.matteryPlayer?.isAndroid != true })
WitherBoss.LIVING_ENTITY_SELECTOR = WitherBoss.LIVING_ENTITY_SELECTOR.and { it.matteryPlayer?.isAndroid != true }

View File

@ -288,7 +288,7 @@ private class AndroidResearchButton(
}
override val cursorType: CursorType
get() = if (node.isAnyBlockerResearchedIndirect && !(parent?.screen as AndroidStationScreen).menu.player.isCreative) CursorType.NOT_ALLOWED else if (node.canResearch && !node.isResearched) CursorType.HAND else CursorType.ARROW
get() = if (node.isAnyBlockerResearchedIndirect && !(parent?.screen as AndroidStationScreen).menu.player.isCreative) CursorType.NOT_ALLOWED else if (node.readyToResearch && !node.isResearched) CursorType.HAND else CursorType.ARROW
override fun innerRender(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
val hovered = screen.hoveredResearch
@ -303,7 +303,7 @@ private class AndroidResearchButton(
AndroidStationScreen.RESEARCHED
} else if (node.isAnyBlockerResearchedIndirect) {
AndroidStationScreen.ALREADY_BLOCKED
} else if (node.canResearch) {
} else if (node.readyToResearch) {
AndroidStationScreen.CAN_BE_RESEARCHED
} else {
AndroidStationScreen.CAN_NOT_BE_RESEARCHED
@ -388,7 +388,7 @@ private class AndroidResearchButton(
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
if (button == InputConstants.MOUSE_BUTTON_LEFT && minecraft.player?.isSpectator != true) {
if (node.canResearch && !node.isResearched && (parent?.screen as AndroidStationScreen).menu.energyWidget.level >= MachinesConfig.AndroidStation.ENERGY_PER_RESEARCH) {
if (node.readyToResearch && !node.isResearched && (parent?.screen as AndroidStationScreen).menu.energyWidget.level >= MachinesConfig.AndroidStation.ENERGY_PER_RESEARCH) {
if (node.type.flatBlocking.isNotEmpty()) {
queryUser(
TranslatableComponent("otm.android_station.research.confirm", node.type.displayName),
@ -420,14 +420,16 @@ private class AndroidResearchButton(
if (node.isResearched) {
list.add(TranslatableComponent("otm.android_station.research.researched").withStyle(ChatFormatting.DARK_AQUA))
} else if (node.canResearch) {
list.add(TranslatableComponent("otm.android_station.research.can_be_researched").withStyle(ChatFormatting.DARK_GREEN))
if (!enoughPower) {
list.add(TranslatableComponent("otm.android_station.research.low_power").withStyle(ChatFormatting.DARK_RED))
}
} else {
list.add(TranslatableComponent("otm.android_station.research.can_not_be_researched").withStyle(ChatFormatting.DARK_RED))
if (node.canResearch) {
if (node.canAfford) {
list.add(TranslatableComponent("otm.android_station.research.can_be_researched").withStyle(ChatFormatting.DARK_GREEN))
} else {
list.add(TranslatableComponent("otm.android_station.research.can_not_afford").withStyle(ChatFormatting.DARK_RED))
}
} else {
list.add(TranslatableComponent("otm.android_station.research.can_not_be_researched").withStyle(ChatFormatting.DARK_RED))
}
if (!enoughPower) {
list.add(TranslatableComponent("otm.android_station.research.low_power").withStyle(ChatFormatting.DARK_RED))

View File

@ -0,0 +1,20 @@
package ru.dbotthepony.mc.otm.registry
import net.minecraft.commands.synchronization.ArgumentTypeInfo
import net.minecraft.commands.synchronization.ArgumentTypeInfos
import net.minecraft.commands.synchronization.SingletonArgumentInfo
import net.minecraft.core.registries.Registries
import net.neoforged.bus.api.IEventBus
import ru.dbotthepony.mc.otm.server.command.AndroidResearchArgument
object CommandArgumentTypes {
private val registry: MDeferredRegister<ArgumentTypeInfo<*, *>> = MDeferredRegister(Registries.COMMAND_ARGUMENT_TYPE)
val ANDROID_RESEARCH by registry.register("android_research") {
ArgumentTypeInfos.registerByClass(AndroidResearchArgument::class.java, SingletonArgumentInfo.contextFree(AndroidResearchArgument.Companion::create))
}
fun register(bus: IEventBus) {
registry.register(bus)
}
}

View File

@ -0,0 +1,11 @@
package ru.dbotthepony.mc.otm.server
import net.neoforged.neoforge.event.RegisterCommandsEvent
import ru.dbotthepony.mc.otm.server.command.*
object MCommands {
fun register(event: RegisterCommandsEvent) {
ExopackCommand.register(event)
AndroidCommand.register(event)
}
}

View File

@ -0,0 +1,125 @@
package ru.dbotthepony.mc.otm.server.command
import net.minecraft.commands.Commands
import net.minecraft.commands.arguments.EntityArgument
import net.minecraft.world.entity.player.Player
import net.neoforged.neoforge.event.RegisterCommandsEvent
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.android.AndroidResearchType
import ru.dbotthepony.mc.otm.capability.matteryPlayer
object AndroidCommand {
fun register(event: RegisterCommandsEvent) {
event.dispatcher.register(
Commands.literal("android")
.requires { it.hasPermission(Commands.LEVEL_GAMEMASTERS) }
.then(Commands.literal("on")
.executes { makeAndroid(listOf(it.source.playerOrException)) }
.then(Commands.argument("targets", EntityArgument.players()).executes { makeAndroid(EntityArgument.getPlayers(it, "targets")) })
)
.then(Commands.literal("off")
.executes { makeHuman(listOf(it.source.playerOrException)) }
.then(Commands.argument("targets", EntityArgument.players()).executes { makeHuman(EntityArgument.getPlayers(it, "targets")) })
)
.then(
Commands.literal("research")
.then(
Commands.literal("grant")
.then(
Commands.argument("targets", EntityArgument.players())
.then(
Commands.argument("research", AndroidResearchArgument.create())
.executes {
grantResearch(EntityArgument.getPlayers(it, "targets"), AndroidResearchArgument.getResearchType(it, "research"))
}
.then(
Commands.literal("force")
.executes {
grantResearch(EntityArgument.getPlayers(it, "targets"), AndroidResearchArgument.getResearchType(it, "research"), true)
}
)
)
.then(
Commands.literal("*")
.executes {
val players = EntityArgument.getPlayers(it, "targets")
AndroidResearchManager.researchMap.map { a -> a.value }.forEach { a ->
grantResearch(players, a)
}
players.size
}
.then(
Commands.literal("force")
.executes {
val players = EntityArgument.getPlayers(it, "targets")
AndroidResearchManager.researchMap.map { a -> a.value }.forEach { a ->
grantResearch(players, a, true)
}
players.size
}
)
)
)
)
.then(
Commands.literal("revoke")
.then(
Commands.argument("targets", EntityArgument.players())
.then(
Commands.argument("research", AndroidResearchArgument.create())
.executes {
revokeResearch(EntityArgument.getPlayers(it, "targets"), AndroidResearchArgument.getResearchType(it, "research"))
}
)
.then(
Commands.literal("*")
.executes {
val players = EntityArgument.getPlayers(it, "targets")
AndroidResearchManager.researchMap.map { a -> a.value }.forEach { a ->
revokeResearch(players, a)
}
players.size
}
)
)
)
)
)
}
private fun grantResearch(players: Collection<Player>, type: AndroidResearchType, force: Boolean = false): Int {
for (player in players) {
player.matteryPlayer.getResearch(type).research(force, free = true)
}
return players.size
}
private fun revokeResearch(players: Collection<Player>, type: AndroidResearchType): Int {
for (player in players) {
player.matteryPlayer.getResearch(type).unResearch()
}
return players.size
}
private fun makeAndroid(players: Collection<Player>): Int {
for (player in players) {
player.matteryPlayer.becomeAndroid()
}
return players.size
}
private fun makeHuman(players: Collection<Player>): Int {
for (player in players) {
player.matteryPlayer.becomeHumane()
}
return players.size
}
}

View File

@ -0,0 +1,31 @@
package ru.dbotthepony.mc.otm.server.command
import com.mojang.brigadier.StringReader
import com.mojang.brigadier.arguments.ArgumentType
import com.mojang.brigadier.context.CommandContext
import com.mojang.brigadier.suggestion.Suggestions
import com.mojang.brigadier.suggestion.SuggestionsBuilder
import net.minecraft.commands.CommandSourceStack
import net.minecraft.commands.SharedSuggestionProvider
import net.minecraft.resources.ResourceLocation
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.android.AndroidResearchType
import java.util.concurrent.CompletableFuture
class AndroidResearchArgument : ArgumentType<AndroidResearchType> {
override fun parse(reader: StringReader): AndroidResearchType {
return AndroidResearchManager[ResourceLocation.read(reader)] ?: throw NoSuchElementException()
}
override fun <S : Any?> listSuggestions(context: CommandContext<S>, builder: SuggestionsBuilder): CompletableFuture<Suggestions> {
return SharedSuggestionProvider.suggest(AndroidResearchManager.researchMap.map { it.key.toString() }, builder)
}
companion object {
fun create(): AndroidResearchArgument = AndroidResearchArgument()
fun getResearchType(context: CommandContext<CommandSourceStack>, name: String): AndroidResearchType {
return context.getArgument(name, AndroidResearchType::class.java)
}
}
}

View File

@ -0,0 +1,54 @@
package ru.dbotthepony.mc.otm.server.command
import net.minecraft.commands.Commands
import net.minecraft.commands.arguments.EntityArgument
import net.minecraft.world.entity.player.Player
import net.neoforged.neoforge.event.RegisterCommandsEvent
import net.neoforged.neoforge.server.command.EnumArgument
import ru.dbotthepony.mc.otm.capability.MatteryPlayer.UpgradeType
import ru.dbotthepony.mc.otm.capability.matteryPlayer
object ExopackCommand {
fun register(event: RegisterCommandsEvent) {
event.dispatcher.register(
Commands.literal("exopack")
.requires { it.hasPermission(Commands.LEVEL_GAMEMASTERS) }
.then(Commands.literal("add")
.executes { setExoPack(listOf(it.source.playerOrException), true) }
.then(Commands.argument("targets", EntityArgument.players()).executes { setExoPack(EntityArgument.getPlayers(it, "targets"), true) })
)
.then(Commands.literal("remove")
.executes { setExoPack(listOf(it.source.playerOrException), false) }
.then(Commands.argument("targets", EntityArgument.players()).executes { setExoPack(EntityArgument.getPlayers(it, "targets"), false) })
)
.then(Commands.literal("upgrade")
.then(Commands.argument("type", EnumArgument.enumArgument(UpgradeType::class.java))
.then(Commands.literal("add")
.executes { setUpgrade(listOf(it.source.playerOrException), it.getArgument("type", UpgradeType::class.java), true) }
.then(Commands.argument("targets", EntityArgument.players()).executes { setUpgrade(
EntityArgument.getPlayers(it, "targets"), it.getArgument("type", UpgradeType::class.java), true) }))
.then(Commands.literal("remove")
.executes { setUpgrade(listOf(it.source.playerOrException), it.getArgument("type", UpgradeType::class.java), false) }
.then(Commands.argument("targets", EntityArgument.players()).executes { setUpgrade(
EntityArgument.getPlayers(it, "targets"), it.getArgument("type", UpgradeType::class.java), false) })))
)
)
}
private fun setExoPack(players: Collection<Player>, hasExoPack: Boolean): Int {
for (player in players) {
player.matteryPlayer.hasExopack = hasExoPack
// player.matteryPlayer.recreateExoPackMenu()
}
return players.size
}
private fun setUpgrade(players: Collection<Player>, type: UpgradeType, state: Boolean): Int {
for (player in players) {
player.matteryPlayer.let { type.prop.set(it, state) }
}
return players.size
}
}