Jump to content

[1.10.2] [Scala] Capabilities clashing with each other (SOLVED)


Recommended Posts

Posted

So I'm working on a fairly large mod in Scala, and I have two different capabilities, one for handling mana and the other for handling a custom level/exp system. However, it seems like I've done something wrong, as Forge appears to try to connect an instance of the mana handler to where there should be a level handler.

 

ServerProxy (usually called CommonProxy, I'm weird)

 

class ServerProxy {
def preInit {
	CapabilityManager.INSTANCE.register(classOf[ManaHandler], ManaHandler.getStorageInstance, ManaHandler.getHandlerFactory)
	CapabilityManager.INSTANCE.register(classOf[LevelHandler], LevelHandler.getStorageInstance, LevelHandler.getHandlerFactory)
	MinecraftForge.EVENT_BUS.register(new ChuuniEventHandler)
}
}

 

 

Relevant event handler code

 

@SubscribeEvent def addPlayerCapabilities(e:AttachCapabilitiesEvent.Entity) {
if(e.getEntity.isInstanceOf[EntityPlayer]) {
	e.addCapability(new ResourceLocation(ChuuniMod.MODID, "ManaHandler"), ManaHandler.getHandlerInstance)
	e.addCapability(new ResourceLocation(ChuuniMod.MODID, "LevelHandler"), LevelHandler.getHandlerInstance)
}
}

 

 

Relevant capability code

 

object LevelHandler {
@CapabilityInject(classOf[LevelHandler]) final val CAP:Capability[LevelHandler] = null

def instanceFor(player:EntityPlayer) = player.getCapability(CAP, null)
def getHandlerInstance = new DefaultLevelHandler
def getStorageInstance = new DefaultLevelHandler.Storage
def getHandlerFactory = new Callable[DefaultLevelHandler] { def call = new DefaultLevelHandler }
}

object ManaHandler {
@CapabilityInject(classOf[ManaHandler]) final val CAP:Capability[ManaHandler] = null

def instanceFor(player:EntityPlayer) = player.getCapability(CAP, null)
def getHandlerInstance = new DefaultManaHandler
def getStorageInstance = new DefaultManaHandler.Storage
def getHandlerFactory = new Callable[DefaultManaHandler] { def call = new DefaultManaHandler }
}

 

 

There is also an abstract class LevelHandler, but none of it's code should really be relevant. DefaultLevelHandler is a typical double-inheritance from LevelHandler and ICapabilitySerializable, and it's Storage is fairly standard as well. The same is true of ManaHandler's parts.

 

Can you spot my error? I'm completely stumped. Thanks!

Posted

Ah yes, sorry. The game crashes with this error when I try to load a world:

 

java.lang.ClassCastException: chuunimod.capabilities.DefaultManaHandler cannot be cast to chuunimod.capabilities.LevelHandler
at chuunimod.capabilities.LevelHandler$.instanceFor(LevelHandler.scala:58)
at chuunimod.gui.GuiChuuniOverlay.onRenderGameOverlay(GuiChuuniOverlay.scala:22)
at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_9_GuiChuuniOverlay_onRenderGameOverlay_Post.invoke(.dynamic)
at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90)
at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:168)
at net.minecraftforge.client.GuiIngameForge.post(GuiIngameForge.java:888)
at net.minecraftforge.client.GuiIngameForge.renderExperience(GuiIngameForge.java:586)
at net.minecraftforge.client.GuiIngameForge.renderGameOverlay(GuiIngameForge.java:167)
at net.minecraft.client.renderer.EntityRenderer.updateCameraAndRender(EntityRenderer.java:1125)
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1139)
at net.minecraft.client.Minecraft.run(Minecraft.java:406)
at net.minecraft.client.main.Main.main(Main.java:118)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)
at net.minecraft.launchwrapper.Launch.main(Launch.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97)
at GradleStart.main(GradleStart.java:26)

 

Full crash report:

 

---- Minecraft Crash Report ----
// Don't be sad. I'll do better next time, I promise!

Time: 10/7/16 5:31 PM
Description: Unexpected error

java.lang.ClassCastException: chuunimod.capabilities.DefaultManaHandler cannot be cast to chuunimod.capabilities.LevelHandler
at chuunimod.capabilities.LevelHandler$.instanceFor(LevelHandler.scala:58)
at chuunimod.gui.GuiChuuniOverlay.onRenderGameOverlay(GuiChuuniOverlay.scala:22)
at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_9_GuiChuuniOverlay_onRenderGameOverlay_Post.invoke(.dynamic)
at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90)
at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:168)
at net.minecraftforge.client.GuiIngameForge.post(GuiIngameForge.java:888)
at net.minecraftforge.client.GuiIngameForge.renderExperience(GuiIngameForge.java:586)
at net.minecraftforge.client.GuiIngameForge.renderGameOverlay(GuiIngameForge.java:167)
at net.minecraft.client.renderer.EntityRenderer.updateCameraAndRender(EntityRenderer.java:1125)
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1139)
at net.minecraft.client.Minecraft.run(Minecraft.java:406)
at net.minecraft.client.main.Main.main(Main.java:118)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)
at net.minecraft.launchwrapper.Launch.main(Launch.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97)
at GradleStart.main(GradleStart.java:26)


