Warung Bebas

Kamis, 24 Oktober 2013

Server-side Class Linkage Map

The diagram below shows the cross-references between the most important Server-side vanilla classes. For example:

EntityPlayerMP.playerNetServerHandler contains a NetServerHandler
Entity.worldObj refers to WorldServer
WorldServer.playerEntities contains a collection of EntityPlayers
 The map can be used to find a way to access the particular Class you need, starting with the Class(es) your code has been provided with.
NB - there are several ways of getting to EntityPlayerMP depending on which ones you want:
  1. To get all players on the server, use ServerConfigurationManager.playerEntityList()
  2. To get all players within range of a particular chunk, start from PlayerManager()
  3. For the player corresponding to a particular NetServerHandler, use .playerEntity
  4. For all players within range of a particular Entity, start from EntityTracker.
  5. For all players in a particular dimension, use worldServer.playerEntities, where you get worldServer using MinecraftServer.getServer().worldServerForDimension or DimensionManager.getWorld()
 MinecraftServer is designed as a Singleton (there is only ever one instance of the Class). It can be accessed by MinecraftServer.getServer().
Server-side Class Linkage Map for reference between the major vanilla Classes. Fields which are public are designated by solid arrows; private fields are in curly brackets and have dotted arrows. MinecraftServer is accessible using .getServer()

Sabtu, 19 Oktober 2013

Client-side Class linkage map

The diagram below shows the cross-references between the various Client-side vanilla classes.  For example:
  • Minecraft.thePlayer contains an EntityClientPlayerMP.
  • Entity.worldObj refers to WorldClient
  • WorldClient.loadedTileEntityList contains a collection of TileEntity
The map can be used to find a way to access the particular Class you need, starting with the Classe(s) your code has been provided with.

Minecraft and RenderManager are designed as Singletons (there is only ever one instance of the Class).  They can be accessed by
  • Minecraft.getMinecraft()
  • RenderManager.instance
Minecraft holds an IntegratedServer but this is a server side object and shouldn't be accessed from the client side.  If you do, your code might work when the server and client are on the same computer, however it will almost certainly break when  the client is on a different computer.

Client-side Class Linkage Map for reference between the major vanilla Classes.  Fields which are public are designated by solid arrows; private fields are in curly brackets and have dotted arrows.  Minecraft and RenderManager are accessible using .getMinecraft() and .instance respectively.  IntegratedServer is stored in Minecraft but is actually Server side - i.e. must not be accessed from client side.






Jumat, 18 Oktober 2013

User Input


Minecraft retrieves input from the user using two library Classes - Mouse and Keyboard.

Mouse
This class provides a range of information about mousebutton clicks and cursor movement.  Minecraft vanilla uses a variety of the methods depending on whether the user is in a GUI (eg inventory screen) or is walking around in the world.

Keyboard
Minecraft uses the Keyboard directly for keypresses which can't be re-bound by the user.  For example the function keys, the hotbar slot selection keys 0 .. 8, etc.
  • .isKeyDown for determining whether a key is pressed
  • getEventKey for responding to key pushes (i.e. change of state from "not pressed" to "pressed").
Keyboard contains a table of all the key codes at the front.

KeyBinding (eg GameSettings.keyBindAttack)
Minecraft uses KeyBindings to assign keypresses or mouse clicks to a particular action, for example keyBindAttack can be changed from Left Mouse Button to "m".  (Minecraft uses negative keycodes for mouse buttons: -100 = left, -99 = right, -98 = middle)

KeyBinding provides:
  • .pressed is true if this key is being held down
  • .isPressed() which returns true if the key has been pressed.  It should really be called retrieveKeyPress() or similar:  KeyBinding counts the number of times that user pushes a key, i.e. pressing and holding for 2 seconds still only counts as a single push.  Each time isPressed is called, it decreases this count by one.  (A better name for  .pressTime would be .pressCount, similarly.onTick() would better be called incrementPressCount() ).
 Forge provides a similar functionality using KeyHandler.

