-
Posts
624 -
Joined
-
Last visited
-
Days Won
1
Everything posted by Busti
-
You could use the Cauldron renderer in RenderBlocks as an example... Just make a text search for it...
-
I am using chickenbones render library to render models but everything it does is basically writing vertices into the tessellator... (It is working when I use it to draw a block) I am also using scala... GL11.glEnable(GL11.GL_BLEND) GL11.glBlendFunc(GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_SRC_ALPHA) CCRenderState.alphaOverride = 100 renderCenterGlass(connMap, ops :+ new IconTransformation(sprites(0)):_*) renderConnectionGlass(connMap, ops :+ new IconTransformation(sprites(0)):_*) GL11.glDisable(GL11.GL_BLEND)
-
Render the water texture after you rendered the cauldron with your personal texture also after the last GL11.glPopMatrix(); and use the default, already registered water texture. You can access those textures by binding the default texture atlas to the render engine and using the water IIcon to get its UV coordinates which you then use in the model / tessellator. You can bind the default block texture like this: engine().bindTexture(TextureMap.locationBlocksTexture); And here is the water IIcon: IIcon iicon = BlockLiquid.getLiquidIcon("water_still"); You can also use the registerIcons() method in your block class to register your personal texture and use it in a similar way then. It can also have animations using that method. The reg.registerIcon(path) method returns an IIcon.
-
You can set it to be accessible using reflection. This StackoOverflow post shows you how to do it: http://stackoverflow.com/questions/3301635/change-private-static-final-field-using-java-reflection But be aware that reflection uses quite a lot of cpu power...
-
Hello, Is there any way to render something transparent using an IItemRenderer? I tried activating GL_BLEND and setting the BlendFunc but it doesn't seem to work...
-
Microsoft buys Mojang/Minecraft ... FAQ for Forge Team/LexManos
Busti replied to Aridhol's topic in General Discussion
As I first saw the news I was pretty shocked... But I think at this moment everybody is pretty much overreacting. Yes Microsoft has Lawyers and yes the change they bring is really dangerous for the modding and server community. But MS literally just spend 2.5 BILLION Dollars on a game that is driven by its status in the world and by its community and they will do their very best to not screw this up. It seems like they are aiming for the Eduacautional sector of Minecraft because thats the best way to get their money back. They could always hire programmers to create a plugin system and if they do so they would propably destroy any other abstraction layer, but they cant create the mods. There would just be a plugin system that nobody uses, but only when we modders DONT use it... It is important that we never us such systems as a community because that would be the only way to stop such things. I myself will always continue modding and will use forge as long as it continues to exist. If forge is ever going to be stopped I will stay with the last version of it and continue modding in an outdated version of minecraft. But I am never going to use any MS plugin system. I would totally like to help coding forge but I am afraid I don't have the time or the experience for doing so. But I am happy to see that you, Lex are continuing and I wish you and the whole modding comunity the best luck you can get. -
ChickenBones Multipart - [Highly Advanced]
Busti replied to Busti's topic in User Submitted Tutorials
OOps... It was supposed to be an "if (false)" statement as we want to only return the middle box there because we still want to be able to place covers on the sides. If we were to return all of the boxes there we wouldn't be able to place those, they would fail the occlusion test. We use the statement later to test for those boxes one at a time and test if a cover is placed or not. The result is then used to update the possible connections of the pipe. I still need some time for the next tutorial since my code is still pretty messy and needs a lot of cleanup. -
Ok it seems to work now... EDIT: I forgot about the old "toLowerCase" thing ._.
-
Hi, I registered a texture like this from an Item. @SideOnly(Side.CLIENT) def registerIcons(reg:IIconRegister) { sprites(0) = reg.registerIcon(TechnicaCore.RESOURCEID + "parts/Glass_Basic") } ...how can I use it in a rendering method with the Tesselator in the world renderer? I tried using its U and V values for the vertex adding but it doesn't seem to work: val minU = sprites(0).getMinU val maxU = sprites(0).getMaxU val minV = sprites(0).getMinV val maxV = sprites(0).getMaxV //Minecraft.getMinecraft.renderEngine.bindTexture(TextureMap.locationItemsTexture) val tesselator = Tessellator.instance tesselator.addVertexWithUV(pos.x+1, pos.y, pos.z, maxU, minV) tesselator.addVertexWithUV(pos.x+1, pos.y+1, pos.z, maxU, maxV) tesselator.addVertexWithUV(pos.x, pos.y+1, pos.z, minU, maxV) tesselator.addVertexWithUV(pos.x, pos.y, pos.z, minU, minV) I also tried using the Item Texture but it doesn't work either.
-
ChickenBones Multipart - [Highly Advanced]
Busti replied to Busti's topic in User Submitted Tutorials
That's actually a really nice tutorial. I wonder why I've never seen it before. I will add it to the parent post -
ChickenBones Multipart - [Highly Advanced]
Busti replied to Busti's topic in User Submitted Tutorials
Oh sorry I forgot to delete that. It is actually for the piping tutorial and does all the connection work but I didn't got anything to render just yet. You actually have to extend TMultiPart there. -
Did you spawn it on the server? When its spawned on the server it appears to exist but wont be saved.
-
ChickenBones Multipart is an API / Library by Chickenbones to create multiple Tileentitys inside a single block, so called Parts. Note: The mod is released under the name 'Forge' Multipart, however, it is NOT official and has no relation to the official Forge project. As such we will refer to it as CBMP in reference to it's author ChickenBones. It also comes with a submod called 'Forge' Microblock (Again, no relation to Forge itself) which adds some parts to, for instance, cover up pipes. Some spotlights can be found on its official Minecraft Forums Topic. [Click Here] This post will contain all CBMP related tutorials. If you want to make your own just post it as a reply and I am going to add it. CBMP makes use of a programming language called Scala. Please make sure that you have basic knowledge of Scala since almost all of CBMP's code is written in scala. On of the best tutorials for Scala is this one: There's also a Java implementation of this tutorial by larsgerrits https://github.com/Larsg310/FMP-Tutorial Another great tutorial was made by Whov: http://whov.altervista.org/forge-modding-tutorials/ All Tutorials in chronological order: [spoiler=Installing Scala] [*]Download and Install the latest Scala binaries from: http://www.scala-lang.org/download/ [*]IntelliJ Idea is the better choice because it suggests scala code. Eclipse: (Please note that the scala plugin is not ready for Eclipse Luna yet) [*]IntelliJ Idea: [*]Go to: File / Settings / Plugins and click 'Install JetBrains Plugin...' [spoiler=Image] [*]Choose "Scala" from the List and Install the plugin. [*]Right-click on your project and choose 'Add FrameWork support' from the context menu. [*]Select Scala in the list and correct the path for the scala home to where you installed your scala binaries. For me its C://Program File(x86) [*]You should now be able to use scala code and files. [spoiler=Adding CBMP to your enviroment] [*]Create a /libs folder in your modding enviroment. (Where the build.gradle file is) [*]Download the CBMP dev and src .jar from http://files.minecraftforge.net/ForgeMultipart/ and put them into the /libs folder. [*]Download the CodeChickenCore and NEI dev and src .jar form http://chickenbones.net/Pages/links.html and put them into the /libs folder. [*]Download the CodeChickenLib dev and src .jar from http://files.minecraftforge.net/CodeChickenLib/ and put them into the /libs folder. [*]You might want to copy the CodeChickenCore and NEI dev.jar into /eclipse/mods because they don't seem to be compiled in 1.7.10 (Check this yourself) [*]Finally link the dev.jar's as Librarys in your Enviroment and attach the sources. (You can simply Import both the same way in almost all IDE's and they will do the rest.) You should now be able to use CBMP and NEI. You can test CBMP by placing two torches in a single block. [spoiler=Creating your first part] It's finally time: After some installation horror we can begin with our first part. This part is just going to be a hitbox half the size of a block in the middle of it but we will later make a pipe out of this. You will also be able to place covers on its sides. For part registration and functionality you will need 3 Basic classes. The PartFactory which handles the registration itself, the PartItem you have in your inventory and the Actual part itself. Lets begin with the Part factory: Right-click on the folder you want to have the class in and choose a new scala class / file (not a java class like you normally do) and call it whatever you want... I called mine PartFactory. package com.example.examplemod import codechicken.multipart.MultiPartRegistry import codechicken.multipart.MultiPartRegistry.IPartFactory //This is the actual registration class class PartFactory extends IPartFactory { //We call this method from our main mod class. def init() { //Parts are registered by using String maps. Each individual part / subtileEntity has a string like when you register a block. MultiPartRegistry.registerParts(this, Array[string]( "examplePipe" )) } //This method is overridden from IPartFactory and returns a new Part.class matching the assigned string name. override def createPart(name: String, client: Boolean) = name match { case "examplePipe" => new ExamplePipe case _ => null } } //This is the static object used to call the Reg. class object PartRegistry extends PartFactory Next we want to take a look at the PartItem, which is basically a normal item implementing an Interface which makes it place a part in the world when you right-click with it. We, again, create a new scala file and call it Items or PartItems because we can use it later for multiple PartItem classes. package com.example.examplemod import codechicken.lib.vec.{Vector3, BlockCoord} import codechicken.multipart.{TItemMultiPart, MultiPartRegistry} import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.{ItemStack, Item} import net.minecraft.world.World //We can add multiple classes like this one in this scala file. class ItemPartExamplePipe extends Item with TItemMultiPart { def newPart(item:ItemStack, player:EntityPlayer, world:World, pos:BlockCoord, side:Int, vhit:Vector3) = { //We create a new part.class and return it. Any modifications (set NBT data in the part by Item NBT) can be made here. val w = MultiPartRegistry.createPart("examplePipe", false).asInstanceOf[ExamplePipe] w } } Don't forget to register this item like any other item in your mod class. Last but not least we want to create the Part itself. It is a bit like the combination of a block and a TileEntity and has all methods for Rendering, Hit- / Boundingboxes, Updates, NBT data and many more. package com.example.examplemod import codechicken.lib.raytracer.IndexedCuboid6 import codechicken.lib.vec.Cuboid6 import codechicken.multipart.{TMultiPart, TNormalOcclusion} import scala.collection.JavaConverters._ class ExamplePipe extends TMultiPart with TNormalOcclusion { //We have to return the pipes register name a last time. override def getType = "examplePipe" //Here we want to generate whatever boxes the Pipe is going to use later. For now it is only a center box but later we want to add sides for every possible connection. def generateBoxes = { import com.example.examplemod.PipeBoxes._ var boxes = Seq(oBounds(0)) boxes } //Here we return the collision boxes generated in generateBoxes(). We need to convert it to java because this method expects a java iterable not the scala one. def generateCollisionBoxes = { import mlb.technica.experience.PipeBoxes._ var boxes = Seq(oBounds(0)) boxes } //This method returns any occlusion boxes for the part to check if another part can be placed in the same space as this one. override def getOcclusionBoxes = { import mlb.technica.experience.PipeBoxes._ Seq(oBounds(0)).asJava } //This method is used to return any sub parts that can be broken or clicked by the player to render their outlines. The connections the pipe makes to its sides are such subparts. override def getSubParts = { val b = generateBoxes var i = Seq[indexedCuboid6]() for (c <- b) i :+= new IndexedCuboid6(0, c) i.asJava } } //This Object stores all the possible boxes. object PipeBoxes { var oBounds = { val boxes = new Array[Cuboid6](1) val w = 2/8D boxes(0) = new Cuboid6(0.5-w, 0.5-w, 0.5-w, 0.5+w, 0.5+w, 0.5+w) boxes } } Finally we want to take a look at our examplemod class where everything should be registered. package com.example.examplemod; import net.minecraft.init.Blocks; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; import cpw.mods.fml.common.event.FMLInitializationEvent; @Mod(modid = ExampleMod.MODID, version = ExampleMod.VERSION) public class ExampleMod { public static final String MODID = "examplemod"; public static final String VERSION = "1.0"; public static Item item_ExamplePipe; @EventHandler public void init(FMLInitializationEvent event) { item_ExamplePipe = new ItemPartExamplePipe().setUnlocalizedName("ExamplePipe").setCreativeTab(someTab); PartRegistry.init(); GameRegistry.registerItem(item_ExamplePipe, "ExamplePipe", MODID); } } You should now have a part that does nothing at all... Please make sure that there are not any missing Imports I might have forgotten. [spoiler=Using multiple Hit / Bounding-boxes] Having multiple Hit and Bounding-boxes is important for anything that goes beyond a simple cube. For our pipe we want to have a single bounding box in the middle of the part and six more for every side connection of the pipe. CBMP gives us the possibility to create each box that a part can have individually. (Bounding, Collision and Occlusion) The Bounding-boxes, which are called SubParts in CBMP, are used to generate boxes the player can interact with. They are also used to render the parts outline which can also be rendered individually. The Collision-boxes are used for collision testing with Entity's. It determines where you can stand on the part and where you can walk through. The Occlusion-boxes are used to test if your part collides with another so nothing else can be placed at the position of your part. The Hollow Cover is a good example for the use of different boxes since it uses a single Collision and Bounding-box but four occlusion boxes to create the hole in the middle. You can create multiple boxes by adding this simple code to your TMultiPart: (ExamplePipe) class ExamplePipe extends TMultiPart with TNormalOcclusion { //We have to return the pipes register name a last time. override def getType = "examplePipe" //Here we generate the collision boxes. def generateCollisionBoxes = { import mlb.technica.experience.PipeBoxes._ var boxes = Seq(oBounds(6)) for (s <- 0 until 6) boxes :+= oBounds(s) boxes } //Here we want to return the collision boxes generated in generateCollisionBoxes(). We have to convert it to java since it is expected. override def getCollisionBoxes = { generateCollisionBoxes.asJava } //This method returns any occlusion boxes for the part to check if another part can be placed in the same space as this one. We will just return the middle box for now as nothing can connect yet. //But we already added the structure for multiple boxes. override def getOcclusionBoxes = { import mlb.technica.experience.PipeBoxes._ if (false) else Seq(oBounds(6)).asJava } //This method is used to return any sub parts that can be broken or clicked by the player to render their outlines. The connections the pipe makes to its sides are such subparts. override def getSubParts = { val b = generateCollisionBoxes var i = Seq[indexedCuboid6]() for (c <- b) i :+= new IndexedCuboid6(0, c) i.asJava } } //This Object stores all the possible boxes. object PipeBoxes { var oBounds = { val boxes = new Array[Cuboid6](7) val w = 2/8D boxes(6) = new Cuboid6(0.5-w, 0.5-w, 0.5-w, 0.5+w, 0.5+w, 0.5+w) for (s <- 0 until 6) boxes(s) = new Cuboid6(0.5-w, 0, 0.5-w, 0.5+w, 0.5-w, 0.5+w).apply(Rotation.sideRotations(s).at(Vector3.center)) boxes } } This should provide a simple way to add more boxes to the part, by creating arrays of Cuboids. In the next tutorial we want to make them connect automatically. [spoiler=Rendering] CBMP has two main methods to render the part in the world but the bounding-box renderer can also be overridden. The part can be rendered using static and dynamic rendering. The static renderer uses the world renderer and only updates every time something in the world changes while the dynamic renderer updates every frame. It can be used for moving things as it also passes the partialTickTime. First of all we want to take a look at the static renderer. When using the static renderer the Tessellator is already running in quad mode and only draws when the world has rendered. It can be accessed by overriding the renderStatic method in the part. We also have to return if vertecies were added to the Tessellator. @SideOnly(Side.CLIENT) override def renderStatic(pos: Vector3, pass: Int) = { TextureUtils.bindAtlas(0) //First of all we want to bind the Block texture atlas just to be super safe... /* * All of your rendering code can go here but we have to register and use a texture first... */ } Now that we have the renderer set up we can't simply bind a texture as it would also apply to every other block rendered by the world renderer. But we can register a texture to the main texture atlas where all the block textures are stored. To do so we can simply use the Item we created for the part. class ItemPartExamplePipe extends Item with TItemMultiPart { val sprites = new Array[iIcon](1) //For some reason it won't let me use a simple IIcon but we can use this for other parts... def newPart(item:ItemStack, player:EntityPlayer, world:World, pos:BlockCoord, side:Int, vhit:Vector3) = { val w = MultiPartRegistry.createPart("examplemod_examplepipe", false).asInstanceOf[examplepipe] w } @SideOnly(Side.CLIENT) override def registerIcons(reg:IIconRegister) { sprites(0) = reg.registerIcon("modid:parts/TextureName") //The texture is stored at assets/modid/textures/blocks/parts } /** * Returns 0 for /terrain.png, 1 for /gui/items.png * We use it to make the item not register the texture in the item texture atlas. */ @SideOnly(Side.CLIENT) override def getSpriteNumber = 0 } Now that we have the texture IIcon we can get the textures UV coordinates from it and use it for the tessellator. uMin = sprites(0).getMinU uMax = sprites(0).getMaxU vMin = sprites(0).getMinV vMax = sprites(0).getMaxV When we want to use the dynamic renderer we just have to start / draw / stop it. We can use the CCRenderState Library to do so. It also has methods for light adjusting and transparency, which might come in handy when you have light problems. override def renderDynamic(pos: Vector3, frame: Float, pass: Int): Unit = { TextureUtils.bindAtlas(0) CCRenderState.startDrawing() // Render stuff CCRenderState.draw() } Finally make sure that you only render solid stuff when the pass var is 1 and only render transparent stuff when the pass is 1. Never render stuff at both passes as it would just cause framerate lag. When you don't render something make sure to return false, otherwise the game will crash. More Tutorials will follow weekly... I apologize for any English mistakes. Please write a comment about them and any error you get in the code so I can improve the Tutorial. Overall Credits: Chickenbones: For the great code. MrTJP: For the great example that is ProjectRed. Any tutorials without credit are by me. Edited by Lex, CBMP has no realtion to Forge, so make that clean and changed FMP to CBMP. Go to: Help / Install New Software [spoiler=Image] Type the Update URL for the Scala plugin from http://scala-ide.org/download/current.html into the "Work with" field and click 'Add...' [spoiler=Image] Choose "Scala" as name and click 'OK' Select all components and click 'Next' [spoiler=Image] Click 'Next' again and accept all Licenses. Last but not least click 'Finish' to Install the plugins. Finally right-click on your project and choose Configure / Add Scala Nature from the context menu.
-
Assign a new Entity Renderer to the Entity class... Most of the Entity tutorials have that...
-
Create a /jars/ folder in your forge folder and put them there then link them as librarys in your IDE. You might want to put them in /eclipse/mods as well but normally they should be added automatically. Dont forget to insert the mods into the /mods folder as well.
-
You have to create an ItemStack with an "infinite" damage value for the crafting to work with any damage value
-
You would have to replace the ItemDamageCrafting() with your constructor (The place where you set the creative Tab and name and so on) So it would be public bankerHammer()
-
Or you could use this ItemStack in your recipe: new ItemStack(ItemHammer, 1, Short.MAX_VALUE)
-
Oh sorry I forgot that... put this in your class and intitialize it: private Random rand; public ItemDamageCrafting() { rand = new Random(); }
-
There is an old Tutorial on the wiki for 1.5.2 some things are still working: http://www.minecraftforge.net/wiki/Gui_Overlay
-
This is the code I use to decrease an Items durability. It also breaks the Item and plays the breaking sound: @Override public boolean hasContainerItem(ItemStack stack) { return true; } @Override public ItemStack getContainerItem(ItemStack itemStack) { if (itemStack.attemptDamageItem(1, rand)) { itemStack.stackSize--; if (itemStack.stackSize < 0) itemStack.stackSize = 0; itemStack.setItemDamage(0); itemStack = null; Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.func_147673_a(new ResourceLocation("random.break"))); } return itemStack; }
-
Have a look at net.minecraft.block.BlockLog.class and BlockRotatedPillar.class
-
The last "1" is also in the wrong bracket but you wont need it anyways since a new ItemStack always creates a stack of a single item...
-
Remove the new Object[]{ } with the brackets and it should work.
-
[1.7.10]Cant view forgeMultiPart classes in dev environment
Busti replied to slugslug's topic in Modder Support
You have to use "gradlew setupDecompEnvoroment" ...