Jump to content

Bektor

Forge Modder
  • Posts

    852
  • Joined

  • Last visited

Everything posted by Bektor

  1. Hi, I've got a little problem. My UI rendered on top of the block using the RenderGameOverlayEvent.Post event doesn't show my changed values. When my block received energy it normally displays the new values for how much energy it stores now, but in some rare condition it doesn't show the new value. For example you have a solar panel and place under the solar panel the new block. The new block shows always 0 until you relog. After a relog it shows the actual value. If you would place the solar panel ontop of the new block it will work as it should be, but having the solar panel already placed, the UI doesn't show the changed values. in update(): { [...] if(this.flag) { this.getWorld().notifyBlockUpdate(this.getPos(), this.getWorld().getBlockState(this.getPos()), this.getWorld().getBlockState(this.getPos()), 3); this.markDirty(); } } @Override public SPacketUpdateTileEntity getUpdatePacket() { return new SPacketUpdateTileEntity(this.getPos(), 3, this.getUpdateTag()); } @Override public NBTTagCompound getUpdateTag() { return this.writeToNBT(new NBTTagCompound()); } @Override public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { super.onDataPacket(net, pkt); this.handleUpdateTag(pkt.getNbtCompound()); } Note: flag will change when the block itself sends energy. Thx in advance. Bektor
  2. I might look into your idea at some point, thought not yet as I don't have enough time to do the required testing and implementation before the Server of a few friends of mine goes online. Hm, I'm wondering, how does this pathfinding from IC2 actually work?
  3. Hi, I'm currently working on an energy network and I am wondering how I can send energy into a specific direction. Imagine the following situation: You've got about 100 solar panels which produce energy You've also got one machine which should consume the energy Everything is connected with cables Point beeing: How can I and how do other mods find out in which direction the energy should be send so that it ends up beeing send to the consumer and not beeing send to producer 51 or the like. Thx in advance. Bektor
  4. The problem I see with this is when multiply players build up their networks and these networks aren't connected to each other. Here we have the problem that when adding blocks simply to the network in those methods: How do you know they are really connected to the network? Who tells you that they are connected to other cables? How do you know they are connected to other cables and those cables are part of the network and not some random cables in the world connected to no network?? Well, looking at the code, I guess this one if-check got lost in the endless code updates. ^^
  5. Ok, I've now used VisualVM and got the following results:
  6. Why would caching be more trouble than it's worth? Well, currently I plan just on sending a few hundred values to the client. This values might either be of integer type of boolean or long.
  7. The problem is that you call in line 193 registerBlock(rockwall); but I don't see that you initializes the rockwall value and thus it is null.
  8. I would rather start with FE and not use RF, because the FE API is build into Forge itself and thus it is always available. You would also not run into problems when the RF API doesn't update anymore. Like I remember a time where the mods by TeamCOFH got the 1.7.10 version 2014 and three years later followed 1.10.2 skipping 1.8.9 etc. Also most mods which support RF also support FE. More explanation on wether to use FE or RF or both might be found here: https://minecraft.curseforge.com/projects/redstone-flux Most mods have this complex implementations because they are supporting multiply energy APIs while converting the energy internally to the one which is requested as an output or they got their own energy API for internal uses and convert to RF or FE or whatever is required by the connected machines. When searching for mods which support energy and don't have complex systems I would start searching for mods which just support FE or maybe even support FE and Tesla, but I would also suggest looking into mods which got a fresh rewrite as otherwhise it might be that at one point they added support for FE into their existing systems and later on removed all the other APIs which aren't needed and such code is harder to read when you've got no idea how it works. WARNING: I might have missed some things in the following description as my own energy system also supports Tesla and thus is a bit more complicated. As a starting point for FE, I would highly suggest to learn about the Capability System by Forge, if you haven't already done this. https://mcforge.readthedocs.io/en/latest/datastorage/capabilities/ This is required as the Forge Energy system is based around capabilities. The next point would be create a new class extended from EnergyStorage or just implement all the code yourself using the IEnergyStorage interface which I would suggest if you plan on overwritting all methods provided in EnergyStorage anyway. This class should also implement the interface INBTSerializable<NBTTagCompound> if you want to store your energy data (I assume here that you are already familiar with Java Generics). In this class, save your data and read it in using normal NBT read and write methods (serializeNBT and deserializeNBT). This methods will later be called in for example our TileEntity's NBT read and write methods. In a more advanced system you might also use the capability methods to call wrapper classes around FE and Tesla and other capability based energy systems in this class, but this is out of scope of this basic overview. At next, you should create a TileEntity. This TileEntity needs your EnergyManager class you created before (the class which extends EnergyStorage or implements IEnergyStorage ). In here you add the read and write methods for NBT data and call the serializeNBT and deserializeNBT methods of your EnergyManager. For example: this.container.deserializeNBT(compound.getCompoundTag("Energy")); (container is here the instance of EnergyManager.) Then you also need the hasCapability and getCapability methods. I think you figure yourself out what to put in there. In the update method of your TileEntity you might want to put your logic about energy production or extraction in. this.container.receiveEnergy(int maxReceive, boolean simulate); this.container.extractEnergy(int maxExtract, boolean simulate); If you want to extract or receive energy from another TileEntity, you first need to get it at the specific location and than get the capability at the specific side. (Note: If a machine only sends energy in other machines underneath, then it might only return a capability for EnumFacing.DOWN.) An EnumFacing with null is also possible and might be used for internal purposes if I recall correctly. Do note that it is recommended for the most compatibility between mods to let your machines send the energy into the cables instead of letting the cables extract the energy out of your machines. https://github.com/SleepyTrousers/EnderIO/issues/4081#issuecomment-284911416 I hope this gives you a basic overview of how energy systems actually work. For items, I currently having figured it out myself as I've not worked with items and capabilities so far and transmitting energy wirelessly shouldn't be a challange after reading this. The basics are always the same, just how much more you put around those basic is different.
  9. As I've never used an profiler before, which one would you suggest to use? I don't think this would work as I've got 66 blocks and even with less than those blocks, it would just be a mess to read the data out. This would not work for my part as my system is build upon the idea that a machine gets every tick its energy, like in other energy mods itself. But I have a system in place which might work a bit like this and this is the process to build up the energy network as it doesn't run every tick, it just checks if it needs to run every tick and if it doesn't then it stops there, otherwhise the whole data will be updated, like when a new block is placed and thus the network changed. Yeah, that clear, but it shouldn't hit the limit with only 66 blocks.
  10. And here we've got a few problems: How to send the data to the client in a way the performance doesn't drop when it's a lot of data? How should the client or the server know if the data is different? How should I stop the client from using the data that already comes with the mod instead of using the new server data? Where to save the data on the client side? I mean the data is server specific like a resource pack can be server specific.
  11. Hi, I've got a problem with the code for my energy network. As soon as I build the system to be larger than a some really small value my FPS drops significantly from over 100 to 15-24fps. The size of the network I tested it currently was 11x6. Layer 1: 11x6 solar panels Layer 2: 11x6 transfer pipes Layer 3: 11x6 cables Layer 4: 1x1 transfer pipe Layer 5: 1x1 machine I don't know what exactly causes the problem, but it's not the machine block, as the energy doesn't even reach this block. And from my 66 solar panels, the energy storage of 56 of them is full while the energy storage of the last 10 is empty and stays empty. public class TileEntityPipeTransferEnergy extends TileEntityEnergy { private boolean flag = false; private HashMap<BlockPos, EnumFacing> connected = new HashMap<>(); // without pre-calculated weight public boolean shouldRecalculate = false; public TileEntityPipeTransferEnergy() { super(10, 10); this.container.setTransferMode(EnergyTransfer.PRODUCER); } @Override public void update() { this.flag = false; if(this.shouldRecalculate || this.connected.isEmpty()) { this.shouldRecalculate = false; this.findTransferPipes(); this.flag = true; } this.connected.forEach((pos, side) -> { final TileEntity tile = this.getWorld().getTileEntity(pos); if(tile == null) return; IEnergyStorage storage = tile.getCapability(CapabilityEnergy.ENERGY, side); if(storage == null) storage = tile.getCapability(CapabilityEnergy.ENERGY, null); if(storage != null) { storage.receiveEnergy(this.container.extractEnergy((int)(10 / this.connected.size()), false), false); this.flag = true; // flag has to be a class member because of inner classes } }); if(this.flag) this.markDirty(); } private void findTransferPipes() { if(this.connected.size() > 0) this.connected.clear(); // we want to store the facing and the position Queue<Pair<BlockPos, EnumFacing>> toSearch = new ArrayDeque<>(); HashSet<BlockPos> scanned = new HashSet<BlockPos>(); scanned.add(this.getPos()); if(toSearch.isEmpty() || toSearch.peek() == null) this.getBlocksToScan(toSearch, scanned, this.getPos()); // temp object because we poll stuff out of the list Pair<BlockPos, EnumFacing> pair = null; BlockPos current = null; EnumFacing face = null; while(toSearch.peek() != null) { pair = toSearch.poll(); current = pair.getLeft(); face = pair.getRight(); scanned.add(current); if(this.getWorld().getTileEntity(current) instanceof TileEntityPipeEnergy) // check cable connection this.getBlocksToScan(toSearch, scanned, current); else if(this.getWorld().getTileEntity(current) instanceof TileEntityPipeTransferEnergy && !this.getPos().equals(current) && !this.connected.containsKey(current)) this.connected.put(current, face); // found end of line } } private void getBlocksToScan(Queue<Pair<BlockPos, EnumFacing>> toSearch, HashSet<BlockPos> scanned, BlockPos pos) { // EnumSet.allOf(EnumFacing.class) does not include the null, so machines which don't require a specific // site will be ignored for(EnumFacing face : EnumFacing.VALUES) { // same as pos.north(), just for all directions BlockPos offset = pos.offset(face); if(!scanned.contains(offset)) // create a new pair and add it to the list // a pair is just some class which holds two fields toSearch.add(Pair.of(offset, face.getOpposite())); } } @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); if(compound.hasKey("connection")) { NBTTagList list = compound.getTagList("connection", Constants.NBT.TAG_COMPOUND); for(int i = 0; i <= list.tagCount(); i++) { NBTTagCompound com = list.getCompoundTagAt(i); if(com.hasKey("posX") && com.hasKey("posY") && com.hasKey("posZ") && com.hasKey("facing")) { this.connected.put( new BlockPos( com.getInteger("posX"), com.getInteger("posY"), com.getInteger("posZ")), EnumFacing.byName(com.getString("facing"))); } } } } @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { NBTTagList list = new NBTTagList(); this.connected.forEach((pos, side) -> { NBTTagCompound com = new NBTTagCompound(); com.setInteger("posX", pos.getX()); com.setInteger("posY", pos.getY()); com.setInteger("posZ", pos.getZ()); com.setString("facing", side.getName()); list.appendTag(com); }); compound.setTag("connection", list); return super.writeToNBT(compound); } @Override public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { super.onDataPacket(net, pkt); this.readFromNBT(pkt.getNbtCompound()); } } The code of the cable: public class TileEntityPipeEnergy extends TileEntity { private HashSet<BlockPos> connected_machines = new HashSet<>(); public void searchNetwork() { if(this.connected_machines.size() > 0) this.connected_machines.clear(); ArrayDeque<BlockPos> toSearch = new ArrayDeque<>(); HashSet<BlockPos> scanned = new HashSet<>(); if(toSearch.isEmpty() || toSearch.peek() == null) this.getBlocksToScan(toSearch, scanned, this.getPos()); BlockPos current = null; while(toSearch.peek() != null) { current = toSearch.pop(); scanned.add(current); TileEntity tile = this.getWorld().getTileEntity(current); if(tile != null) { if(tile instanceof TileEntityPipeEnergy) this.getBlocksToScan(toSearch, scanned, current); else if(tile instanceof TileEntityPipeTransferEnergy) this.connected_machines.add(current); } } } private void getBlocksToScan(ArrayDeque<BlockPos> toSearch, HashSet<BlockPos> scanned, BlockPos pos) { for(EnumFacing face : EnumSet.allOf(EnumFacing.class)) { // same as pos.north(), just for all directions BlockPos offset = pos.offset(face); if(!scanned.contains(offset)) toSearch.add(offset); } } public void informNetwork() { this.connected_machines.forEach(pos -> { TileEntity tile = this.getWorld().getTileEntity(pos); // make sure the tile entity at 'pos' is really the one we think it is if(tile != null && tile instanceof TileEntityPipeTransferEnergy) { TileEntityPipeTransferEnergy transfer = (TileEntityPipeTransferEnergy) tile; transfer.shouldRecalculate = true; } }); } @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { NBTTagList list = new NBTTagList(); for(BlockPos pos : this.connected_machines) { NBTTagCompound com = new NBTTagCompound(); com.setInteger("posX", pos.getX()); com.setInteger("posY", pos.getY()); com.setInteger("posZ", pos.getZ()); list.appendTag(com); } compound.setTag("machines", list); return super.writeToNBT(compound); } @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); if(compound.hasKey("machines")) { NBTTagList list = compound.getTagList("machines", Constants.NBT.TAG_COMPOUND); for(int i = 0; i <= list.tagCount(); i++) { NBTTagCompound com = list.getCompoundTagAt(i); if(com.hasKey("posX") && com.hasKey("posY") && com.hasKey("posZ")) { this.connected_machines.add( new BlockPos( com.getInteger("posX"), com.getInteger("posY"), com.getInteger("posZ")) ); } } } } } The code of my solar panel: public class TileEntitySolarPanel extends TileEntityEnergy { [...] @Override public void update() { super.update(); [...] this.container.receiveEnergy(this.inputRate, false); if(this.world.getTileEntity(this.getPos().down()) != null) { int received = sendEnergy(this, this.world.getTileEntity(this.getPos().down()), EnumFacing.DOWN, 10); if(received > 0) flag = true; } if(flag) { this.getWorld().notifyBlockUpdate(this.getPos(), this.getWorld().getBlockState(this.getPos()), this.getWorld().getBlockState(this.getPos()), 3); this.markDirty(); } } public static int sendEnergy(@Nullable TileEntityEnergy from, @Nullable TileEntity sendTo, EnumFacing orientation, int transferAmount) { if(from == null || sendTo == null) return 0; EnumFacing side = orientation.getOpposite(); if(sendTo.hasCapability(CapabilityEnergy.ENERGY, side)) { // Forge Energy Support IEnergyStorage storage = sendTo.getCapability(CapabilityEnergy.ENERGY, side); if(storage != null && storage.canReceive() && from.container.canExtract()) return storage.receiveEnergy(from.container.extractEnergy(transferAmount, false), false); } return 0; } @Override public SPacketUpdateTileEntity getUpdatePacket() { return new SPacketUpdateTileEntity(this.getPos(), 3, this.getUpdateTag()); } @Override public NBTTagCompound getUpdateTag() { return this.writeToNBT(new NBTTagCompound()); } @Override public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { super.onDataPacket(net, pkt); this.handleUpdateTag(pkt.getNbtCompound()); } } The debug mode of eclipse also showed me the information that in TileEntityPipeTransferEnergy the shouldRecalculate value is set to false and the connected list also contains data. So it must have something to do with the energy transfer from one block to anther, thought I'm not sure what could cause the problem there. I just suspect that my solar panels are transfering the energy between themselves instead of putting it into the machine, but I don't see why this would cause a significantly fps drop. Also to note: for rendering I'm just using a default json file with a texture. So nothing really special about it. The RAM stays with about 1.5GB of 3GB available and the chunk updates are above 200. Thx in advance. Bektor EDIT: further note: I had no problems before having so many solar panels, so I think its a problem with the cable network
  12. This is related to writing mods as I want my mod to have this feature, as I want for balancing and thus stuff my mod to sync data between the server and the client so that when I have for example a config file or a json file or whatever file I might want to use, I can change on the server just this file and everyone will be able to play with the new balanced variables instead of the old ones and the old ones are only used on the client when the client is not conntected to my server.
  13. If I would guess, I would say that there is a problem finding OpenGL drivers which could be caused by out-of date drivers or something is wrong with the drivers. I would recommend uninstall the driver with something like DDU to make sure everything is removed uppon uninstallation and then install it again. Downgrading Java should definitly not solve the problem. Also since Mojang enforces Java 8 with Minecraft 1.12, you shouldn't be able to start Minecraft with Java 7/6 or lower.
  14. Hi, if it is possible using Forge to change values server side only, for example to allow a server owner to change how much energy a machine produces or consumes without the need of a update of the mod itself on the client side. Basically the server owner should be able to change specific values and the client uses the values from the server instead of it's own values. My problem there is: I don't know if this is possible with the current available systems in Forge/Minecraft. I don't know how to do it, except for that at some point the server has to send all the data to the client. Thx in advance. Bektor
  15. Hi, I am currently working on implementing a chunk loader to my mod, thought I've got little to none idea how to do this. How the chunk loader should work: if placed by player, create chunk loader for player as long as the limit per player wasn't reached otherwhise let the mod manage the chunk loader until the limit is reached (which should be equal to the limit of chunk loaders per player) if the limit is reached, send a message to the placer informing him about the reached limit This is the code I've got so far: public class TileEntityChunkLoader extends TileEntityEnergy { private final String UUID_TAG = "UUID"; private final int consume; private boolean isActive = true; private ForgeChunkManager.Ticket ticket; private UUID ownerId = null; public TileEntityChunkLoader(int capacity, int maxTransfer) { super(capacity, maxTransfer, false); this.consume = maxTransfer; this.getEnergyManager().setTransferMode(EnergyTransfer.CONSUMER); } @Override public void update() { super.update(); if(!this.hasWorld() || this.getWorld().isRemote) return; this.isActive = EnergyUtils.consumeEnergy(this, this.consume); if(isActive) { startChunkLoading(); this.getWorld().notifyBlockUpdate(this.getPos(), this.getWorld().getBlockState(this.getPos()), this.getWorld().getBlockState(this.getPos()), 3); this.markDirty(); } } private void startChunkLoading() { if(this.ticket == null) { if(this.ownerId != null) this.ticket = ForgeChunkManager.requestPlayerTicket(Constants.MOD_ID, this.ownerId.toString(), this.getWorld(), Type.NORMAL); else this.ticket = ForgeChunkManager.requestTicket(Constants.MOD_ID, this.getWorld(), Type.NORMAL); } if(this.ticket == null) { JustAnotherEnergy.LOGGER.error("Ticket creation for the chunk loader at: [" + this.getPos().getX() + ", " + this.getPos().getY() + ", " + this.getPos().getZ() + "] failed!"); return; } } @Override public SPacketUpdateTileEntity getUpdatePacket() { return new SPacketUpdateTileEntity(this.getPos(), 3, this.getUpdateTag()); } @Override public NBTTagCompound getUpdateTag() { return this.writeToNBT(new NBTTagCompound()); } @Override public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { super.onDataPacket(net, pkt); this.handleUpdateTag(pkt.getNbtCompound()); } @Override public void readFromNBT(NBTTagCompound compound) { this.ownerId = compound.getUniqueId(this.UUID_TAG); super.readFromNBT(compound); } @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { compound.setUniqueId(this.UUID_TAG, this.ownerId); return super.writeToNBT(compound); } public class BlockChunkLoader extends Block implements ITileEntityProvider { public static PropertyEnum<ChunkLoaderTypes> META_PROPERTY = PropertyEnum.create("loader", ChunkLoaderTypes.class); public BlockChunkLoader() { super(Material.IRON); this.setDefaultState(this.blockState.getBaseState().withProperty(META_PROPERTY, ChunkLoaderTypes.LOAD_01)); } @Override public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack) { if(worldIn.isRemote) return; TileEntity tile = worldIn.getTileEntity(pos); if(tile instanceof TileEntityChunkLoader) { TileEntityChunkLoader tileCL = (TileEntityChunkLoader) tile; if(placer instanceof EntityPlayer) { EntityPlayer player = (EntityPlayer) placer; tileCL.setOwnerId(player.getGameProfile().getId()); } } } @Override public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { TileEntity tile = worldIn.getTileEntity(pos); if(tile instanceof TileEntityChunkLoader) { TileEntityChunkLoader tileCL = (TileEntityChunkLoader) tile; } super.breakBlock(worldIn, pos, state); } @Override public TileEntity createNewTileEntity(World worldIn, int meta) { switch(meta) { case 0: return new TileEntityChunkLoader(500, 100); case 1: return new TileEntityChunkLoader(4500, 900); case 2: return new TileEntityChunkLoader(125000, 25000); default: return new TileEntityChunkLoader(500, 100); } } @Override public void getSubBlocks(Item itemIn, CreativeTabs tab, List<ItemStack> list) { for(final ChunkLoaderTypes type : ChunkLoaderTypes.values()) list.add(new ItemStack(this, 1, type.getID())); } @Override public int damageDropped(IBlockState state) { return this.getMetaFromState(state); } @Override protected BlockStateContainer createBlockState() { return new BlockStateContainer(this, META_PROPERTY); } @Override public int getMetaFromState(IBlockState state) { return state.getValue(META_PROPERTY).getID(); } @Override public IBlockState getStateFromMeta(int meta) { return this.getDefaultState().withProperty(META_PROPERTY, ChunkLoaderTypes.byMetadata(meta)); } } As can be seen in the block class, the amount of energy consumption is higher when more chunks should be loaded (radius around the chunk loader including it's chunk, can also be just the chunk of the chunk loader) My problem now is that I am stuck at achieving this. I am also wondering what the difference between an Entity and a Normal ChunkLoader as seen in requestTicket is. Thx in advance. Bektor
  16. Fixed with changing the first 51 parameter from my method to 0. The ScaledResolution thing also solved problems with disappering textures when changing the screen size, which I didn't even noticed before. I suppose it was an issue with missing ScaledResolution and me having the reading direction for OpenGL texture coordinates wrong in my head.
  17. Ok, fixed it with changing the first 51 parameter from my method to 0. Hm, I'm wondering what this invoke method is.
  18. Always forget this one thing, but it didn't solve the problem. The texture is still gone: glTexCoord2f(textureX * (1.f / 256.f), textureY * (1.f / 256.f)); glVertex3i(0, 0, 0); glTexCoord2f(textureX * (1.f / 256.f), (textureY + height) * (1.f / 256.f)); glVertex3i(0, height + 400, 0); glTexCoord2f((textureX + width) * (1.f / 256.f), (textureY + height) * (1.f / 256.f)); glVertex3i(width + 800, height + 400, 0); glTexCoord2f((textureX + width) * (1.f / 256.f), textureY * (1.f / 256.f)); glVertex3i(width + 800, 0, 0); Hope I didn't forgot a small thing again, thought somehow I hope I did as it would solve the problem faster. ^^ Assembly makes fun. You can even enforce a PC configuration with this as it won't run anywhere else. But why using Assembly, binary with its 01010101 is even better. I don't know much about Mesa drivers, except that they got a somewhat stable OpenGL 4.5 support, but why not using official drivers? And I don't think Minecraft uses OpenGL 3.3, the last version I know for sure they are using is OpenGL 2.1.
  19. Changing my code to multiply the texture values with 1/256 just let's the complete image disappear. glTexCoord2f(textureX * (1/256), textureY * (1/256)); glVertex3i(0, 0, 0); glTexCoord2f(textureX * (1/256), (textureY + height) * (1/256)); glVertex3i(0, height + 400, 0); glTexCoord2f((textureX + width) * (1/256), (textureY + height) * (1/256)); glVertex3i(width + 800, height + 400, 0); glTexCoord2f((textureX + width) * (1/256), textureY * (1/256)); glVertex3i(width + 800, 0, 0); Hm, why the hell creates Mojang wrappers around GL 3.0+ rendering instead of using it direclty. I mean, I don't know any graphics card today which doesn't support OpenGL 3.0+, even NVIDIAs GTX 400 series supports OpenGL 4.6 with the newest beta drivers and 4.5 with the newest stable drivers.
  20. Well, I want to place it in the middle of the screen. Well, I used them, thought it didn't went that good. Couldn't see the image anymore, so I started fixing the image first to get it properly drawn as one big image is easier to see then thousands of small images. I don't see any reason why BufferBuilder/VertexBuffer is the prefered way, especially when I do not know how it is connected to the hole rendering system and how those two classes work internally. Hm, now I am wondering, where does MC the conversion? I mean, when calling drawTexturedModalRect I don't think I ever passed the width of the complete image to draw, only the position and width and height of the part of the image to be drawn nor is the texture passed.
  21. RenderGameOverlayEvent.Post calls a custom method which would then execute the code for specific blocks. I'm binding the texture directly above the first line of code I posted. ^^
  22. Hi, I've got a little problem with my OpenGL code while drawing a rectangular texture: thousands of little textures will be drawn instead of one texture the texture to display is part of a larger texture, but the wrong part of this huge "spritesheet" is drawn those thousands of little textures are drawn on the wrong place of the screen `guiStartX` and `guiStartY`: the x and y positions where the GUI should start `textureX` and `textureY`: the position in the "spritesheet" where the texture can be found `width` and `height`: the width and height of the texture to draw mc.getTextureManager().bindTexture(UI_PROGRESS_TEXTURE); int guiStartX = (mc.displayWidth - 16) / 2; int guiStartY = (mc.displayHeight - 51) / 2; renderTexturedRect(guiStartX, guiStartY, 176, 51, 16, 51); renderTexturedRect(int x, int y, int textureX, int textureY, int width, int height) { glBegin(GL_QUADS); glTexCoord2f(textureX, textureY); glVertex3i(0, 0, 0); glTexCoord2f(textureX, textureY + height); glVertex3i(0, height + 400, 0); glTexCoord2f(textureX + width, textureY + height); glVertex3i(width + 800, height + 400, 0); glTexCoord2f(textureX + width, textureY); glVertex3i(width + 800, 0, 0); glEnd(); One may ask, why not using drawTexturedModalRect from Minecraft itself. The Reason for this is that it is not available in the place where I am drawing. And why am I using OpenGL directly instead of for example looking into how drawTexturedModalRect renders a rectangle and doing it the same way?: The answer to this is that I am rather using OpenGL directly instead of using undocumented code where I do not even know what it is doing and how the stuff is getting onto the screen with using this (like where and which OpenGL calls are being called etc.) Note: I am not familiar with OpenGL 2.1 nor with LWJGL 2 as I've only worked with OpenGL 4.5 (in C++) and it's shaders so far (and very little with LWJGL 3). Thx in advance. Bektor
  23. Ok, I found out that my CapabilityProvider has to implement INBTSerializable and has to call my write and read NBT methods from my NBTTag.
×
×
  • Create New...

Important Information

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