The user input from Mouse and Keyboard is processed in three different places:
  1. Minecraft.runTick() handles GUI input, non-bindable keys (eg function keys), and a number of bindable actions such as drop, attack (left mouse button), use item (right mouse button).
  2. EntityClientPlayerSP.onLivingUpdate handles movement input (left, right, forward, back, jump, sneak, etc).
  3. EntityRenderer.updateCameraAndRender() handles movement of the camera (moving the mouse when walking around in-world) using mouseHelper.mouseXYChange();
The diagrams below show these in more detail.

The vanilla code imposes a number of constraints on the way the user input is interpreted, especially the left and right mouse button clicks - for example what happens when the clicks are held down.  It is possible to "intercept" some of the bound keys to gain more control over them, for example see here.  Forge also provides a cancelable event to intercept mouse actions (especially useful for the scroll wheel) - MouseEvent.

User movement is processed in .onLivingUpdate and sent to the server using Packets 10-13, 19, 27

Minecraft.runTick() is responsible for handling most of the user input.

Minecraft.clickMouse handles right- and left- mouse button clicks (the initial click only).  Ongoing effects while holding the left button down are handled by Minecraft.runTick().  Holding the right button down for a non-useable item (eg items which can't be eaten or drunk) causes repeated calls to clickMouse.






Selasa, 08 Oktober 2013

The most important Minecraft Classes... continued

The Minecraft world is made up of a relatively few different types of objects.  The major ones are:

Block

These obviously don't require much explanation.  There many different types of Blocks, all derived from the Block base class.  The Block class and derived classes do not store unique information about every location in the world (it is a "Singleton" and uses the "Flyweight" design pattern), they only store information related to the Block type.  The Block classes hence consist mostly of methods to determine the behaviour of the block and how it is drawn on the screen .  Blocks are laid out in a 3 dimensional grid, every location in the grid has a corresponding BlockID and metadata which specifies the type of Block stored at that location.  This information is stored in an array inside ExtendedBlockStorage objects.  For more information see here.  Blocks are drawn (rendered) using RenderBlocks - for more information see here.

TileEntity

There are some special blocks which need to store more information than a standard Block - for example the BlockSign or BlockChest.  A TileEntity is used in this case.  TileEntities are treated differently from ordinary Blocks.  Each TileEntity corresponds to a single Block at a particular [x,y,z] location.  Minecraft maintains a list of TileEntity objects, each of which stores unique information such as the text on a sign or the contents of a chest.
When rendering, the Minecraft may either render the underlying Block, the TileEntity (using TileEntitySpecialRenderer), or both.  The major difference is that the TileEntity is rendered fresh every frame, whereas the Block uses a 'cached render'  that is only refreshed when the block changes.  This means that if you want your Block to be animated, you need to either use an animated texture for your Block, or use a TileEntity.

Item

Items are things that the player can carry, such as Pickaxe, Sword, Gemstone, Wood.  For blocks which can be mined and carried (eg stone block), this is represented by a Block when placed in the world, but is an item when carried by the player.   Similar to Blocks, each Item class is a Singleton and only stores information about the Item type.    There are many types of Item, all derived from the Item base class.  They are rendered in a number of different ways as described here.  

ItemStack is the class used when an Item is actually "created" - in addition to the Item type, it also stores the item count (eg a stack of 46 planks), "damage" (eg pickaxe "wear-and-tear" indicator), and several other pieces of information.  ItemStacks are stored in "Slots" in the inventory, in the hotbar, in Containers (eg Chest, Furnace, etc). Note: an item which is in the world (eg sitting on the ground after the player has thrown it) is represented by the corresponding EntityItem, not an ItemStack.

A bit more information about Items and ItemStacks here.

Entity

An Entity is used to represent anything that can move around - such as cows, snowballs, or minecarts.  All entities have a fractional position (unlike Blocks and TileEntities which have integer [x,y,z] only) and most have velocity information.  They receive a call to onUpdate() every "Tick" (1/20 of a second) to update their state using appropriate logic - for example updating the position for a thrown object, attacking the player for a hostile mob.

There is a rather complicated inheritance hierarchy shown below, which can be used to group Entities with similar behaviour together.  Entities are rendered using EntityRenderer derived classes, with each Entity mapped to the appropriate Renderer using RenderManager.

The EntityPlayer derived classes are special cases because they deal with players (i.e. human users) and are updated quite differently to other entities.












Senin, 07 Oktober 2013

The most important Minecraft Classes

The Minecraft code is based around a handful of Classes with different responsibilities.  Most of them are split into two parts - the Client side and the Server side; communication between the two is by Packets.  When writing mods it is usually vitally important to know which "side" your code is running on.  If you try to run client code on the server side (or vica versa) it will cause crashes or loss of client-server synchronisation (eg items which disappear).

The diagram below shows the most significant Classes responsible for storing, maintaining and synchronising the game state.

Other significant Classes are
  • Block and its derived classes
  • Item and its derived classes
  • Entity and its derived classes
  • Container and its derived classes
  • TileEntity and its derived classes
For more information, see here.  The game loops are in Minecraft and MinecraftServer, described in more detail here.




The Client <--> Server division


The Minecraft code can be divided into two �sides� � Client and Server.
  • The Server side 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.
  • The Client side is primarily responsible for reading input from the player and for rendering the screen.
There is one server, and a number of clients which connect to it. Even in single player mode, the server and client code are running simultaneously (in separate threads).

Some parts of the code are used by both Client and Server code, for example Block methods.  If you are writing code which might be called by either Client or Server, how can you tell which side has called the code?
First preference: if your method has been passed a World object, or the Class you are extending has a World field (typically called worldObj):
  • if World.isRemote is true, this is Client side
  • if World.isRemote is false, this is Server side.
If your code has been passed a NetHandler:
  • NetHandler.isServerHandler() returns true if Server side.
As a last resort:
  • FMLcommonHandler.instance().getEffectiveSide() returns Side.SERVER or Side.CLIENT.

Client and Server run in parallel

Communication between the Client and Server sides takes place through Packets, which are sent back and forth using NetClientHandler and NetServerHandler.  The basic steps are shown in the diagram below.  There are a large number of different packets used:
* Packets from Server to Client

Some guidelines on the Client<-->Server communication here.



Communication from Client to Server

Communication from Server to Client

If you need to send packets in your mod code, Forge has thoughtfully provided PacketDispatcher to send packets to the client or the server without having to retrieve a NetServerHandler or NetClientHandler.
          .sendPacketToServer()
          .sendPacketToPlayer()
          .sendPacketToAllAround()
          .sendPacketToAllInDimension()
          .sendPacketToAllPlayers()

If the existing packets don�t meet your needs, you can create a custom packet Packet250CustomPayload.  More details here.

In many cases, you won�t need to create custom packets to keep your client and server code synchronised.  The vanilla code and Forge code do this in a number of ways already:
  • Creation, Removal, Movement, health, actions etc for Entities.  This is accomplished for new Entities by Forge packet EntitySpawnPacket.  You can define a custom handler for this using EntityRegistration.setCustomSpawning().
  • Removal or placement of Blocks
  • Adding DataWatcher variables to your Entity (see here)
  • Containers (Inventory, furnace, etc)

Server Packets: Changes to Entities

The following Packets are used to inform the client about changes to Entities.  These are usually generated by
  • EntityTrackerEntry (keeps track of entities near to each player)
  • EntityPlayerMP (keeps track of player status, position, health, inventory, etc
    The Client generally handles these packets by calling methods in
    • EntityClientPlayerMP(for changes to the user / controlling player)
    • WorldClient (addition or removal of Entities)
    • Entity (for status changes to entities in general, eg health, position, etc)


    Typical server origin
    NetClientHandler (Client processing)
    Called by Client during processing
    Packet5PlayerInventory
    Change the equipped item or armour of an entity (player, other players, mob)
    EntityLivingBase.onUpdate()
    EntityTrackerEntry
    .handlePlayerInventory()

    Entity.setCurrentItemOrArmor()
    Packet6SpawnPosition
    Tells the client where the player will respawn next.
    ServerConfigurationManager
    .handleSpawnPosition()

    EntityClientPlayerMP.setSpawnChunk()
    WorldInfo.setSpawnPosition()
    Packet8UpdateHealth
    Sends updated health and food status to the client.
    EntityPlayerMP.onUpdateEntity()
    .handleUpdateHealth()

    EntityClientPlayerMP
    Packet9Respawn
    Tell the client to respawn the player at the given location.
    ServerConfigurationManager
    .transferPlayerToDimension()
    .respawnPlayer()

    .handleRespawn()
    Change dimension, create new WorldClient, change game type
    Minecraft.setDimensionAndSpawnPlayer
    PlayerControllerMP.setGameType
    Packet10Flying,
    Packet11PlayerPosition,
    Packet12PlayerLook,
    Packet13PlayerLookMove


    NetServerHandler
    .setPlayerLocation()

    Only Packet13 is ever sent from server to client.  It is sent once per second, to keep client and server synchronised.  Used as a signal to the client that the world reload after respawning has completed.
    .handleFlying()
    Update position and/or look to the new values.  Then send the same Packet with updated values (in particular the foot and eye y-values) back to the server.  Get rid of respawn screen.
    EntityClientPlayerMP
    .setPositionAndRotation()
    Packet16BlockItemSwitch
    Changes the selected hotbar slot (0..8)
    ServerConfigurationManager
    handleBlockItemSwitch()
    Change inventory.currentitem to the nominated slot.

    Packet17Sleep
    Put a player to sleep
    EntityPlayerMP.sleepInBedAt
    handleSleep()
    Put a player to sleep at the specified location, if possible.
    Entityplayer.sleepInBedAt
    Packet18Animation
    Entity performs an action
    1 = swing item
    2 = gets hurt (not used)
    3 = wake up
    6 = critical hit
    7 = magic critical hit
    EntityPlayerMP
    EntityLivingBase
    handleAnimation()
    Starts the appropriate animation (entity) or EffectRenderer
    EffectRenderer.addEffect()
    Entity
    EntityLivingBase
    EntityPlayer
    <![if !supportLineBreakNewLine]>
    <![endif]>
    Packet20NamedEntitySpawn
    Spawn an Other Player on the client
    EntityTrackerEntry
    handleNamedEntitySpawn()
    Spawn the other player on the client, set its position, look, current item, and other metadata (Datawatcher objects)
    EntityOtherPlayerMP
    WorldClient.addEntityToWorld()
    Packet22Collect
    Collect an item from the ground
    EntityLivingBase
    .onItemPickup()

    handleCollect()
    Removes the EntityItem, plays a sound effect, renders the pickup effect.  Does not actually give an item to the entity.
    WorldClient()
    EffectRenderer()
    Packet23VehicleSpawn
    Spawns a non-living Entity (boat, fireball, firework, etc)
    EntityTrackerEntry
    .getPacketForThisEntity()
    FMLNetworkHandler
    .getEntitySpawningPacket()
    handleVehicleSpawn()
    Create the Entity, set position, pitch & yaw.  If thrown, set velocity.
    WorldClient.addEntityToWorld()
    Packet24MobSpawn
    Spawn a mob
    EntityTrackerEntry
    .getPacketForThisEntity()
    FMLNetworkHandler.
    getEntitySpawningPacket()
    handleMobSpawn()
    Create the Entity, set position, pitch & yaws, and other metadata (Datawatcher objects).
    WorldClient.addEntityToWorld()
    Packet25EntityPainting
    EntityTrackerEntry
    .getPacketForThisEntity()
    handleEntityPainting()
    Create a painting
    WorldClient.addEntityToWorld()
    Packet26EntityXPOrb
    EntityTrackerEntry
    .getPacketForThisEntity()
    handleEntityExpOrb()
    Create an XP orb.
    WorldClient.addEntityToWorld()
    Packet28EntityVelocity
    EntityTrackerEntry
    .sendLocationToAllClients()
    handleEntityVelocity()
    Change the Entity�s velocity
    Entity.setVelocity()
    Packet29DestroyEntity
    Remove one or more entities from client world, i.e. client doesn�t need to track them anymore.
    EntityPlayerMP.onUpdate()
    handleDestroyEntity()

    WorldClient.removeEntityFromWorld
    Packet30Entity,
    Packet31RelEntityMove,
    Packet32EntityLook,
    Packet33RelEntityMoveLook
    Tell the client the relative movement and/or yaw+pitch of the entity.

    EntityTrackerEntry
    .sendLocationToAllClients()

    .handleEntity()
    Update position (based on relative movement) and/or yaw/pitch.
    Entity.setPositionAndRotation2()
    Packet34EntityTeleport
    Move the Entity to the specified position, yaw+pitch
    EntityTrackerEntry
    .sendLocationToAllClients()
    Performs teleport instead of relative movement: once every 20 seconds, if riding, or if movement is too big.
    .handleEntityTeleport()
    Set entity position to the specified position, yaw+pitch
    Entity.setPositionAndRotation2()
    Packet35EntityHeadRotation
    EntityTrackerEntry
    .sendLocationToAllClients()
    .handleEntityHeadRotation()
    Sets the entity�s head to the given yaw
    Entity. setRotationYawHead
    Packet38EntityStatus
    2 = hurt, 3 = dead
    EntityPlayerMP.onItemUseFinish()
    WorldServer.setEntityState()
    .handleEntityStatus()
    calls Entity.handleHealthUpdate(), which plays appropriate sound and calls appropriate client method
    Entity
    .attackEntityFrom()
    .onDeath()
    Packet39AttachEntity
    Sends mounting / leashing info for horse, boat, etc.
    EntityPlayerMP.mountEntity
    EntityTrackerEntry
    EntityLiving
    .handleAttachEntity()
    mounts / leashes or unmounts / unleashes entity � horse, boat, cart, etc
    EntityLiving
    EntityBoat
    Packet40EntityMetadata
    Copy all changed metadata (WatchedObjects) to client (and optionally, clear the �changed� flag .watched for each)
    EntityTrackerEntry
    .handleEntityMetadata()
    Transmit all metadata for the entity that has been changed (�.watched� flag is true).  The �.watched� flag for each is optionally cleared when the packet is created.
    Entity.DataWatcher
    .updateWatchedObjectsFromList
    Packet41EntityEffect
    Apply the potion effect to the entity
    EntityTrackerEntry
    EntityPlayerMP
    ServerConfigurationManager
    .handleEntityEffect()
    Apply the potion effect to the entity
    EntityLivingBase.addPotionEffect()
    Packet42RemoveEntityEffect
    Remove a potion effect from the entity
    EntityPlayerMP
    .handleRemoveEntityEffect()
    EntityLivingBase. removePotionEffectClient
    Packet43Experience
    Set player experience
    EntityPlayerMP
    ServerConfigurationManager
    .handleExperience()
    sets the client player experience & level
    EntityClientPlayerMP.setXPstats
    Packet44UpdateAttributes
    Send all Attributes for this entity to the client.
    EntityTrackerEntry
    .handleUpdateAttributes()
    set the attributes of the client entity
    EntityLivingBase.getAttributeMap() (the elements in the map are overwritten).
    Packet200Statistic
    Send statistics (achievement, distance walked, or similar)
    EntityPlayerMP
    .handleStatistic()
    EntityClientPlayerMP
    .incrementStat
    Packet201PlayerInfo
    Send network info about a player to client (name, connected?, ping)
    ServerConfigurationManager
    .handlePlayerInfo()
    NetClientHandler
    Packet202PlayerAbilities
    Inform the client of the player�s abilities (can fly, walk speed, etc)
    EntityPlayerMP
    ServerConfigurationManager
    .handlePlayerAbilities()
    NB - .allowEdit is ignored

    EntityClientPlayerMP

    There are also two FMLpackets used for custom entities:

    Typical Server origin
    FMLClientHandler (Client processing)
    Called by Client during processing
    EntitySpawnPacket
    FMLNetworkHandler
    .getEntitySpawningPacket
    (from EntityTrackerEntry)
    EntitySpawnPacket.execute()
    FMLClientHandler
    .spawnEntityIntoClientWorld()
    EntitySpawnAdjustmentPacket
    FMLNetworkHandler
    .makeEntitySpawnAdjustment
    (from EntityTrackerEntry)
    EntitySpawnAdjustmentPacket.execute()
    FMLClientHandler
    .adjustEntityLocationOnClient()
     

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