-
Posts
1773 -
Joined
-
Last visited
-
Days Won
61
Everything posted by V0idWa1k3r
-
You are. The formats have changed to work with GL >=3.0 startDrawingQuads -> begin, now needs a format to be specified for vertices. addVertex -> pos(x, y, z).tex(u, v).color(r, g, b, a).normal(x, y, z).lightmap(s, t).endVertex(). Note that the chaining will be different for the format you choose. If your format is POSITION_TEX you will only have pos(...).tex(...).endVertex() draw is still draw. Look at the way vanilla works with tessellator now in vanilla code. GUIs are a good example as they usually manipulate tessellator directly
-
[1.11.2] Make Water Bottles the same as a Bucket
V0idWa1k3r replied to CyberPunkBln's topic in Modder Support
If you cancel the forge event you are handling then no additional behaviour will occur. Most forge events can be canceled with setCanceled(boolean b) -
[1.11.2] Make Water Bottles the same as a Bucket
V0idWa1k3r replied to CyberPunkBln's topic in Modder Support
Depends on how you want to achieve it. If you are using forge then the events are: PlayerInteractEvent.RightClickBlock fires when the player clicks on a solid block in the world. PlayerInteractEvent.RightClickItem fires when the player presses the right mouse button with an item in his/hers hand and there is no block with a collision box that is being targeted by the player. For both events you can get the world, use the World::rayTraceBlocks(Vec3d start, Vec3d end, boolean stopOnLiquid, boolean ignoreBlockWithoutBoundingBox, boolean returnLastUncollidableBlock) to get the block the player is effectively looking at. If it is the desired water block fill your glass bottle with water and remove the water block. Both events are cancelable so you can prevent vanilla behaviour. As @Jay Avery said you can look at the way buckets handle their raytracing of water to understand how to do it correctly. -
[1.11.2] Make Water Bottles the same as a Bucket
V0idWa1k3r replied to CyberPunkBln's topic in Modder Support
I think that his problem is the following: He made all water in the world finite and is now trying to achieve correct item behaviour. Water buckets behave just fine as they remove the water block they are used on. However glass bottles don't. They just fill up with water and the block is not removed. Right now he is using one of events to remove the water block the bottle is filled from. It however only functions with water blocks that have a solid block directly under them as the event he uses only fires when the block with a collision bounding box is clicked. At least this is the way I am understanding the issue. CyberPunkBln if that is your issue you can use forge's PlayerInteraction events. There are 2 - when a solid block is clicked and when a player performs right click with an iten without targeting a block. Then you can raytrace the block the player is looking at and remove it. -
Yes... Although now when I've looked into the container class it seems that you can get the slot by your ID using the getSlot method, so storing it in a field is not really necessary. Is is for your recipe handling as you need to pass it the content of your extra slot somehow
-
A... java field? You know, public InventoryCrafting craftMatrix; public IInventory craftResult; public World world; private final BlockPos pos; Those? They are all fields, and you want your own to store your slot so you can interact with it later from other methods
-
I believe the first parameter of the slot is the inventory it belongs to. If you want to interact with your slot later you probably want to store it in a field
-
You need to offset the vertexbuffer/gl matrix(whichever you are using) before rendering the lines at the desired position. Think of it this way: Every time MC renders the world it offsets everything based on the player's position. The RenderWorldLast event is fired when those offsets are applied. If you want your outline to be stationary and not follow the player you need to 'negate' them by offsetting your rendering back to where it was(0,0,0) and then render at the desired position(x,y,z). So your rendering would then look like calculate offsets offset(-offsets) render boxes loop offset(offsets). As I usually do, here is a simple example: // your positions. You might want to shift them a bit too int sX = yourX; int sY = yourY; int sZ = yourZ; // Usually the player Entity entity = Minecraft.getMinecraft().getRenderViewEntity(); //Interpolating everything back to 0,0,0. These are transforms you can find at RenderEntity class double d0 = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * (double)evt.getPartialTicks(); double d1 = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * (double)evt.getPartialTicks(); double d2 = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * (double)evt.getPartialTicks(); //Apply 0-our transforms to set everything back to 0,0,0 Tessellator.getInstance().getBuffer().setTranslation(-d0, -d1, -d2); //Your render function which renders boxes at a desired position. In this example I just copy-pasted the one on TileEntityStructureRenderer renderBox(Tessellator.getInstance(), Tessellator.getInstance().getBuffer(), sX, sY, sZ, sX + 1, sY + 1, sZ + 1); //When you are done rendering all your boxes reset the offsets. We do not want everything that renders next to still be at 0,0,0 :) Tessellator.getInstance().getBuffer().setTranslation(0, 0, 0); note that if you want to outline more than 1 box like this you would need to apply player offsets first, then render your boxes in a loop, then reset the offsets. This is a result I get with my example:
-
You can render the outline in any of forge's rendering events. I would recommend RenderWorldLastEvent. To make it render on top of everything just disable depth in the GlStateManager. Don't forget to re-enale it once you are done. The TileEntityStructureRenderer can assist you with rendering the box itself - see how it is done there, in vanilla. Once you piece it all together you can store the positions of the blocks you want to outline in any array and in the event iterate through that array, offset the gl matrix accordingly(again, look at how vanilla handles it, generic entity rendering is the example you need) and render your box.
-
Look at the way it is done in vanilla (you will mostly be looking at the ContainerWorkbench). The craftMatrix field, slot initialization and the onCraftMatrixChanged are the things that you will need to build your own functional "crafting container". The most difficult part of it I guess is the CraftingManager as you have mentioned, but you could create a new recipe class that will implement IRecipe, have a Shaped/ShapelessOreRecipe stored in there for the 3x3 matrix and a string representing the oredict id of your pan/whatever you want the recipe to work with. Then you would add your recipes to some kind of array/list so in your container you could iterate through them to find the matching one. You do not need the full functionality of the CraftingManager class But it still would be a good idea to implement those which are related to crafting. Sounds confusing enough? Here is a very simple example: public class YourRecipe implements IRecipe { public final IRecipe craftMatrixRecipe; public final String penItem; ... public YourRecipe(...){...} public boolean matches(InventoryCrafting inv, ItemStack fryingPenItemStack, World w) { return yourCheckThatFryingPenItemStackParamIsThePenItemYouWant && this.craftMatrixRecipe.matches(inv, w); } ...All other implemented methods. You can see how they are handled in vanilla & forge recipes. There is nothing special to them } public class SimpleCraftingManager { public static List<YourRecipe> allMyRecipes = Lists.newArrayList(); public static void register(YourRecipe rec) { allMyRecipes.add(rec); } public static ItemStack findMatchingRecipe(InventoryCrafting craftMatrix, ItemStack penItem, World worldIn) { for (YourRecipe rec : allMyRecipes) { if (rec.matches(craftMatrix, penItem, worldIn)) { return rec; } } return ItemStack.EMPTY; } ...All other implemented methods you need } Or you could even make your instance of InventoryMatrix have a not 3x3 height/width and have 1 less method as you will be able to use the regular IRecipe::matches In your container then you would simply reference your CraftingManager instead of vanilla's. Note that if you want NEI/JEI/Whatever integration you will need your own handlers for that.
-
[Design question]Value synchronization vs killing it with packets
V0idWa1k3r replied to Zethariel's topic in Modder Support
Why are you sending 5 floats per packet each tick/second? Only send things that have changed and send them as a single packet. Implement the 'dirty' trackers for your floats (simple booleans will do) and set them to true everytime a value changes. Then in your tick/second function grab every field that has it's dirty tracker set to true and pack it into a single packet. That way you are only syncing what needs to be synced. You could append a byte before each value to mark it's "id" so when you read your packet you know which fields you are recieving. Another solution is to render your mana bar by interpolating values (current vs prev. tick) using the partialTicks. Vanilla does it everywhere. Literally. It makes flickering almost impossible to notice as everything is smooth, including that flickering. Also 5 floats is only 20 bytes. 20 bytes/packet/player is nothing -
You can wrap your actions you want to perform upon the packet's arrival in a Runnable. Then obtain a IThreadListener for the respective side (Client = Minecraft.getMinecraft().world, server = DimensionManager.getWorld(dimensionID)). That thread listener object has addScheduledTask method to execute your code on that thread.
-
:: is simply a way to write method names ClassName::MethodName As for the code example I suppose it would look something like this: Multimap<BiomeDictionary.Type, Biome> biomesAndTypes = HashMultimap.create(); for (Biome b : Biome.REGISTRY) { Set<BiomeDictionary.Type> types = BiomeDictionary.getTypes(b); for (BiomeDictionary.Type t : types) { biomesAndTypes.put(t, b); } } EntityRegistry.addSpawn(YourMonsterEntityClass.class, weight, min, max, EnumCreatureType.MONSTER, biomesAndTypes.get(BiomeDictionary.Type.SANDY).toArray(new Biome[biomesAndTypes.get(BiomeDictionary.Type.SANDY).size()])); Or for something more specific(in this case the entity is only allowed to spawn at sandy biomes which are not cold) List<Biome> criteriaMet = Lists.newArrayList(); for (Biome b : Biome.REGISTRY) { Set<BiomeDictionary.Type> types = BiomeDictionary.getTypes(b); if (types.contains(BiomeDictionary.Type.SANDY) && !types.contains(BiomeDictionary.Type.COLD)) { criteriaMet.add(b); } } EntityRegistry.addSpawn(YourMonsterEntityClass.class, weight, min, max, EnumCreatureType.MONSTER, criteriaMet.toArray(new Biome[criteriaMet.size()]));
-
It seems that there is a bug in the BiomeDictionary class somehow? At least it seems to be this way for me, I might be mistaken as my forge version is not the most recent(I'm 2 versions behind). If I am, I am sorry. For the FuzzyAcornIndustries: You can iterate through the biome registry and use the BiomeDictionary::getTypes(Biome) method to obtain the types for that specific biome, that should work (works for me). Then you would check if the obtained set contains your desired biome type and add it that way.
-
You could render your GUI directly with Tessellator's VertexBuffer object. See how vanilla handles it in the various Gui.class methods(including the 'drawTexturedModalRect you are already using'), experiment with it, it is pretty simple. You will then put your desired positions into the vertex buffer. You can calculate those positions based on your desired 'scale'. Or you could directly use GlStateManger's scale method. Just do not forget to push/pop the state matrix to not mess up the rendering of anything else and after/before scaling you would want to GlStateManger.translate your Gui position to adapt to scale changes(think of it as GlStateManager's scale will simply multiply ALL positions of your Gui(typically 4 corners of it) by the numbers you give to it without having a care about the current screen's size so you need to offset the position to display the Gui correctly). I would recommend tessellator's vertexbuffer though. Also note that in both cases you would have to implement custom buttons if you want them to work as they operate with parameters they are constructed with to check if the mouse is hovering over the button and those will obviously not scale on their own