Jump to content

tripl3dogdare

Members
  • Posts

    41
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by tripl3dogdare

  1. I'm working on a small mod that revolves around a specific block, and I've more or less got the functionality down. The issue I'm having is with the models - I've managed to get the model to apply when the block is placed in the world, but I can't get the item to be modeled in the player's inventory. It just shows up as the default flat black/magenta checkerboard in its slot, and as an overlarge block of the same texture when held. I wouldn't normally ask for help with something so mundane, but I'm legitimately stumped what I'm doing wrong. I've tried just about everything I can think of, including converting the blockstate JSON to Forge's format, changing paths, everything. The registry code is clearly working at least in part, since the block model works when it's placed, but the item just refuses to work. ClientRegistry.kt @SideOnly(Side.CLIENT) @Mod.EventBusSubscriber(Side.CLIENT) object ClientRegistry { @SubscribeEvent fun registerModels(e: ModelRegistryEvent) { ModelLoader.setCustomModelResourceLocation( Registry.itemBlockAutocrafter, 0, ModelResourceLocation(Registry.blockAutocrafter.registryName!!, "inventory")) } } blockstates/autocrafter.json { "variants": { "normal": { "model": "autocrafter:autocrafter" }, "inventory": { "model": "autocrafter:autocrafter" } } } models/block/autocrafter.json (copied wholesale from the Crafting Table, going to edit more later) { "parent": "block/cube", "textures": { "particle": "blocks/crafting_table_front", "down": "blocks/planks_oak", "up": "blocks/crafting_table_top", "north": "blocks/crafting_table_front", "east": "blocks/crafting_table_side", "south": "blocks/crafting_table_side", "west": "blocks/crafting_table_front" } } models/item/autocrafter.json (again copied/modified from the Crafting Table) { "parent": "autocrafter:block/autocrafter" } The item being rendered The block when placed (currently looks the same as a Crafting Table, but it's not)
  2. Ah, ok. Glad to hear that it's being worked on! I'll continue using the Java code as a workaround for the time being.
  3. As my previous posts probably suggest, I generally prefer modding in Scala to modding in Java. However, I've run up against an issue where I can't get the @Config annotation to work with Scala code. My solution thus far has been to stick it on Java code instead and simply link the two, but it'd be nice to have some of Scala's conciseness when defining the config. Is there any way to get these two to play nice?
  4. Thanks for the advice, I've started on the process but it's slow going. Guess they really wanted to make this complicated, huh? Still, thanks! I probably wouldn't have figured that out alone...
  5. My bad, I guess I'm just a bit too used to Scala where I can just if(world.isRemote) { import net.minecraft.client.Minecraft // do stuff } Please disregard my previous comments as to how to use Minecraft#getMinecraft safely, it appears I am either an idiot or really rusty when it comes to Java.
  6. What would really be ideal is to be able to load the assets from a folder within the .minecraft folder, where I'm already loading the blocks themselves from. I'm aiming to make these "block packs" as easy as possible to install, which means that the models and textures need to be in roughly the same location as everything else so they come down to a simple drag and drop install.
  7. @LousyLynx Sorry, not much I can do right now... If you still need help later, I can take a look. Wish I could be of more use.
  8. @LousyLynx Hmm... I remember having issues with this myself. Luckily, I just remembered how to fix it, I think! It's definitely true that this is an unusually painful process for blocks, and there's little to no documentation. In your block class, override this method: getBlockLayer() It should return BlockRenderLayer.CUTOUT and then the model should work, if I remember right from when I last did this. If it doesn't, let me know - I still have source code laying around, so I can dig though it a bit and see what else is relevant (it's been a month or two since I worked with this, so I don't remember off the top of my head).
  9. @LousyLynx You'll want to look into the "tintindex" parameter in the block model JSON, it defines what tint index (the int in the method signature) the block should be tinted on. Here's a link to the spec for that file: http://minecraft.gamepedia.com/Model#Block_models
  10. Glad I could help! That is one of the most common uses of it that's actually legitimately needed, yes. Just be careful to check world.isRemote to make sure you're on the client side before you try to use Minecraft#getMinecraft, and you should be fine =)
  11. Each instance of Minecraft initializes the mod separately, so they won't overlap ever. I can't answer to whether saving it statically is safe, but I'd assume so. However, you should only ever use Minecraft#getMinecraft() if you absolutely have to - there are almost always better and safer ways to get the information you want. The player can only be gotten from a Minecraft instance on the client side, not on the server, so be very careful where you do this. If you can avoid using Minecraft#player at all, do. The relevant player will usually be passed along with events and method calls. I can't answer to this for sure, but again, Minecraft#getMinecraft() is usually unnecessary and the same effects can be achieved in a different and safer way. Hope that helps!
  12. I'd assume you're using the IItemColor interface to color your items, correct? If so, there is a corresponding IBlockColor interface that works essentially exactly the same. The main differences are that the method you need to implement is colorMultiplier(IBlockState, IBlockAccess, BlockPos, Int) rather than getColor(ItemStack, Int) and instead of registering with Minecraft.getMinecraft.getItemColors.registerItemColorHandler you register with Minecraft.getMinecraft.getBlockColors.registerBlockColorHandler Hope that helps!
  13. I'm attempting to make a mod that essentially lets you add blocks and items to the game via JSON (yes, I know some already exist, but 1. this is mostly just to see if I can and 2. they all have some drawback or another). What I'm wondering is, is it possible to change the location that Minecraft looks for block and item models at? For example, would it be possible to add my own directory as an additional directory to search for domains in (i.e. it would search for assets both in assets/<domain> as usual and in my own moddirectory/<domain>)? The one other thought I've had at the moment is to copy the model files into the built-in folder at runtime, but that would really not be ideal if it can be avoided.
  14. Thank you, that seems to have fixed it ^-^ I guess I haven't broken out of my Java habits as nicely as I'd have hoped.
  15. Here is the main repo: https://github.com/tripl3dogdare/rwbymod And the scala branch: https://github.com/tripl3dogdare/rwbymod/tree/scala
  16. Yes, in my main mod file I have this: @Instance(MODID) var instance = null That's how I've done it in a couple other Scala mods - however, none of them had GUIs, which may be why I'm only running into this issue now.
  17. I'm trying to register a GUI handler for my mod, and it gives me this error: net.minecraftforge.fml.common.LoaderExceptionModCrash: Caught exception from The Minecraft RWBY Mod (rwbymod) Caused by: java.lang.NullPointerException at net.minecraftforge.fml.common.network.NetworkRegistry.registerGuiHandler(NetworkRegistry.java:229) at com.rwbymod.z_proxy.CommonProxy.init(CommonProxy.scala:21) at com.rwbymod.z_proxy.ClientProxy.init(ClientProxy.scala:10) If I go to NetworkRegistry, the offending line shows this: FMLLog.log(Level.ERROR, "Mod of type %s attempted to register a gui network handler during a construction phase", mod.getClass().getName()); What's odd is that I'm registering the GUI handler in the Init phase, while in a Java version of the same mod I register it in PreInit... and it works. I switch over to Scala, and suddenly it stops working. Here's my code: CommonProxy.scala (ClientProxy just calls the methods here, plus irrelevant rendering stuffs): class CommonProxy { def preInit { // irrelevant } def init { NetworkRegistry.INSTANCE.registerGuiHandler(RWBYMod.instance, new GuiHandler()) } def postInit {} } GuiHandler.scala: object GuiHandler { val guiScroll = 0 } class GuiHandler extends IGuiHandler { import GuiHandler._ def getServerGuiElement(id:Int, player:EntityPlayer, world:World, x:Int, y:Int, z:Int) = id match { case _ => null } def getClientGuiElement(id:Int, player:EntityPlayer, world:World, x:Int, y:Int, z:Int) = id match { case i if i == guiScroll => new GuiScroll() case _ => null } }
  18. Except doing it that way would require two separate implementations - not very clean at all. Wouldn't null-checking be cleaner than that? I don't know, maybe that's just me being weird about how I code.
  19. The only real problem with that approach is that due to the auto-constructed nature of capabilities, that becomes a bit of a logistical pain in the backside. For example, the function for registering a capability takes a factory for them, in a context where I have no possible way to access the player. I'll probably just end up making them a nulled optional argument... Not optimal either, but depending on how i play it I could get it to work (probably...)
  20. That would indeed probably be the simplest way, although if you have any custom NBT attached to it you'll need to copy it over.
  21. I'm working with the capability system for mana and custom levels/experience, and trying to expose custom Forge events for things like leveling up or your mana being full. However, as far as I can tell I either have to do this externally (not optimal) or have some way of getting or storing the player by capability instance. Any ideas on how to do this efficiently? LevelHandler: trait LevelHandlerLike { var level,maxLevel:Int var exp:Float def expToNext = if(level >= maxLevel) 0 else Math.pow(level, 1.1).toFloat*100 def setLevel(lvl:Int) { level = lvl; updateLevelInfo } def setExp(amt:Float) { exp = amt; updateLevelInfo } def setMaxLevel(lvl:Int) = maxLevel = lvl def addExp(amt:Float) = setExp(exp+amt) def updateLevelInfo { if(level >= maxLevel) { exp = 0; return } if(exp >= expToNext) { exp -= expToNext setLevel(Math.min(level+1, maxLevel)) } } def copyTo(lh:LevelHandlerLike) { lh.setMaxLevel(maxLevel) lh.setLevel(level) lh.setExp(exp) } } class LevelHandler(var level:Int = 0, var exp:Float = 0, var maxLevel:Int = 0) extends LevelHandlerLike with ICapabilitySerializable[NBTTagCompound] { private var dirty = true private var lvupev = false def shouldFireLevelUpEvent:Boolean = { val o = lvupev; lvupev = false; o } private def updateDirty[T <% Float](bfr:T, aft:T, isLevel:Boolean=false) = if(bfr != aft) { dirty = true; if(isLevel) lvupev = true } override def setLevel(lvl:Int) { val old = level; super.setLevel(lvl); updateDirty(old, level, true) } override def setExp(amt:Float) { val old = exp; super.setExp(amt); updateDirty(old, exp) } override def setMaxLevel(lvl:Int) { val old = maxLevel; super.setMaxLevel(lvl); updateDirty(old, maxLevel) } def updateClient(player:EntityPlayer, force:Boolean=false) = if(!player.worldObj.isRemote && (force || dirty)) { ChuuniMod.network.sendTo(new MessageUpdateClient(this), player.asInstanceOf[EntityPlayerMP]); dirty = false } def hasCapability(capability:Capability[_], f:EnumFacing) = capability == Capabilities.LEVEL def getCapability[T](capability:Capability[T], f:EnumFacing) = { if(capability == Capabilities.LEVEL) this else null }.asInstanceOf[T] def serializeNBT:NBTTagCompound = { val nbt = new NBTTagCompound nbt.setInteger("level", level) nbt.setFloat("exp", exp) nbt.setInteger("maxLevel", maxLevel) nbt } def deserializeNBT(nbt:NBTTagCompound) = { setLevel(nbt.getInteger("level")) setExp(nbt.getFloat("exp")) setMaxLevel(nbt.getInteger("maxLevel")) } } object LevelHandler { def instanceFor(player:EntityPlayer) = player.getCapability(Capabilities.LEVEL, null) def getHandlerInstance = new LevelHandler def getStorageInstance = new LevelHandler.Storage def getHandlerFactory = new Callable[LevelHandler] { def call = new LevelHandler } class Storage extends IStorage[LevelHandler] { def writeNBT(cap:Capability[LevelHandler], ins:LevelHandler, f:EnumFacing) = ins.asInstanceOf[LevelHandler].serializeNBT def readNBT(cap:Capability[LevelHandler], ins:LevelHandler, f:EnumFacing, nbt:NBTBase) = ins.asInstanceOf[LevelHandler].deserializeNBT(nbt.asInstanceOf[NBTTagCompound]) } class MessageUpdateClient(lh:LevelHandlerLike) extends IMessage with LevelHandlerLike { var level,maxLevel:Int = 0 var exp:Float = 0 if(lh != null) lh.copyTo(this) def this() = this(null) def fromBytes(buf:ByteBuf) { level = buf.readInt; exp = buf.readFloat; maxLevel = buf.readInt } def toBytes(buf:ByteBuf) { buf.writeInt(level); buf.writeFloat(exp); buf.writeInt(maxLevel) } } object MessageUpdateClient { class Handler extends IMessageHandler[MessageUpdateClient, IMessage] { def onMessage(msg:MessageUpdateClient, ctx:MessageContext):IMessage = { Minecraft.getMinecraft.addScheduledTask(new Runnable { def run = { val player = Minecraft.getMinecraft.thePlayer val lh = LevelHandler.instanceFor(player) msg.copyTo(lh) }}) null } } def register(net:SimpleNetworkWrapper, id:Int) = net.registerMessage(classOf[MessageUpdateClient.Handler], classOf[MessageUpdateClient], id, Side.CLIENT) } } You can see my hacky, sort-of-works way of doing it in LevelHandler.shouldFireLevelUpEvent and related.. but this relies on the EventHandler checking this any place that it updates the LevelHandler. Bleh. I can handle the ManaHandler with the same concept once I get the LevelHandler exposed.
  22. That would be nice... Java/Scala interop always gets me down. "Seamless" my eye...
  23. *sigh* thought so. Won't be pretty, but then neither is this whole process. Thanks!
  24. That's about what I figured. Do you know any way around it? I'd prefer not to make this an implementation detail of whatever mixes in the trait.
×
×
  • Create New...

Important Information

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