A detailed walkthrough of the error, its code path and all known details is as follows:
---------------------------------------------------------------------------------------

-- Head --
Thread: Client thread
Stacktrace:
at chuunimod.capabilities.LevelHandler$.instanceFor(LevelHandler.scala:58)
at chuunimod.gui.GuiChuuniOverlay.onRenderGameOverlay(GuiChuuniOverlay.scala:22)
at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_9_GuiChuuniOverlay_onRenderGameOverlay_Post.invoke(.dynamic)
at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90)
at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:168)
at net.minecraftforge.client.GuiIngameForge.post(GuiIngameForge.java:888)
at net.minecraftforge.client.GuiIngameForge.renderExperience(GuiIngameForge.java:586)
at net.minecraftforge.client.GuiIngameForge.renderGameOverlay(GuiIngameForge.java:167)

-- Affected level --
Details:
Level name: MpServer
All players: 1 total; [EntityPlayerSP['tripl3_'/949, l='MpServer', x=8.50, y=65.00, z=8.50]]
Chunk stats: MultiplayerChunkCache: 0, 0
Level seed: 0
Level generator: ID 00 - default, ver 1. Features enabled: false
Level generator options: 
Level spawn location: World: (-116,64,124), Chunk: (at 12,4,12 in -8,7; contains blocks -128,0,112 to -113,255,127), Region: (-1,0; contains chunks -32,0 to -1,31, blocks -512,0,0 to -1,255,511)
Level time: 0 game time, 0 day time
Level dimension: 0
Level storage version: 0x00000 - Unknown?
Level weather: Rain time: 0 (now: false), thunder time: 0 (now: false)
Level game mode: Game mode: creative (ID 1). Hardcore: false. Cheats: false
Forced entities: 1 total; [EntityPlayerSP['tripl3_'/949, l='MpServer', x=8.50, y=65.00, z=8.50]]
Retry entities: 0 total; []
Server brand: fml,forge
Server type: Integrated singleplayer server
Stacktrace:
at net.minecraft.client.multiplayer.WorldClient.addWorldInfoToCrashReport(WorldClient.java:451)
at net.minecraft.client.Minecraft.addGraphicsAndWorldToCrashReport(Minecraft.java:2779)
at net.minecraft.client.Minecraft.run(Minecraft.java:435)
at net.minecraft.client.main.Main.main(Main.java:118)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)
at net.minecraft.launchwrapper.Launch.main(Launch.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97)
at GradleStart.main(GradleStart.java:26)

-- System Details --
Details:
Minecraft Version: 1.10.2
Operating System: Windows 10 (amd64) version 10.0
Java Version: 1.8.0_74, Oracle Corporation
Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode), Oracle Corporation
Memory: 598666392 bytes (570 MB) / 1038876672 bytes (990 MB) up to 1038876672 bytes (990 MB)
JVM Flags: 4 total; -Xincgc -Xmx1024M -Xms1024M -Xbootclasspath/a:C:\Program Files (x86)\Scala IDE\plugins\org.scala-lang.scala-library_2.11.8.v20160304-115712-1706a37eb8.jar;C:\Program Files (x86)\Scala IDE\plugins\org.scala-lang.scala-reflect_2.11.8.v20160304-115712-1706a37eb8.jar
IntCache: cache: 0, tcache: 0, allocated: 13, tallocated: 95
FML: MCP 9.32 Powered by Forge 12.18.1.2095 4 mods loaded, 4 mods active
States: 'U' = Unloaded 'L' = Loaded 'C' = Constructed 'H' = Pre-initialized 'I' = Initialized 'J' = Post-initialized 'A' = Available 'D' = Disabled 'E' = Errored
UCHIJAAAA	mcp{9.19} [Minecraft Coder Pack] (minecraft.jar) 
UCHIJAAAA	FML{8.0.99.99} [Forge Mod Loader] (forgeSrc-1.10.2-12.18.1.2095.jar) 
UCHIJAAAA	Forge{12.18.1.2095} [Minecraft Forge] (forgeSrc-1.10.2-12.18.1.2095.jar) 
UCHIJAAAA	chuunimod{INDEV} [ChuuniMod] (bin) 
Loaded coremods (and transformers): 
GL info: ' Vendor: 'NVIDIA Corporation' Version: '4.5.0 NVIDIA 358.91' Renderer: 'GeForce GTX 750 Ti/PCIe/SSE2'
Launched Version: 1.10.2
LWJGL: 2.9.4
OpenGL: GeForce GTX 750 Ti/PCIe/SSE2 GL version 4.5.0 NVIDIA 358.91, NVIDIA Corporation
GL Caps: Using GL 1.3 multitexturing.
Using GL 1.3 texture combiners.
Using framebuffer objects because OpenGL 3.0 is supported and separate blending is supported.
Shaders are available because OpenGL 2.1 is supported.
VBOs are available because OpenGL 1.5 is supported.

