Warung Bebas

Jumat, 20 September 2013

The Minecraft main game loop

Minecraft uses two main game loops, one for the client and one for the server.
The client loop is primarily responsible for reading input from the player and for rendering the screen.
The server loop is responsible for maintaining the master copy of the world - updating the blocks and entities based on packets received from the client, and sending updated information to all the clients. 
Communication between the server and the clients is done using Packets.  Some information here, more to follow when I figure it out myself.

Client Game Loop

The key concepts for the Client Game Loop are:
  • The activities in the game loop are broadly grouped into (1) clock-based (Ticks) and (2) variable-timing (mostly - display rendering).  
  • The game loop calls the clock-based update code (.runTick) twenty times per second.  If the loop gets behind (for example due to slow rendering or other programs), it will repeatedly call .runTick until it catches up to real time.
  • In contrast, the display rendering is not time-critical.  Rendering is performed only when the Ticks are up-to-date.  If the game loop slows down, the framerate will be reduced but the Ticks will remain in synchronisation.
  • Actions which affect the world / entities are sent to the server for processing.
  • The state of client objects (blocks, entities, etc) is updated in response to packets received from the server.
  •  It can be very useful to insert breakpoints at key locations in .runTick(), in order to diagnose problems with player actions or entity AI.
  • Likewise, troubleshooting many rendering problems can be achieved by putting breakpoints in the appropriate parts of EntityRenderer.renderWorld.

Server Game Loop

Unlike the client loop, the server loop is essentially all clock-based (Ticks).  Key concepts:
  • The server is responsible for performing Block Ticks (both scheduled and random) and Entity Ticks (eg movement, AI, etc).
  • The server receives packets from the clients whenever the client performs an action which might affect the world or other entities.  It processes the packet to updates the world and entity states as appropriate, then sends the updated information to all relevant clients.
  • Sometimes the same code runs independently on both the client and the server (for example - blocklight and skylight calculation).  This reduces the amount of information that needs to be sent between client and server - there's no need to send information that can be locally calculated, so long as the client and server remain synchronised.











Rabu, 11 September 2013

Custom Item rendering using IItemRenderer


If you want your item to have non-vanilla rendering, your best best is probably to make use of the Forge IItemRenderer interface.  The same method in this interface is called whenever your item is rendered, regardless of whether the view is Inventory, Equipped (First person or Third person), or Dropped ("ENTITY").  The diagram below shows the various entry points.  The key concepts are:
  1. Write your rendering class to implement IItemRenderer.  Register it with MinecraftForgeClient.registerItemRenderer().
  2. The same method (IItemRenderer.renderItem) is called for all views, with one of the five ItemRenderTypes (INVENTORY, ENTITY, etc) passed in as a parameter.
  3. Your render code in renderItem() should look at the rendertype parameter to decide which view it needs to render.
  4. Your code should override .handleRenderType to return true for each of the rendering views it supports.
  5. ForgeHooksClient can apply a number of different transformations to the view before passing control to your .renderItem code.  These are called RenderHelpers.  Before calling .renderItem, MinecraftForgeClient queries IItemRenderer.shouldUseRenderHelper(HELPER) to see whether it should apply that helper or not.  For further details see below.

Diagram showing how the vanilla code interfaces with IItemRenderer to render the various different views of an Item.

RenderHelpers

The diagrams below show how the four different render types (INVENTORY, EQUIPPED_FIRST_PERSON,  EQUIPPED, and ENTITY) are affected by the various RenderHelpers. Unfortunately, the coordinate range that the caller expects you to render over is not consistent for the different views. In most cases a transformation using GL11.glTranslatef() and GL11.glScalef() will be the easiest way to compensate for this.  If you're finding it all a bit confusing, looking at the sample code may help.
Diagram identifying the faces of the test cube used for the examples below.  (In the pictures below, each face also has a unique colour.)  





Rendering options for renderItem(INVENTORY).  

Rendering Options for renderItem(EQUIPPED_FIRST_PERSON).

Rendering options for renderItem(EQUIPPED).  Also depends on whether Item.isFull3D() is overridden to return true.

Rendering options for renderItem(ENTITY).

Some miscellaneous notes

If your Item's custom renderer uses an icon from the block texture map, make sure that Item.getSpriteNumber() returns 0, otherwise the tessellator will render using the item texture map, i.e. the wrong icons will be used.

In order to get the lighting right for your custom render, you will need to use tessellator.setNormal to set the normal before you draw each face.  The normal affects the brightness of the face; if the normal points directly towards the scene's light source, the face will be bright.  As the normal moves away from the scene's light source, the face brightness will decrease.
  • If you can't be bothered to light each face differently, use
    tessellator.setNormal(0.0F, 1.0F, 0.0F);
     This will make all faces bright (the normal faces up).
  • For cubes, the normal points in the direction of the axis, eg east face is [1.0F, 0.0F, 0.0F],  bottom face is [0.0F, -1.0F, 0.0F], etc
  • For arbitrary faces, calculate the normalised cross product of two adjacent edges of each face.  for example, for a south-east face, i.e. the normal is [0.707, 0.0, 0.707].   This tool can be useful for these calculations, you will need to adjust the sign of the normal to make sure it is pointing in the correct direction. 
Diagram showing how the Normal relates to the face.
For some reason, rendering in Third Person Equipped turns off back-face culling.  i.e. you can see faces from both sides.  If this makes your rendering look strange, you can turn it back on using GL11.glEnable(GL11.GL_CULL_FACE);


Senin, 09 September 2013

Sample code for rendering items

Although I said I wasn't going to provide any code snippets or sample code, the Item rendering turned out to be so full of "special cases" I've changed my mind.

I have posted the test code I used onto GitHub.  It is located here.

The picture below shows the module structure, based around
  1. ItemSmileyFace, which is a very simple Item that uses iconRegister.registerIcon() and nothing more.
  2. BlockNumberedFaces1, a simple cube.  When placed in the world as a block it uses vanilla code, when visible as an item it uses IItemRenderer to do custom rendering as a 3D cube.
  3. ItemNumberedFaces2, the same cube as BlockNumberedFaces1 except it is an Item only, and it is rendered in 2D, the same as most vanilla items.
  4. ItemNumberedFaces3, the same cube as BlockNumberedFaces1, except it is an Item only.  Rendered in 3D using IItemRenderer.
  5. BlockPyramid, (Block and Item) - showing how to render custom shapes using ISimpleBlockRenderingHandler.
  6. ItemLampshade, an Item showing some unusual custom rendering using IItemRenderer.
Which one should you use?
  1. If you want your item to look similar to the vanilla minecraft items, use ItemSmileyFace
  2. If your item can also be placed in the world as a block, and you want the item to look similar to the block, use BlockPyramid or BlockNumberedFaces1.
  3. If you want your item to render in 2D similar to the vanilla minecraft items, perhaps with a bit of extra fancy stuff, look at ItemNumberedFaces2
  4. If your item should render as a 3D object, look at ItemNumberedFaces3 or ItemLampshade.


"Inventory" render of the test Items: from left to right: Pyramid, Lampshade, SmileyFace, NumberedFaces1, NumberedFaces2, NumberedFaces3
"Dropped" render of the test items.  ("Fancy Graphics" option on).
"Dropped" render of the test items in picture frames.


"Dropped" render of the two test Items which are also Blocks.

"First Person Equipped" render of the test items.







"Third person equipped" render of the test items.




 

My Blog Copyright © 2012 Fast Loading -- Powered by Blogger