-
Posts
1773 -
Joined
-
Last visited
-
Days Won
61
Everything posted by V0idWa1k3r
-
It is simply a storage for items. It's the entire IInventory in one line of code. Elegant and simple. Instead of defining the ItemStack array/list you define the ItemStackHandler with your desired size. Then you can use it the same way you would use the IInventory - there are getters and setters for items in slots and insert/extract methods. The best thing is that you do not need to implement IInventory anymore and simply need to expose your ItemStackHandler instance as a capability. Then the tutorial is crap and you can tell the author of the tutorial just that. IInventory is what, 4-5 years outdated by this point and people might not even bother with checking for it anymore since they assume everyone moved to capabilities by now. We simply try to provide a solution which gives you the best results and compatibility. We are not taking it to an extreme, we simply tell you "Don't use IInventory, use capabilities". Ahem. Direct method signature: @Deprecated //TODO: Remove in 1.13, Use ResourceLocation version. public static void registerTileEntity(Class<? extends TileEntity> tileEntityClass, String key) BlockBase is an antipattern. What even is this? You do not need any of this. Just override TileEntity#shouldRefresh. You do not need this. You already return the state for placement at Block#getStateForPlacement. You do not need this since the super implementation of this method should already return MODEL. You are only (de)serializing your facing property but not the ACTIVE one. I assume you want that one to persist too. This is the IHasModel all over again just this time without an interface. You do not need this in your block class. This goes into your ModelRegistryEvent directly, even without the need for the proxy. All of the things you need are public. There is no need for this method to be anywhere else apart from your ModelRegistryEvent. Are you sure this is correct? What if I only put 1 piece of coal in your furnace? Then when this code is executed the stack in slot 2 will be empty and the currentBurnTime will be 0. Even though it should be the burn time of coal. This code makes no sense. "Serialize these as an integer using 4 bytes but truncate them to shorts first thus discarding the first 2 bytes". Why? Don't cast them to shorts at all just save them as ints in the first place. The fact that they are casted to shorts in TileEntityFurnace is a Mojang bug. Sigh. You do not need the get/setField nonesense if you are not using IInventory. And you are not. Just access the fields directly. You probably do not want to be setting the state to a new one every tick. Only do it when the "should be" and "current" states do not match. Any particular reasons for this array to exist? You are not iterating it. You are just using it to access elements at an index. You might as well use ItemStackHandler#getStackInSlot directly then. You already know that fuel isn't empty by now. If isBurning returns true then the burnTime for the fuel is not 0. Then the fuel isn't empty. Why use insertItem here? You might as well be using setStackInSlot. This return is pointless since it is the last statement that gets executed. I don't know about eclipse but Idea warns you about these kinds of things. This is not really an issue btw, just me nitpicking. ? Why? handler.getStackInSlot(0).shrink(); handler.getStackInSlot(1).shrink(); Does the same and is 50% less code. ItemStackHandler#getStackInSlot already returns an ItemStack there is no need to cast it to one. Again, a normal IDE would warn you about these kind of things. You do not need this method since it is directly copied from TileEntityFurnace. Why did you do it in the first place? The method is static and public, you do not need to copy it. As for the actual issue... It's a bit hard for me to tell just by looking at this code. I'll try to debug this locally and provide you with an answer in a bit. As for shift-clicking - something is wrong with your logic in Container#transferStackInSlot. Use the debugger to find out what exactly.
-
What is this? If you want to know what the jump key is you must use KeyBindings. They are all public. Don't use keyboard.isKeyDown, use KeyBinding#isKeyDown. There are so many things wrong with this: You are leaking memory with this map since you never clean it up Player names can and will change Using strings as a key for a hashmap is a bad choice. Use a UUID You do not need this map at all. Use capabilities. This will persist between different saves since you never clean it. Don't use a HashMap. Use capabilities when you need to store something per player. Instead of all this tick/hashmap hackery use a KeyInputEvent to detect when the jump key is pressed and then perform the jump. Why? You can do this in a much simplier way: p.getPosition().down() And what if the block isn't an instance of BlockAir but is supposed to behave just like air, like RailCraft's residual heat? Use World#isAirBlock. This will fire when the jump event fires which is probably not what you want. You probably want to check that Entity.onGround is true in some kind of tick event. Also your double jump will only work if jumps[playername] == 1 yet you set it to 0 here thus making sure it won't work ever again. And you know why it won't work? Because when the tick event fires next and checks for the block below the player it is not going to be an air block. Thus it will set the jumps to 0 again even though you've jumped. Ad for your issue - use the debugger to find out what is wrong. However I suspect that if you fix everything I've mentioned the issue will fix itself.
-
Unless you want your mod to be client-side only you can't do this in the FMLInitializationEvent. And you do not want your mod to be client-only since you are planning to have dynamic collision boxes for your non-cubes. And the server needs to know about those.
-
[Solved][1.12] Entity#setAir(int air) does nothing
V0idWa1k3r replied to Spaceboy Ross's topic in Modder Support
Wouldn't you be able to just periodically(LivingUpdateEvent, check if Entity.ticksExisted % X == 0 to make the check happen once every X ticks) check whether the entity has a "space suit" or similar equipped and if not deal drowning damage via Entty#attackEntityFrom? As far as I can see there is no reason to use ASM here. -
Ahem. "Please bind my texture and then draw it at position [0,0] with a size of [0,0]" I don't think that this is the behaviour you wanted. Also you do not need to do this The game already does that for you.
-
[1.12] Render what entity sees on screen
V0idWa1k3r replied to Spaceboy Ross's topic in Modder Support
This statement is ambiguous. Do you mean see as in see through the eyes of the entity(read: see the game from a different perspective) or see as in see a picture of the entity's vision on your HUD? If it's the former then you do not need the framebuffers, you simply need to change the renderViewEntity although I've heard that it is not quite that simple and causes frustrum culling issues. -
[1.12] Render what entity sees on screen
V0idWa1k3r replied to Spaceboy Ross's topic in Modder Support
A snippet of what? Setting the renderViewEntity? Creating a framebuffer? Rendering everything all over again? Setting the renderViewEntity: Minecraft.getMinecraft().setRenderViewEntity(yourEntity) Creating a framebuffer(somewhat of a pseudo-code as I don't know if Minecraft allows using framebuffers directly like that(it might bind it's own framebuffer somewhere else) but I think for your purpose something like this should suffice - so don't use this code directly, it is meant to be an example) int rbo = GL30.glGenRenderbuffers(); // Should be a field GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, rbo); GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL30.GL_DEPTH24_STENCIL8, texWidth, texHeight); int fbo = GL30.glGenFramebuffers(); // Should be a field GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, fbo); GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL11.GL_TEXTURE_2D, tex, 0); GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_STENCIL_ATTACHMENT, GL30.GL_DEPTH24_STENCIL8, rbo); But I think the minecraft-way of doing framebuffers is in the net.minecraft.client.shader.Framebuffer class. However I have never used it and as such you need to figure it out yourself but I would imagine it's not too hard. Seems like it largely does the same my example code does but instead uses OpenGlHelper which is the correct way of doing it I suppose since it accounts for extensions. Rendering everything: Minecraft mc = Minecraft.getMinecraft(); FMLCommonHandler.instance().onRenderTickStart(mc.getRenderPartialTicks()); mc.entityRenderer.updateCameraAndRender(mc.getRenderPartialTicks(), System.nanoTime()); FMLCommonHandler.instance().onRenderTickEnd(mc.getRenderPartialTicks()); Note that you will have to handle the case of the game being paused and supplying renderPartialTicksPaused from the game's timer to the updateCameraAndRender method and for that you will need refiection. But you still haven't told us whether you even need all this framebuffer stuff. Do you just want to render the game from a different perspective or do you actually want to render a quad on the screen that shows what another entity is seeing? -
See how vanilla does music disks at ItemRecord and do the same.
-
[1.12.2][SOLVED] Passing NBT/Instance data to functions
V0idWa1k3r replied to RiNickolous's topic in Modder Support
Well here you register the value for the TYPE as an EnumChesterType. But later you use this data manager key as if it was associated with a byte. Stay consistent. If only java had a way to automatically check these kind of errors for you... You know, if only you could put a constraint on the TYPE parameter instead of it being a generic Object accepting anything. Something like DataParameter<Byte> TYPE = ... -
[1.12.2][SOLVED] Passing NBT/Instance data to functions
V0idWa1k3r replied to RiNickolous's topic in Modder Support
(De)serialize the enum as the ordinal. Use the ordinal in your DataManager. Pseudo-code: Deserialization: setType(EnumChesterType.values()[tag.readByte("type")]) Serialization: tag.writeByte("type", this.getType().ordinal()) getType: EnumChesterType.values()[dataManager.get(TYPE)] setType: dataManager.set(TYPE, type.ordinal()) -
[1.12.2][SOLVED] Passing NBT/Instance data to functions
V0idWa1k3r replied to RiNickolous's topic in Modder Support
You do not need all this "metadata" nonsense, get the enum by it's ordinal(Enum.values()[ordinal], Enum#ordinal). As for your capability question create a field of ChesterInventory in your entity class, (de)serialize it when needed(readFrom/writeToNBT), override Entity#hasCapability and Entity#getCapability. In those methods check if the capability is yours exactly the same way you are checking it in your provider. If it is return your ChesterInventory, otherwise return a super implementation(return cap == YOUR_CAP ? yourField : super.getCapability(cap, facing) and return cap == YOUR_CAP || super.hasCapability(cap, facing)) -
[1.12.2][SOLVED] Passing NBT/Instance data to functions
V0idWa1k3r replied to RiNickolous's topic in Modder Support
Consider changing your field from a string to an enum and serialize/deserialize it by an ordinal. It will save on both the NBT data size and the network packet size(more on that later). If you want some data of the entity to affect something on the client you need to create a new DataParameter, store your data in the entity's DataManager with that DataParameter as the key and retrieve the data by using that DataParameter as the key. See pretty much any minecraft entity for an example, an EntitySheep for example. Additionally since it is your own entity you do not need a capability provider, the entity itself is one. Directly have the inventory stored in your entity as a field, override Entity#hasCapability and Entity#getCapability to check if the capability parameter is your capability and return your inventory if it is, otherwise default to a super implementation. By the way if you are wondering the reason the static field worked was only because you were reaching across logical sides. It would not work if you would have launched a dedicated server and connected to it. -
[1.12] Render what entity sees on screen
V0idWa1k3r replied to Spaceboy Ross's topic in Modder Support
I actually don't think it's too challenging. As long as you change the renderViewEntity you can just do the same the game does when it renders everything. And it doesn't do much - it just calls a couple of public methods here and there. I also don't think CMEs are going to be a thing. CME happens when a collection is modified while it is iterated. That shouldn't happen when the game simply renders the scene twice. -
As far as I know OBJLoader is a custom model loader provided by forge designed to create block/item models from a wavefront file. If you are using OBJLoader then you must render your thing as an item. You could in theory bake the IModel you get from the loader yourself and later render it similar to how RenerItem#renderItemModelIntoGUI does it. That would be your example. But you would need to use ModelBakeEvent to bake your model first. And then you would need to fully mimic the code of RenerItem#renderItemModelIntoGUI(which expects an ItemStack btw so you would need to fix that too). It might be easier to use either a custom dummy item(don't show it in the creative menu and it will be completely hidden in the game) or a custom model loader, wavefront isn't too complicated - for example here is mine simple .obj loader and vertex uploader.
-
[1.12] Render what entity sees on screen
V0idWa1k3r replied to Spaceboy Ross's topic in Modder Support
You would need to create a framebuffer, set it up correctly, bind a render texture to it, bind it as the active framebuffer and pretty much mimic the entire rendering of the game but with the Minecraft.renderViewEntity being the entity of your choice. Then you would retrieve your texture, bind it and render a quad with it. This is theoretical, I have never done anything like that and don't even know if this is possible. Look at minecraft's shaders, they might offer an insight at the issue. Edit: If you simply want to change what the player sees on the screen(read: not add another texture on to of player's view) then you simply need to change Minecraft.renderViewEntity to the entity you wish to view the world from. However this was raised in an another topic and I believe the author of that topic had some frustrum culling issues with this approach. -
Depends on how you got it to load. If it is a block/item model then you can use RenderItem#renderItemAndEffectIntoGUI. If it is a custom model with a custom loader it is up to you to upload each and every vertex to the BufferBuilder. It also depends on where you want to do that from. If it is your own GUI then there are no problems. However if you just want it rendered somewhere on the screen at all time you will need to use an event. RenderGameOverlayEvent will do fine.
-
Overriding the player rendering is the only logical way of achieving what you want. Call GlStateManager.rotate and pass 180 degrees to it to rotate the model vertically. You can also just call ModelBiped#render instead of manucally rendering each part. I believe the event gives you all the parameters you need. Instead of passing a different scale parameter to the model scale the entire thing with GlStateManager.scale. However there is an issue with this approach - the model will dissappear if you look up above the player's bounding box even though it should be visible. The reason for that is that the player's bounding box is no longer in the camera's frustrum. I believe morph mod fixed that by manually changing the bounding box of the player. I don't know how exactly it did that but I suspect calling Entity#setSize might be enough.
-
LivingJumpEvent issues: Firing twice, not finding capability/NBT
V0idWa1k3r replied to Alekseyev's topic in Modder Support
AttachCapabilitiesEvent fires on both the server and the client. This means that the client also has the capability, just not the latest data. On the client you always have access to the client player - Minecraft.getMinecraft().player. That player will have your capability. All that's left is to set the data in that capability. I assume you do know how to create and use a setter. -
In the code the OP posted he has one though He is just using a deprecated version. Which is his issue as far as I can tell.
-
I don't see anything obviously wrong with your TE and Block(apart from what me and Diesieben mentioned). Use the debugger to find out what's going on. Alternatively if you could setup a github repository of your mod I could debug it locally.
-
@Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { super.writeToNBT(compound); compound.setInteger("cooldown", cooldown); if(compound.hasKey("CustomName", 8)) { compound.setString("CustomName", this.customName); } return compound; } This will never be true. This public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand){ if (!worldIn.isRemote){ if(worldIn.getTileEntity(pos) instanceof TileEntityTrebuchet) { ((TileEntityTrebuchet)worldIn.getTileEntity(pos)).setCooldown(0); } } } doesn't do what you think it does. It fires each tick, sure... for one random block in all of loaded chunks. Implement ITickable in your TileEntity and do the stuff with the cooldown there. What makes you think no tile entity is created? Have you placed a breakpoing in any of your methods that get the tile entity and inspected the TE local?
-
Separating them into 2 blocks creates a lot of confusion since your will have 2 meaningless blocks (BlockThingOne and BlockThingTwo). That said this way is pretty good if you want to save on block ids. Creating a unique block for each variant is a more intuitiva approach. This is also how variants function in 1.13. So this approach will allow you to update your mod to 1.13 easier and is more intuitive but it's less conservative on block ids. Alternatively you can store all your variants in a single block by using a TileEntity. Since TEs can be non-tickable now this approach is also viable.
-
This would be your issue. You are only spawning your arrow on the client. You need to do the opposite. Also you can't do this Blocks are singletons thus every block in the world that shares this class shares all the variables of that class. You must use a TileEntity if you want to store the data per-block.
-
Do you mean that you want the player's model replaced? Then handle the RenderPlayerEvent.Pre, render your model instead and cancel the event so the original model doesn't render.