Using VBOs: Yes
Is Modded: Definitely; Client brand changed to 'fml,forge'
Type: Client (map_client.txt)
Resource Packs: 
Current Language: English (US)
Profiler Position: N/A (disabled)
CPU: 4x Intel(R) Core(TM) i5-4570 CPU @ 3.20GHz

 

 

All I'm doing is trying to access the handlers via the instanceFor method to render their information to a GUI.

Posted

Mana:

class DefaultManaHandler(cur:Float=0,max:Float=250,regen:Float=.25f) extends ManaHandler(cur,max,regen) with ICapabilitySerializable[NBTTagCompound] {
def hasCapability(capability:Capability[_], f:EnumFacing) = capability == ManaHandler.CAP
def getCapability[T](capability:Capability[T], f:EnumFacing) = { if(capability == ManaHandler.CAP) this else null }.asInstanceOf[T]

def serializeNBT:NBTTagCompound = new NBTManaHandler(this).nbt
def deserializeNBT(nbt:NBTTagCompound) = new NBTManaHandler(nbt).copyTo(this)
}

object DefaultManaHandler {
class Storage extends IStorage[ManaHandler] {
	def writeNBT(cap:Capability[ManaHandler], ins:ManaHandler, f:EnumFacing) = ins.asInstanceOf[DefaultManaHandler].serializeNBT
	def readNBT(cap:Capability[ManaHandler], ins:ManaHandler, f:EnumFacing, nbt:NBTBase) = ins.asInstanceOf[DefaultManaHandler].deserializeNBT(nbt.asInstanceOf[NBTTagCompound])
}
}

 

Levels:

class DefaultLevelHandler(lvl:Int=1,xp:Float=0) extends LevelHandler(lvl,xp) with ICapabilitySerializable[NBTTagCompound] {
def hasCapability(capability:Capability[_], f:EnumFacing) = capability == LevelHandler.CAP
def getCapability[T](capability:Capability[T], f:EnumFacing) = { if(capability == LevelHandler.CAP) this else null }.asInstanceOf[T]

def serializeNBT:NBTTagCompound = new NBTLevelHandler(this).nbt
def deserializeNBT(nbt:NBTTagCompound) = new NBTLevelHandler(nbt).copyTo(this)
}

object DefaultLevelHandler {
class Storage extends IStorage[LevelHandler] {
	def writeNBT(cap:Capability[LevelHandler], ins:LevelHandler, f:EnumFacing) = ins.asInstanceOf[DefaultLevelHandler].serializeNBT
	def readNBT(cap:Capability[LevelHandler], ins:LevelHandler, f:EnumFacing, nbt:NBTBase) = ins.asInstanceOf[DefaultLevelHandler].deserializeNBT(nbt.asInstanceOf[NBTTagCompound])
}
}

Posted

Not really sure what you mean by the same class - the capability type is Handler, and the default implementation is DefaultHandler.

 

As to the debugger idea, the only option I have is the Eclipse debugger, which doesn't seem to be up to the task.

Posted
DefaultLevelHandler implements both LevelHandler and ICapabilitySerializable (i.e. ICapabilityProvider)

Ah, ok. Honestly, I've used this structure before and not had any problems with keeping track of it... For brevity's sake I'll leave it for now, especially as I don't think that's where the problem is (the mana handler worked fine before I added the level handler)

Posted

I have only the vaguest idea why, but for some reason that worked. Thank you! My updated code is below for anyone having the same issue.

 

object (x)Handler

object ManaHandler {
def instanceFor(player:EntityPlayer) = player.getCapability(Capabilities.MANA, null)
def getHandlerInstance = new DefaultManaHandler
def getStorageInstance = new DefaultManaHandler.Storage
def getHandlerFactory = new Callable[DefaultManaHandler] { def call = new DefaultManaHandler }
}

object LevelHandler {
def instanceFor(player:EntityPlayer) = player.getCapability(Capabilities.LEVEL, null)
def getHandlerInstance = new DefaultLevelHandler
def getStorageInstance = new DefaultLevelHandler.Storage
def getHandlerFactory = new Callable[DefaultLevelHandler] { def call = new DefaultLevelHandler }
}

 

Capabilities.java

public class Capabilities {
@CapabilityInject(ManaHandler.class) public static final Capability<ManaHandler> MANA = null;
@CapabilityInject(LevelHandler.class) public static final Capability<LevelHandler> LEVEL = null;
}

 

Moral of the story, don't try to inject capabilities into Scala code if you intend to use more than one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.