Exosuit probe
This commit is contained in:
parent
f0ba88776d
commit
52e6971c9d
@ -45,7 +45,22 @@ private fun sounds(provider: MatteryLanguageProvider) {
|
||||
|
||||
private fun misc(provider: MatteryLanguageProvider) {
|
||||
with(provider.english) {
|
||||
misc("gui.exosuit", "Exosuit Inventory")
|
||||
gui("exosuit", "Exosuit Inventory")
|
||||
|
||||
gui("exosuit.probe1", "This little device feels unnatural to touch, it is almost certainly resilient to any possible attempt to break it open.")
|
||||
gui("exosuit.probe2", "There is fingerprint reader built into one of sides which gently glow when touched.")
|
||||
gui("exosuit.probe3", "It seems this box will unlock once you strongly press fingerprint reader, and you feel what's inside will affect you without any way back!")
|
||||
|
||||
gui("exosuit.already_activated", "You already have exosuit following you")
|
||||
|
||||
misc("exosuit.granted1", "As you keep pressing fingerprint reader, you are getting hurt in finger.")
|
||||
misc("exosuit.granted2", "After you raise your finger, fingerprint reader glows very bright.")
|
||||
misc("exosuit.granted3", "Then, fingerprint reader fades, leaving faint trace not of your finger, but of your very soul.")
|
||||
misc("exosuit.granted4", "The device opens... And whatever was inside it shroud you, yet you feel nothing, as it wasn't even there.")
|
||||
misc("exosuit.granted5", "As whatever shrouded you takes final form, you feel it binds to your soul.")
|
||||
misc("exosuit.granted6", "INITIALIZATION SEQUENCE COMPLETE. WELCOME, USER %s")
|
||||
misc("exosuit.granted7", "You are not permanently equipped with four dimensional omni-present Exosuit.")
|
||||
misc("exosuit.granted8", "As of now, this exosuit is not much, but it's built-in AI hints there are upgrade modules out there somewhere...")
|
||||
|
||||
misc("iteration", "Iteration %s")
|
||||
misc("death_reason", "Decommissioned!")
|
||||
@ -213,6 +228,9 @@ private fun death(provider: MatteryLanguageProvider) {
|
||||
death("otm_hawking_radiation.player", "%1\$s disintegrated whilst fighting %2\$s")
|
||||
death("otm_emp.player", "%1\$s blew fuzes of %2\$s")
|
||||
death("otm_emp.player.item", "%1\$s blew fuzes of %2\$s using %3\$s")
|
||||
|
||||
death(MRegistry.DAMAGE_EXOSUIT_PROBE_ID, "%1\$s hit little finger against cupboard")
|
||||
death("${MRegistry.DAMAGE_EXOSUIT_PROBE_ID}.player", "%1\$s hit little finger against cupboard whilst %2\$s tried to finish them off")
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,6 +293,7 @@ private fun blocks(provider: MatteryLanguageProvider) {
|
||||
|
||||
private fun items(provider: MatteryLanguageProvider) {
|
||||
with(provider.english) {
|
||||
add(MItems.EXOSUIT_PROBE, "Exosuit Probe")
|
||||
add(MItems.NUTRIENT_PASTE, "Nutrient paste")
|
||||
|
||||
add(MItems.BLACK_HOLE_SCANNER, "Singularity Scanner")
|
||||
|
@ -82,7 +82,7 @@ public final class OverdriveThatMatters {
|
||||
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setupClient);
|
||||
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
MinecraftForge.EVENT_BUS.register(TickerKt.class);
|
||||
MinecraftForge.EVENT_BUS.register(GlobalEventHandlerKt.class);
|
||||
MinecraftForge.EVENT_BUS.register(MatteryPlayerCapability.Companion);
|
||||
MinecraftForge.EVENT_BUS.register(MatterRegistryKt.class);
|
||||
MinecraftForge.EVENT_BUS.register(MatterDataKt.class);
|
||||
@ -120,6 +120,8 @@ public final class OverdriveThatMatters {
|
||||
MinecraftForge.EVENT_BUS.register(MatteryGUI.INSTANCE);
|
||||
MinecraftForge.EVENT_BUS.register(EventHandlerKt.class);
|
||||
|
||||
event.enqueueWork(GlobalEventHandlerKt::recordClientThread);
|
||||
|
||||
TritaniumArmorModel.register();
|
||||
GravitationStabilizerModel.register();
|
||||
}
|
||||
|
@ -27,13 +27,127 @@ private val postWorldTick = WeakHashMap<Level, ArrayList<IConditionalTickable>>(
|
||||
private val preWorldTickOnce = WeakHashMap<Level, ArrayList<ITickable>>()
|
||||
private val postWorldTickOnce = WeakHashMap<Level, ArrayList<ITickable>>()
|
||||
|
||||
private val preServerTickTimers = TimerQueue()
|
||||
private val postServerTickTimers = TimerQueue()
|
||||
|
||||
class TimerQueue {
|
||||
private var ticks = 0
|
||||
private var head: Timer? = null
|
||||
|
||||
inner class Timer(val timerTicks: Int, val runnable: Runnable) {
|
||||
val ringAt = ticks + timerTicks
|
||||
var finished = false
|
||||
private set
|
||||
|
||||
var next: Timer? = null
|
||||
var prev: Timer? = null
|
||||
|
||||
init {
|
||||
if (head == null) {
|
||||
head = this
|
||||
} else {
|
||||
var next = head
|
||||
|
||||
while (next != null) {
|
||||
if (next.ringAt >= this.ringAt) {
|
||||
next.prev?.next = this
|
||||
this.prev = next.prev
|
||||
next.prev = this
|
||||
this.next = next
|
||||
break
|
||||
} else if (next.next == null) {
|
||||
next.next = this
|
||||
this.prev = next
|
||||
break
|
||||
} else {
|
||||
next = next.next
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun execute() {
|
||||
check(!finished) { "Already finished" }
|
||||
runnable.run()
|
||||
finished = true
|
||||
}
|
||||
}
|
||||
|
||||
fun tick() {
|
||||
ticks++
|
||||
|
||||
var head = head
|
||||
|
||||
while (head != null) {
|
||||
if (head.ringAt <= ticks) {
|
||||
head.execute()
|
||||
head = head.next
|
||||
head?.prev = null
|
||||
this.head = head
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
ticks = 0
|
||||
head = null
|
||||
}
|
||||
}
|
||||
|
||||
fun addPreTickTimer(inTicks: Int, callback: Runnable): TimerQueue.Timer? {
|
||||
if (SERVER_IS_DYING) {
|
||||
LOGGER.error("Refusing to add timer $callback in ticks $inTicks while server is dying", IllegalStateException("Server is stopping"))
|
||||
return null
|
||||
}
|
||||
|
||||
return preServerTickTimers.Timer(inTicks, callback)
|
||||
}
|
||||
|
||||
fun addPostTickTimer(inTicks: Int, callback: Runnable): TimerQueue.Timer? {
|
||||
if (SERVER_IS_DYING) {
|
||||
LOGGER.error("Refusing to add ticker $callback in ticks $inTicks while server is dying", IllegalStateException("Server is stopping"))
|
||||
return null
|
||||
}
|
||||
|
||||
return postServerTickTimers.Timer(inTicks, callback)
|
||||
}
|
||||
|
||||
private var _server: MinecraftServer? = null
|
||||
private var _serverThread: Thread? = null
|
||||
private var _clientThread: Thread? = null
|
||||
|
||||
fun recordClientThread() {
|
||||
if (_clientThread != null) {
|
||||
throw IllegalStateException("Already have client channel")
|
||||
}
|
||||
|
||||
_clientThread = Thread.currentThread()
|
||||
}
|
||||
|
||||
fun runIfClient(lambda: () -> Unit) {
|
||||
if (_clientThread !== null) {
|
||||
lambda.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
fun <V> runIfClient(value: V, lambda: () -> V): V {
|
||||
if (_clientThread !== null) {
|
||||
return lambda.invoke()
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
fun isServerThread(): Boolean {
|
||||
return Thread.currentThread() === _serverThread
|
||||
}
|
||||
|
||||
fun isClientThread(): Boolean {
|
||||
return Thread.currentThread() === _clientThread
|
||||
}
|
||||
|
||||
val MINECRAFT_SERVER: MinecraftServer
|
||||
get() {
|
||||
return _server ?: throw NullPointerException("Not running a server!")
|
||||
@ -67,6 +181,8 @@ interface IConditionalTickable : ITickable {
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
fun onServerTick(event: ServerTickEvent) {
|
||||
if (event.phase === TickEvent.Phase.START) {
|
||||
preServerTickTimers.tick()
|
||||
|
||||
for (i in preServerTick.size - 1 downTo 0) {
|
||||
val ticker = preServerTick[i]
|
||||
|
||||
@ -82,6 +198,8 @@ fun onServerTick(event: ServerTickEvent) {
|
||||
preServerTickOnce.removeAt(i)
|
||||
}
|
||||
} else {
|
||||
postServerTickTimers.tick()
|
||||
|
||||
for (i in postServerTick.size - 1 downTo 0) {
|
||||
val ticker = postServerTick[i]
|
||||
|
||||
@ -223,6 +341,8 @@ fun addPostWorldTickerOnce(level: Level, ticker: ITickable) {
|
||||
}
|
||||
|
||||
private fun clear() {
|
||||
preServerTickTimers.clear()
|
||||
postServerTickTimers.clear()
|
||||
preServerTick.clear()
|
||||
postServerTick.clear()
|
||||
preWorldTick.clear()
|
@ -0,0 +1,82 @@
|
||||
package ru.dbotthepony.mc.otm.item
|
||||
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResultHolder
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.*
|
||||
import net.minecraft.world.level.Level
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.addPostTickTimer
|
||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
import ru.dbotthepony.mc.otm.runIfClient
|
||||
|
||||
class ExoSuitProbeItem : Item(Properties().tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB).stacksTo(1).rarity(Rarity.EPIC)) {
|
||||
override fun getUseDuration(p_41454_: ItemStack): Int {
|
||||
return 24
|
||||
}
|
||||
|
||||
override fun appendHoverText(p_41421_: ItemStack, p_41422_: Level?, tooltip: MutableList<Component>, p_41424_: TooltipFlag) {
|
||||
super.appendHoverText(p_41421_, p_41422_, tooltip, p_41424_)
|
||||
|
||||
val alreadyHas = runIfClient(false) {
|
||||
return@runIfClient minecraft.player?.matteryPlayer?.hasExoSuit ?: false
|
||||
}
|
||||
|
||||
if (alreadyHas) {
|
||||
tooltip.add(TranslatableComponent("otm.gui.exosuit.already_activated").withStyle(ChatFormatting.DARK_RED))
|
||||
} else {
|
||||
tooltip.add(TranslatableComponent("otm.gui.exosuit.probe1").withStyle(ChatFormatting.GRAY))
|
||||
tooltip.add(TranslatableComponent("otm.gui.exosuit.probe2").withStyle(ChatFormatting.GRAY))
|
||||
tooltip.add(TranslatableComponent("otm.gui.exosuit.probe3").withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
}
|
||||
|
||||
override fun use(p_41432_: Level, player: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
if (player.matteryPlayer?.hasExoSuit == false) {
|
||||
player.startUsingItem(hand)
|
||||
return InteractionResultHolder.consume(player.getItemInHand(hand))
|
||||
}
|
||||
|
||||
return super.use(p_41432_, player, hand)
|
||||
}
|
||||
|
||||
override fun finishUsingItem(itemStack: ItemStack, level: Level, player: LivingEntity): ItemStack {
|
||||
val mattery = player.matteryPlayer ?: return super.finishUsingItem(itemStack, level, player)
|
||||
|
||||
if (mattery.hasExoSuit) {
|
||||
return super.finishUsingItem(itemStack, level, player)
|
||||
}
|
||||
|
||||
itemStack.shrink(1)
|
||||
|
||||
if (player is ServerPlayer) {
|
||||
mattery.hasExoSuit = true
|
||||
|
||||
player.displayClientMessage(TranslatableComponent("otm.exosuit.granted1").withStyle(ChatFormatting.GRAY), false)
|
||||
player.hurt(MRegistry.DAMAGE_EXOSUIT_PROBE, 1f)
|
||||
|
||||
for (i in 2 .. 8) {
|
||||
addPostTickTimer((i - 1) * 100) {
|
||||
if (!player.hasDisconnected()) {
|
||||
if (i == 6) {
|
||||
player.displayClientMessage(TranslatableComponent("otm.exosuit.granted$i", player.displayName.copy().withStyle(ChatFormatting.DARK_PURPLE)).withStyle(ChatFormatting.DARK_AQUA), false)
|
||||
} else {
|
||||
player.displayClientMessage(TranslatableComponent("otm.exosuit.granted$i").withStyle(ChatFormatting.GRAY), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return itemStack
|
||||
}
|
||||
|
||||
override fun getUseAnimation(p_41452_: ItemStack): UseAnim = UseAnim.BOW
|
||||
}
|
@ -74,6 +74,8 @@ object MItems {
|
||||
}
|
||||
}
|
||||
|
||||
val EXOSUIT_PROBE: Item by registry.register(MNames.EXOSUIT_PROBE, ::ExoSuitProbeItem)
|
||||
|
||||
val DEBUG_EXPLOSION_SMALL: Item by registry.register(MNames.DEBUG_EXPLOSION_SMALL) { BlockItem(MBlocks.DEBUG_EXPLOSION_SMALL, DEFAULT_PROPERTIES) }
|
||||
val DEBUG_SPHERE_POINTS: Item by registry.register(MNames.DEBUG_SPHERE_POINTS) { BlockItem(MBlocks.DEBUG_SPHERE_POINTS, DEFAULT_PROPERTIES) }
|
||||
|
||||
|
@ -92,6 +92,8 @@ object MNames {
|
||||
const val GRAVITATION_FIELD_SENSOR = "gravitation_field_sensor"
|
||||
const val PORTABLE_GRAVITATION_STABILIZER = "portable_gravitation_stabilizer"
|
||||
|
||||
const val EXOSUIT_PROBE = "exosuit_probe"
|
||||
|
||||
// armor
|
||||
const val TRITANIUM_HELMET = "tritanium_helmet"
|
||||
const val TRITANIUM_CHESTPLATE = "tritanium_chestplate"
|
||||
|
@ -181,10 +181,18 @@ object MRegistry {
|
||||
CRATE_PURPLE,
|
||||
)
|
||||
|
||||
val DAMAGE_BECOME_ANDROID = ImmutableDamageSource(DamageSource("otm_become_android").bypassArmor().bypassInvul().bypassMagic())
|
||||
val DAMAGE_BECOME_HUMANE = ImmutableDamageSource(DamageSource("otm_become_humane").bypassArmor().bypassInvul().bypassMagic())
|
||||
val DAMAGE_EVENT_HORIZON = ImmutableDamageSource(DamageSource("otm_event_horizon").bypassMagic().bypassArmor())
|
||||
val DAMAGE_HAWKING_RADIATION = ImmutableDamageSource(DamageSource("otm_hawking_radiation"))
|
||||
const val DAMAGE_BECOME_ANDROID_ID = "otm_become_android"
|
||||
const val DAMAGE_BECOME_HUMANE_ID = "otm_become_humane"
|
||||
const val DAMAGE_EVENT_HORIZON_ID = "otm_event_horizon"
|
||||
const val DAMAGE_HAWKING_RADIATION_ID = "otm_hawking_radiation"
|
||||
const val DAMAGE_EXOSUIT_PROBE_ID = "otm_exosuit_probe"
|
||||
|
||||
val DAMAGE_EXOSUIT_PROBE = ImmutableDamageSource(DamageSource(DAMAGE_EXOSUIT_PROBE_ID).bypassArmor().bypassMagic())
|
||||
|
||||
val DAMAGE_BECOME_ANDROID = ImmutableDamageSource(DamageSource(DAMAGE_BECOME_ANDROID_ID).bypassArmor().bypassInvul().bypassMagic())
|
||||
val DAMAGE_BECOME_HUMANE = ImmutableDamageSource(DamageSource(DAMAGE_BECOME_HUMANE_ID).bypassArmor().bypassInvul().bypassMagic())
|
||||
val DAMAGE_EVENT_HORIZON = ImmutableDamageSource(DamageSource(DAMAGE_EVENT_HORIZON_ID).bypassMagic().bypassArmor())
|
||||
val DAMAGE_HAWKING_RADIATION = ImmutableDamageSource(DamageSource(DAMAGE_HAWKING_RADIATION_ID))
|
||||
const val DAMAGE_EMP_NAME = "otm_emp"
|
||||
const val DAMAGE_PLASMA_NAME = "otm_plasma"
|
||||
val DAMAGE_EMP: DamageSource = ImmutableDamageSource(EMPDamageSource())
|
||||
|
@ -0,0 +1,40 @@
|
||||
package ru.dbotthepony.mc.otm.tests
|
||||
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.Test
|
||||
import ru.dbotthepony.mc.otm.TimerQueue
|
||||
|
||||
object TimerQueueTests {
|
||||
@Test
|
||||
@DisplayName("TimerQueue test")
|
||||
fun test() {
|
||||
val queue = TimerQueue()
|
||||
|
||||
var state = 0
|
||||
|
||||
queue.Timer(1) { state = 1 }
|
||||
queue.Timer(2) { state = 2 }
|
||||
queue.Timer(3) { state = 3 }
|
||||
queue.Timer(7) { state = 7 }
|
||||
queue.Timer(6) { state = 6 }
|
||||
queue.Timer(2) { state = 2 }
|
||||
|
||||
queue.tick() // 1
|
||||
assertEquals(1, state)
|
||||
queue.tick() // 2 + 2
|
||||
assertEquals(2, state)
|
||||
queue.tick() // 3
|
||||
assertEquals(3, state)
|
||||
queue.tick() // 4
|
||||
assertEquals(3, state)
|
||||
queue.tick() // 5
|
||||
assertEquals(3, state)
|
||||
queue.tick() // 6
|
||||
assertEquals(6, state)
|
||||
queue.tick() // 7
|
||||
assertEquals(7, state)
|
||||
queue.tick() // 8
|
||||
assertEquals(7, state)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user