Ktor服务器中ItemStack获取ItemMeta空指针问题咨询
问题:Ktor服务器调用Spigot API的ItemMeta时触发空指针异常
我正在开发一款Ktor服务器,用于实现玩家用游戏内货币购买游戏内物品的功能,当前使用1.20版本的Spigot API。调用getItemMeta()方法(Kotlin中为.itemMeta)时出现空指针异常,导致fromJson(string: String?):ItemStack?方法无法正常工作,同时调用toJson(itemStack: ItemStack):String方法也会触发空指针。
异常堆栈
java.lang.NullPointerException: null at org.bukkit.Bukkit.getItemFactory(Bukkit.java:1608) at org.bukkit.inventory.ItemStack.getItemMeta(ItemStack.java:550) at fr.plaglefleau.serialization.JsonItemStack.fromJson(JsonItemStack.kt:278) at fr.plaglefleau.bdd_MySql.Gestion.updateInventory(Gestion.kt:815) at fr.plaglefleau.plugins.RoutingKt$configureRouting$1$3$1$1$7.invokeSuspend(Routing.kt:588) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.internal.DispatchedContinuation.resumeWith(DispatchedContinuation.kt:205) at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:135) at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:109) at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(SuspendFunctionGun.kt:11) at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(SuspendFunctionGun.kt:59) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106) at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:167) at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.ktor.server.netty.EventLoopGroupProxy$Companion.create$lambda$1$lambda$0(NettyApplicationEngine.kt:296) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:834) 2023-07-09 03:46:51.495 [eventLoopGroupProxy-4-1] TRACE io.ktor.server.sessions.Sessions - Sending session data for /api/client/updateInventory: connect 2023-07-09 03:46:51.496 [eventLoopGroupProxy-4-1] TRACE i.k.s.p.c.ContentNegotiation - Skipping response body transformation from HttpStatusCode to OutgoingContent for the PUT /api/client/updateInventory request because the HttpStatusCode type is ignored. See [ContentNegotiationConfig::ignoreType].
相关代码片段
Gestion.updateInventory方法
fun updateInventory(inventory: ArrayList<ItemSlotPair>, username: String) { val laConnexion = Connexion(url, this.username, password) var preparedStatement = laConnexion.getConnexion().prepareStatement( "SELECT id FROM user WHERE username = ?" ) preparedStatement.setString(1,username) var rs = preparedStatement.executeQuery() val userID = if(rs.next()) { rs.getInt("id") } else { null } if(userID == null) { return } for(i in 0..inventory.size) { val item = JsonItemStack.fromJson(inventory[i].item) ?: return addItemIfNotExist(item) preparedStatement = laConnexion.getConnexion().prepareStatement( "UPDATE inventaire SET article_id = ?, quantité = ? WHERE slot_number = ? AND user_id = ?" ) preparedStatement.setInt(1,item.type.id) preparedStatement.setInt(2,item.amount) preparedStatement.setInt(3, inventory[i].slot) preparedStatement.setInt(4,userID) preparedStatement.executeUpdate() } laConnexion.fermerConnexion() }
JsonItemStack.kt:218行
val meta = itemStack.itemMeta
Routing.kt中的updateInventory路由
put("updateInventory") { val receive = call.receive<InventoryReceive>() gestion.updateInventory(receive.inventory, receive.username) call.respond(HttpStatusCode.OK, "Good") }
问题推测与需求
获取ItemStack的ItemMeta需要依赖ItemFactory接口,而获取该接口需要调用Server.getItemFactory(),但我的服务未运行在Minecraft服务器环境中,导致Spigot API无法正常获取ItemMeta。现寻求可行的解决方案,目前考虑使用自定义类存储ItemStack的相关数据。
内容的提问来源于stack exchange,提问作者Plag
相关产品推荐
相关产品推荐

