I am currently running
Issue Description
I add custom blocks with Forge. Then I go ingame on forge server and place custom block. It works. Then I add SpongeForge and place custom block I get evil exception (see below). Doesnt make sense tbh because the same method that is used to get the id I use from forge and it is "gss-decor:statue_jupiter" which when split with : should have length 2 which it apparently doesnt have when sponge calls it. Im confused sorry.
Relevant Mixins
https://github.com/SpongePowered/SpongeCommon/blob/bleeding/src/main/java/org/spongepowered/common/mixin/blockcapturing/MixinBlock_BlockCapturing.java#L55
https://github.com/SpongePowered/SpongeCommon/blob/bleeding/src/main/java/org/spongepowered/common/mixin/core/block/MixinBlock.java#L169
Calling this from Forge gets "gss-decor:statue_jupiter" (its used from the Mixin):
Block.REGISTRY.getNameForObject((Block) (Object) this).toString();
But somehow Sponge fails at ids[1]:
String[] ids = this.getId().split(":");
String modId = ids[0];
String name = ids[1];
Exception
[22:31:23] [Server thread/ERROR] [net.minecraft.server.MinecraftServer]: Encountered an unexpected exception
net.minecraft.util.ReportedException: Exception while ticking a block
at net.minecraft.server.MinecraftServer.func_71190_q(MinecraftServer.java:760) ~[MinecraftServer.class:?]
at net.minecraft.server.dedicated.DedicatedServer.func_71190_q(DedicatedServer.java:396) ~[nz.class:?]
at net.minecraft.server.MinecraftServer.func_71217_p(MinecraftServer.java:666) ~[MinecraftServer.class:?]
at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:524) [MinecraftServer.class:?]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_162]
Caused by: java.lang.ArrayIndexOutOfBoundsException: 1
at net.minecraft.block.Block.initializeBlockCapturingState(Block.java:3705) ~[aow.class:?]
at org.spongepowered.common.event.tracking.TrackingUtil.checkAndAssignBlockTickConfig(TrackingUtil.java:335) ~[TrackingUtil.class:1.12.2-2611-7.1.0-BETA-2970]
at org.spongepowered.common.event.tracking.TrackingUtil.updateTickBlock(TrackingUtil.java:276) ~[TrackingUtil.class:1.12.2-2611-7.1.0-BETA-2970]
at net.minecraft.world.WorldServer.redirect$onUpdateTick$zll000(WorldServer.java:2248) ~[oo.class:?]
at net.minecraft.world.WorldServer.func_72955_a(WorldServer.java:737) ~[oo.class:?]
at net.minecraft.world.WorldServer.func_72835_b(WorldServer.java:223) ~[oo.class:?]
at net.minecraft.server.MinecraftServer.func_71190_q(MinecraftServer.java:754) ~[MinecraftServer.class:?]
... 4 more
provide a test mod to reproduce this, otherwise im gonna blame this on the way you register your block
the only way this error could occur if your block id is wrong
how do you explain in that case that when I call the exact same NMS method I get a proper "gss-decor:something" and apparently sponge gets something else?
this is the mod odnwload:
https://drive.google.com/file/d/1ok4rzwAtlR9Uv84BkzsbMyjv5xVF5CJb/view?usp=sharing
and this is source:
https://gist.github.com/nihiluis/e449fe235b72f6689fab60007426ddec
I added the "gss-decor" prepend to the registry name to see if it makes difference it doesnt.
It鈥檚 possible to add some validation exception printout in the event the block id is malformed from the registry. Then it should be possible to find the root of the problem.
how?
Once build 2994 is done, give that build a test and we'll see what it will print something out for the issue. It should provide us some more information on what's causing the block id to be malformed.
Ok, a new build has been published (had some issues with maven dependencies), can you give it a try now?
The mod-id is missing. Im really unable to comprehend why Sponge and my own mod get different results. Any ideas?
[11:17:51] [Server thread/INFO] [STDOUT]: [goldsunsaga.decor.EventHandler$Companion:blockPlace:41]: gss-decor:statue_jupiter
[11:17:52] [Server thread/WARN] [Sponge]: /*******************************************************************************/
[11:17:52] [Server thread/WARN] [Sponge]: /* Malformatted Block ID discovered! */
[11:17:52] [Server thread/WARN] [Sponge]: /*******************************************************************************/
[11:17:52] [Server thread/WARN] [Sponge]: /* Sponge has found a malformatted block id when trying to load */
[11:17:52] [Server thread/WARN] [Sponge]: /* configurations for the block id. The printed out block idis */
[11:17:52] [Server thread/WARN] [Sponge]: /* not originally from sponge, and should be brought up with */
[11:17:52] [Server thread/WARN] [Sponge]: /* themod developer as the registration for this block is not */
[11:17:52] [Server thread/WARN] [Sponge]: /* likelyto work with other systems and assumptions of having a */
[11:17:52] [Server thread/WARN] [Sponge]: /* properlyformatted block id. */
[11:17:52] [Server thread/WARN] [Sponge]: /* Malformed ID : statue_jupiter */
[11:17:52] [Server thread/WARN] [Sponge]: /* Discovered id array : [Ljava.lang.String;@16c4601d */
[11:17:52] [Server thread/WARN] [Sponge]: /* */
[11:17:52] [Server thread/WARN] [Sponge]: /* Sponge will attempt to work around this by using the provided generated id: */
[11:17:52] [Server thread/WARN] [Sponge]: /* Generated ID : [Ljava.lang.String;@44817fae */
[11:17:52] [Server thread/WARN] [Sponge]: /*******************************************************************************/
I tried another mod "Forestry" and wanted to see if the same error occurs there. It doesn't. I can place those blocks normally.
I try to copy that format and register a block like this now, to no avail:
fun DecorativeBlock.activate() {
unlocalizedName = "gssdecor.$id"
setRegistryName(id)
setCreativeTab(CreativeTabs.DECORATIONS)
soundType = SoundType.STONE
}
@Mod.EventHandler
fun preInit(event: FMLPreInitializationEvent) {
Statues
Trees
Statues.blocks.forEach {
it.activate()
ForgeRegistries.BLOCKS.register(it)
ForgeRegistries.ITEMS.register(ItemBlock(it).setRegistryName(it.registryName))
if (event.side == Side.CLIENT) {
it.registerRender()
}
}
Trees.blocks.forEach {
it.activate()
ForgeRegistries.BLOCKS.register(it)
ForgeRegistries.ITEMS.register(ItemBlock(it).setRegistryName(it.registryName))
if (event.side == Side.CLIENT) {
it.registerRender()
}
}
logger = event.modLog
}
Can you print out what the ForgeRegistries.BLOCKS.getNameForObject(this) returns? Comparing for vanilla forge and sponge forge. It sounds like there's a registration discrepancy (and I don't know where the id is coming from in your code)
Do you mean like this?
@SubscribeEvent
@JvmStatic
@SideOnly(Side.SERVER)
fun blockPlace(event: BlockEvent.PlaceEvent) {
println(Block.REGISTRY.getNameForObject(event.placedBlock.block))
println(event.placedBlock.block.registryName!!.resourceDomain)
println(event.placedBlock.block.registryName!!.resourcePath)
}
With SpongeForge
[22:24:44] [Server thread/INFO] [STDOUT]: [goldsunsaga.decor.EventHandler$Companion:blockPlace:40]: gssdecor:statuetest
[22:24:44] [Server thread/INFO] [STDOUT]: [goldsunsaga.decor.EventHandler$Companion:blockPlace:41]: gssdecor
[22:24:44] [Server thread/INFO] [STDOUT]: [goldsunsaga.decor.EventHandler$Companion:blockPlace:42]: statuetest
[22:24:45] [Server thread/WARN] [Sponge]: /*******************************************************************************/
[22:24:45] [Server thread/WARN] [Sponge]: /* Malformatted Block ID discovered! */
[22:24:45] [Server thread/WARN] [Sponge]: /*******************************************************************************/
[22:24:45] [Server thread/WARN] [Sponge]: /* Sponge has found a malformatted block id when trying to load */
[22:24:45] [Server thread/WARN] [Sponge]: /* configurations for the block id. The printed out block idis */
[22:24:45] [Server thread/WARN] [Sponge]: /* not originally from sponge, and should be brought up with */
[22:24:45] [Server thread/WARN] [Sponge]: /* themod developer as the registration for this block is not */
[22:24:45] [Server thread/WARN] [Sponge]: /* likelyto work with other systems and assumptions of having a */
[22:24:45] [Server thread/WARN] [Sponge]: /* properlyformatted block id. */
[22:24:45] [Server thread/WARN] [Sponge]: /* Malformed ID : statuetest */
[22:24:45] [Server thread/WARN] [Sponge]: /* Discovered id array : [Ljava.lang.String;@5cb0900a */
[22:24:45] [Server thread/WARN] [Sponge]: /* */
[22:24:45] [Server thread/WARN] [Sponge]: /* Sponge will attempt to work around this by using the provided generated id: */
[22:24:45] [Server thread/WARN] [Sponge]: /* Generated ID : [Ljava.lang.String;@c0b07de */
[22:24:45] [Server thread/WARN] [Sponge]: /*******************************************************************************/
Without SpongeForge
[22:30:31] [Server thread/INFO] [STDOUT]: [goldsunsaga.decor.EventHandler$Companion:blockPlace:40]: gssdecor:statuetest
[22:30:31] [Server thread/INFO] [STDOUT]: [goldsunsaga.decor.EventHandler$Companion:blockPlace:41]: gssdecor
[22:30:31] [Server thread/INFO] [STDOUT]: [goldsunsaga.decor.EventHandler$Companion:blockPlace:42]: statuetest
I assume the id is added automatically. I prepended gssdecor to the registryName before btw, to no avail
But you're not requesting the id from ForgeRegistries.BLOCK, I know that they should be pointing to the same registry, Sponge is picking up from the very same registry that the id is not prefixed with the mod id. That is the problem it's having. At what point of the game is this occurring btw?
Can you add some more printouts for the initial registration of the blocks? (And also, you should be registering the blocks in the registry event iirc).
well Sponge is using Block.REGISTRY. ForgeRegistries.BLOCKS doesnt have the method getNameForObject so I used .getKey().
Its always occuring when I place the custom block. Not when I destroy one.
I registered the blocks in the registry event before, but I thought since this is the way a mod that works does it, maybe I can solve my problem like this.
I do this preInit check now
Statues.blocks.forEach {
it.activate()
ForgeRegistries.BLOCKS.register(it)
println("REGISTERED")
println(Block.REGISTRY.getNameForObject(it))
println(it.registryName!!.resourceDomain)
println(it.registryName!!.resourcePath)
println((ForgeRegistries.BLOCKS.getKey(it)))
ForgeRegistries.ITEMS.register(ItemBlock(it).setRegistryName(it.registryName))
if (event.side == Side.CLIENT) {
it.registerRender()
}
}
which returns this
cor.DecorativeBlock:activate:123]: Setting registry name to statuetest
[11:19:34] [Server thread/INFO] [STDOUT]: [goldsunsaga.decor.Main:preInit:24]: REGISTERED
[11:19:34] [Server thread/INFO] [STDOUT]: [goldsunsaga.decor.Main:preInit:25]: gssdecor:statuetest
[11:19:34] [Server thread/INFO] [STDOUT]: [goldsunsaga.decor.Main:preInit:26]: gssdecor
[11:19:34] [Server thread/INFO] [STDOUT]: [goldsunsaga.decor.Main:preInit:27]: statuetest
[11:19:34] [Server thread/INFO] [STDOUT]: [goldsunsaga.decor.Main:preInit:28]: gssdecor:statuetest
and then I place the block and this event triggers
@SubscribeEvent
@JvmStatic
@SideOnly(Side.SERVER)
fun blockPlace(event: BlockEvent.PlaceEvent) {
println(Block.REGISTRY.getNameForObject(event.placedBlock.block))
println(event.placedBlock.block.registryName!!.resourceDomain)
println(event.placedBlock.block.registryName!!.resourcePath)
println((ForgeRegistries.BLOCKS.getKey(event.placedBlock.block)))
}
when this has passed I get the known sponge error:
[11:22:37] [Server thread/WARN] [Sponge]: /*******************************************************************************/
[11:22:37] [Server thread/WARN] [Sponge]: /* Malformatted Block ID discovered! */
[11:22:37] [Server thread/WARN] [Sponge]: /*******************************************************************************/
[11:22:37] [Server thread/WARN] [Sponge]: /* Sponge has found a malformatted block id when trying to load */
[11:22:37] [Server thread/WARN] [Sponge]: /* configurations for the block id. The printed out block idis */
[11:22:37] [Server thread/WARN] [Sponge]: /* not originally from sponge, and should be brought up with */
[11:22:37] [Server thread/WARN] [Sponge]: /* themod developer as the registration for this block is not */
[11:22:37] [Server thread/WARN] [Sponge]: /* likelyto work with other systems and assumptions of having a */
[11:22:37] [Server thread/WARN] [Sponge]: /* properlyformatted block id. */
[11:22:37] [Server thread/WARN] [Sponge]: /* Malformed ID : statue_venus_aerie */
[11:22:37] [Server thread/WARN] [Sponge]: /* Discovered id array : [Ljava.lang.String;@2ddfb8f5 */
[11:22:37] [Server thread/WARN] [Sponge]: /* */
[11:22:37] [Server thread/WARN] [Sponge]: /* Sponge will attempt to work around this by using the provided generated id: */
[11:22:37] [Server thread/WARN] [Sponge]: /* Generated ID : [Ljava.lang.String;@30517313 */
[11:22:37] [Server thread/WARN] [Sponge]: /*******************************************************************************/
Your second paste doesn't show me what the registries are printing out. What's odd is that Sponge is only using one of the registry pointers (Block.REGISTRY) which forge reroutes to using the ForgeRegistries.BLOCKS. Sponge otherwise doesn't interfere with registration of blocks or changes them in any way, so I'm having some trouble understanding how it's getting different information at different times.
it prints the same, sorry.
could someone please test the mod (see above for dl) and see if there are issues on another end as well when placing a block?
no fix or tests about this bug?
This was only closed because I ported a commit from stable-7 to our bleeding branch with a commit message that suggested it should be closed, I'll reopen it.
The problem is at https://gist.github.com/nihiluis/e449fe235b72f6689fab60007426ddec#file-decorative-kt-L108 - this will create
public String getId() {
return Id;
}
And that will override getID that is already in block class.
https://github.com/SpongePowered/SpongeCommon/commit/cc085aff33913f99ff0cc020668ebf2f8d4c4634 - this commit actually fixes this issue, sort-of ...
Explanation for @nihiluis:
Because sponge is mixing into Block at runtime, kotlin wont generate any errors - it checks at compile time only.
Explanation for sponge dev's:
This is kind-of an issue with kotlin and sponge mixin's. Kotlin by itself doesn't allow to override methods by "error" - it requires override. But it only checks for methods at compile-time only ( why should it check at runtime, huh ? ) - and this is where the core of issue is.
Right now I can't think of any fixes that won't touch API compatibility. And this is also repeatable in java:
public String getName() {
return null; // Just to be a little bit devil-ish
}
... or you could rewrite mixin's to use abstract classes instead. This won't generate callVirtual and will generate callSpecial instead, that will try to call path/to/abstractClass.getId() - but this is only theory as I don't know how exactly callSpeciall is implemented - but this will still break API compat/API . Or write runtime patcher that would replace callVirtual with api classes to call base class that it was mixed in.
@Mumfrey
Can you take a look at this to see what your thoughts are?
Most helpful comment
The problem is at https://gist.github.com/nihiluis/e449fe235b72f6689fab60007426ddec#file-decorative-kt-L108 - this will create
And that will override getID that is already in block class.
https://github.com/SpongePowered/SpongeCommon/commit/cc085aff33913f99ff0cc020668ebf2f8d4c4634 - this commit actually fixes this issue, sort-of ...
Explanation for @nihiluis:
Because sponge is mixing into Block at runtime, kotlin wont generate any errors - it checks at compile time only.
Explanation for sponge dev's:
This is kind-of an issue with kotlin and sponge mixin's. Kotlin by itself doesn't allow to override methods by "error" - it requires override. But it only checks for methods at compile-time only ( why should it check at runtime, huh ? ) - and this is where the core of issue is.
Right now I can't think of any fixes that won't touch API compatibility. And this is also repeatable in java:
... or you could rewrite mixin's to use abstract classes instead. This won't generate callVirtual and will generate callSpecial instead, that will try to call path/to/abstractClass.getId() - but this is only theory as I don't know how exactly callSpeciall is implemented - but this will still break API compat/API . Or write runtime patcher that would replace callVirtual with api classes to call base class that it was mixed in.