Exemplo n.º 1
0
bool BlockChest::onInteract(User* user, int32_t x, int16_t y, int32_t z, int map)
{
  //ToDo: check for large chest!
  sChunk* chunk = ServerInstance->map(map)->getChunk(blockToChunk(x), blockToChunk(z));
  if(chunk == NULL)
  {
    return false;
  }

  chestDataPtr _chestData;

  for(uint32_t i = 0; i < chunk->chests.size(); i++)
  {
    if((chunk->chests[i]->y() == y) && (chunk->chests[i]->x() == x) && (chunk->chests[i]->z() == z))
    {
      _chestData = chunk->chests[i];
      break;
    }
  }
  if(_chestData != NULL)
  {
    ServerInstance->inventory()->windowOpen(user, (_chestData->large() ? WINDOW_LARGE_CHEST : WINDOW_CHEST), x, y, z);
    return true;
  } else {
    return false;
  }
}
Exemplo n.º 2
0
//Falling physics loop
bool Physics::updateFall()
{

  uint32_t listSize = fallSimList.size();

  for (int32_t simIt = listSize-1; simIt >= 0; simIt--)
  {
    bool hitGround = false;    
    double timeInSec = (microTime()-fallSimList[simIt].startTime)/1000000.0;
    fallSimList[simIt].ticks++;

    const double gravity = 9.81;
    double offset = 0.5*gravity*timeInSec*timeInSec;
    int blockOffset = fallSimList[simIt].pos.y() - fallSimList[simIt].lastY;
    if(blockOffset != (int)offset)
    {
      for(int ypos = fallSimList[simIt].lastY-1; ypos >= fallSimList[simIt].lastY-((int)offset-blockOffset);ypos--)
      {
        uint8_t block, meta;
        ServerInstance->map(map)->getBlock(fallSimList[simIt].pos.x(),ypos,fallSimList[simIt].pos.z(), &block, &meta);
        fallSimList[simIt].lastY--;
        switch (block)
        {
        case BLOCK_AIR:
        case BLOCK_WATER:
        case BLOCK_STATIONARY_WATER:
        case BLOCK_LAVA:
        case BLOCK_STATIONARY_LAVA:
        case BLOCK_SNOW:
          break;
          //If we hit ground
        default:
          {
            ServerInstance->map(map)->setBlock(fallSimList[simIt].pos.x(),ypos+1,fallSimList[simIt].pos.z(), fallSimList[simIt].block, 0);
            ServerInstance->map(map)->sendBlockChange(fallSimList[simIt].pos.x(),ypos+1,fallSimList[simIt].pos.z(), fallSimList[simIt].block, 0);
            
            //Despawn entity
            Packet pkt = Protocol::destroyEntity(fallSimList[simIt].EID);
            const int chunk_x = blockToChunk(fallSimList[simIt].pos.x());
            const int chunk_z = blockToChunk(fallSimList[simIt].pos.z());
            const ChunkMap::const_iterator it = ServerInstance->map(map)->chunks.find(Coords(chunk_x, chunk_z));
            if (it != ServerInstance->map(map)->chunks.end())
            {               
              it->second->sendPacket(pkt);
            }
            //Erase from the simulation list
            fallSimList.erase(fallSimList.begin()+simIt);
            hitGround = true;
          break;
          }
        }
        if(hitGround)
        {
          break;
        }
      }
    }
  }
  return true;
}
Exemplo n.º 3
0
//Falling physics loop
bool Physics::updateFall()
{

	uint32_t listSize = fallSimList.size();

	for (int32_t simIt = listSize-1; simIt >= 0; simIt--) {
		Falling& f = fallSimList[simIt];

		double timeInSec = (microTime()-f.startTime)/1000000.0;
		f.ticks++;

		const double gravity = 9.81;
		double offset = 0.5*gravity*timeInSec*timeInSec;
		int blockOffset = f.pos.y() - f.lastY;
		if(blockOffset != (int)offset) { ///  not necessary, doesn't optimize much
			int yStart = f.pos.y();
			int x = f.pos.x();
			int z = f.pos.z();

			int ypos = f.lastY;

			f.lastY = yStart-(int)offset;
			for(; ypos >= f.lastY; ypos--) {
				uint8_t block, meta;
				map->getBlock(x,ypos,z, &block, &meta);
				switch (block) {
				case BLOCK_AIR:
				case BLOCK_WATER:
				case BLOCK_STATIONARY_WATER:
				case BLOCK_LAVA:
				case BLOCK_STATIONARY_LAVA:
				case BLOCK_SNOW:
					break;
				//If we hit ground
				default: {
					map->setBlock(x, ++ypos, z, f.block, 0);
					map->sendBlockChange(x, ypos, z, f.block, 0);

					//Despawn entity
					Packet pkt = Protocol::destroyEntity(f.EID);
					const int chunk_x = blockToChunk(x);
					const int chunk_z = blockToChunk(z);
					const ChunkMap::const_iterator it = map->chunks.find(Coords(chunk_x, chunk_z));
					if (it != map->chunks.end()) {
						it->second->sendPacket(pkt);
					}
					//Erase from the simulation list
					fallSimList.erase(fallSimList.begin()+simIt);
					goto breakout;
				}
				}
			}
		}
breakout:
		continue;
	}
	return true;
}
Exemplo n.º 4
0
void BlockFalling::applyPhysics(User* user, int32_t x, int16_t y, int32_t z, int map)
{
  uint8_t fallblock, block;
  uint8_t fallmeta, meta;

  if (!ServerInstance->map(map)->getBlock(x, y, z, &fallblock, &fallmeta))
  {
    return;
  }


  
  if (ServerInstance->map(map)->getBlock(x, y - 1, z, &block, &meta))
  {
    switch (block)
    {
    case BLOCK_AIR:
    case BLOCK_WATER:
    case BLOCK_STATIONARY_WATER:
    case BLOCK_LAVA:
    case BLOCK_STATIONARY_LAVA:
    case BLOCK_SNOW:
      break;
    default:
       return;
      break;
    }

    // Destroy original block
    ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);
    ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);

    y--;


    //Spawn an entity for the falling block
    const int chunk_x = blockToChunk(x);
    const int chunk_z = blockToChunk(z);

    const ChunkMap::const_iterator it = ServerInstance->map(map)->chunks.find(Coords(chunk_x, chunk_z));

    if (it == ServerInstance->map(map)->chunks.end())
       return;

    uint32_t EID = Mineserver::generateEID();
    uint8_t object = 70; //type == Falling object
    Packet pkt = Protocol::addObject(EID,object, (x<<5)+16, ((y+1)<<5)+16, (z<<5)+16, fallblock|(fallmeta<<0x10));
    it->second->sendPacket(pkt);

    //Add to physics loop
    ServerInstance->physics(map)->addFallSimulation(fallblock,vec(x, y, z), EID);

    this->notifyNeighbours(x, y + 1, z, map, "onNeighbourMove", user, fallblock, BLOCK_BOTTOM);

  }
}
Exemplo n.º 5
0
bool BlockChest::getChestByCoordinates(int32_t x, int16_t y, int32_t z, int map, chestDataPtr& chest)
{
	sChunk* chunk = ServerInstance->map(map)->getChunk(blockToChunk(x), blockToChunk(z));
	for(size_t i = 0; i < chunk->chests.size(); i++) {
		if((chunk->chests[i]->x() == x)
		        && (chunk->chests[i]->y() == y)
		        && (chunk->chests[i]->z() == z)) {
			chest = chunk->chests[i];
			return true;
		}
	}
	return false;
}
Exemplo n.º 6
0
void ItemFood::onRightClick(User* user, Item* item)
{
	int healammount = 0;
	switch (item->getType()) {
	case ITEM_GOLDEN_APPLE:
		healammount = 20;
		break;
	case ITEM_MUSHROOM_SOUP:
		healammount = 10;
		break;
	case ITEM_GRILLED_PORK:
		healammount = 8;
		break;
	case ITEM_PORK:
		healammount = 3;
		break;
	case ITEM_BREAD:
		healammount = 5;
		break;
	case ITEM_COOKED_FISH:
		healammount = 5;
		break;
	case ITEM_RAW_FISH:
		healammount = 2;
		break;
	case ITEM_APPLE:
		healammount = 4;
		break;
	}

	int newhealth = user->health + healammount;
	if (newhealth > 20) {
		newhealth = 20;
	}

	user->sethealth(newhealth);

	//Accept eating
	user->buffer << Protocol::entityStatus(user->UID, 9);

	//Eating animation
	MetaData meta;
	meta.set(MetaDataElem(0,0x10));
	Packet pkt = Protocol::animation(user->UID,5);
	//pkt << Protocol::entityMetadata(user->UID, meta);
	//ToDo: add timer stop animation

	sChunk* chunk = ServerInstance->map(user->pos.map)->getChunk(blockToChunk((int32_t)user->pos.x), blockToChunk((int32_t)user->pos.z));
	if (chunk != nullptr) {
		chunk->sendPacket(pkt);
	}

	if(item->getCount() > 1) {
		item->setCount(item->getCount()-1);
	} else {
		item->setType(-1);
		item->setCount(0);
	}
}
Exemplo n.º 7
0
bool Map::getBlock(int x, int y, int z, uint8 *type, uint8 *meta, bool generate)
{
#ifdef MSDBG
  printf("getBlock(x=%d, y=%d, z=%d)\n", x, y, z);
#endif

  if((y < 0) || (y > 127))
  {
    printf("(%i, %i, %i) ", x, y, z);
    LOG("Invalid y value (getBlock)");
    return false;
  }

  int chunk_x = blockToChunk(x);
  int chunk_z = blockToChunk(z);

  uint32 mapId;
  Map::posToId(chunk_x, chunk_z, &mapId);

  sChunk *chunk = getMapData(chunk_x, chunk_z, generate);

  if(!chunk)
  {
    if(generate)
     LOG("Loading chunk failed (getBlock)");
    return false;
  }

  int chunk_block_x  = blockToChunkBlock(x);
  int chunk_block_z  = blockToChunkBlock(z);

  uint8 *blocks      = chunk->blocks;
  uint8 *metapointer = chunk->data;
  int index          = y + (chunk_block_z * 128) + (chunk_block_x * 128 * 16);
  *type = blocks[index];
  uint8 metadata     = metapointer[(index)>>1];

  if(y%2)
  {
    metadata  &= 0xf0;
    metadata >>= 4;
  }
Exemplo n.º 8
0
bool BlockFurnace::onBroken(User* user, int8_t status, int32_t x, int8_t y, int32_t z, int map,  int8_t direction)
{
  uint8_t block;
  uint8_t meta;

  if (!Mineserver::get()->map(map)->getBlock(x, y, z, &block, &meta))
  {
    return true;
  }

  bool destroy = false;

  int chunk_x = blockToChunk(x);
  int chunk_z = blockToChunk(z);

  sChunk* chunk = Mineserver::get()->map(map)->loadMap(chunk_x, chunk_z);

  if (chunk == NULL)
  {
    return true;
  }

  for (uint32_t i = 0; i < chunk->furnaces.size(); i++)
  {
    if (chunk->furnaces[i]->x == x &&
        chunk->furnaces[i]->y == y &&
        chunk->furnaces[i]->z == z)
    {
      chunk->furnaces.erase(chunk->furnaces.begin() + i);
      break;
    }
  }

  Mineserver::get()->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);
  Mineserver::get()->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);
  this->spawnBlockItem(x, y, z, map, block);
  return false;
}
Exemplo n.º 9
0
int PacketHandler::entity_crouch(User* user)
{
  int32_t EID;
  int8_t action;
  MetaData meta;
  MetaDataElemByte *element;

  user->buffer >> EID >> action;
  Packet pkt;
  bool packetData = false;

  //ToDo: handle other actions
  switch(action)
  {
  //Crouch
  case 1:    
    element = new MetaDataElemByte(0,0x02);
    meta.set(element);
    pkt << Protocol::animation(user->UID, 104) << Protocol::entityMetadata(user->UID,meta);
    packetData = true;
    break;
    //Uncrouch
  case 2:
    element = new MetaDataElemByte(0,0x00);
    meta.set(element);
    pkt << Protocol::animation(user->UID, 105) << Protocol::entityMetadata(user->UID,meta);
    packetData = true;
    break;
  default:
    break;
  }
  
  if(packetData)
  {
    sChunk* chunk = ServerInstance->map(user->pos.map)->getChunk(blockToChunk((int32_t)user->pos.x), blockToChunk((int32_t)user->pos.z));
    if (chunk != NULL)
    {
      chunk->sendPacket(pkt);
    }
  }

  user->buffer.removePacket();
  return PACKET_OK;
}
Exemplo n.º 10
0
void BlockChest::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)
{
  // Locksystem
  if (user->inv[36 + user->currentItemSlot()].getType() == ITEM_WOODEN_AXE)
  {
    int chunk_x = blockToChunk(x);
    int chunk_z = blockToChunk(z);

    sChunk* chunk = ServerInstance->map(map)->loadMap(chunk_x, chunk_z);

    if (chunk == NULL)
    {
      return;
    }

    NBT_Value* entityList = (*(*(chunk->nbt))["Level"])["TileEntities"];

    if (!entityList)
    {
      entityList = new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND);
      chunk->nbt->Insert("TileEntities", entityList);
    }

    if (entityList->GetType() == NBT_Value::TAG_LIST)
    {
      if (entityList->GetListType() != NBT_Value::TAG_COMPOUND)
      {
        entityList->SetType(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND);
      }

      std::vector<NBT_Value*> *entities = entityList->GetList();
      std::vector<NBT_Value*>::iterator iter = entities->begin(), end = entities->end();

      //bool done = false; // Unused variable

      for (; iter != end; iter++)
      {
        if ((**iter)["x"] == NULL || (**iter)["y"] == NULL || (**iter)["z"] == NULL ||
            (**iter)["x"]->GetType() != NBT_Value::TAG_INT ||
            (**iter)["y"]->GetType() != NBT_Value::TAG_INT ||
            (**iter)["z"]->GetType() != NBT_Value::TAG_INT)
        {
          continue;
        }

        if ((int32_t)(*(**iter)["x"]) == x && (int32_t)(*(**iter)["y"]) == y && (int32_t)(*(**iter)["z"]) == z)
        {
          int8_t locked;
          NBT_Value* nbtLockdata = (**iter)["Lockdata"];
          if (nbtLockdata != NULL)
          {
            std::string player = *(*nbtLockdata)["player"]->GetString();
            // Toggle lock if player is the owner of block
            if (player == user->nick)
            {
              locked = *(*nbtLockdata)["locked"];
              locked = (locked == 1) ? 0 : 1;
              *(*nbtLockdata)["locked"] = locked;

              if (locked == 1)
              {
                ServerInstance->chat()->sendMsg(user, MC_COLOR_RED + "Chest locked", Chat::USER);
              }
              else
              {
                ServerInstance->chat()->sendMsg(user, MC_COLOR_RED + "Chest opened", Chat::USER);
              }

            }
          }
          else
          {
            // If lockdata is missing (old chest)
            NBT_Value* nbtLock = new NBT_Value(NBT_Value::TAG_COMPOUND);
            nbtLock->Insert("player", new NBT_Value(user->nick));
            nbtLock->Insert("locked", new NBT_Value((int8_t)1));
            (*iter)->Insert("Lockdata", nbtLock);
          }
          break;
        }
      }
    }
  }
}
Exemplo n.º 11
0
bool InventoryWorkbench::onwindowClick(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber, 
                                      int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode)
{

  // Safeguard against overflow
  if (slot > MAX_SLOT_CRAFTING_TABLE) return false;
  if (slot != -999 && slot < 0) return false;

  Inventory* inventory = ServerInstance->inventory();
  //Ack
  if(actionNumber)
  {
    // ToDo: actually check the action before ack
    user->writePacket(Protocol::confirmTransaction(windowID, actionNumber, 1));
  }

  // Handle drag mode in a base class helper function
  if (mode == INVENTORY_MODE_DRAG)
  {
    return this->handleDrag(user, windowID, slot, button, actionNumber, itemID, itemCount, itemUses, mode);
  }
  else if (mode == INVENTORY_MODE_NUMBER)
  {
    return this->handleNumber(user, windowID, slot, button, actionNumber, itemID, itemCount, itemUses, mode);
  }
  user->openInv.recordAction = false;

  //Click outside the window
  if (slot == -999)
  {
    //Dropping outside of the window
    if(button == 0 && mode == 0 && user->inventoryHolding.getType() != -1)
    {
      ServerInstance->map(user->pos.map)->createPickupSpawn((int)user->pos.x, (int)user->pos.y, (int)user->pos.z,
          user->inventoryHolding.getType(), user->inventoryHolding.getCount(),
          user->inventoryHolding.getHealth(), user);
      user->inventoryHolding.setType(-1);
      return true;
    }
    return true;
  }
  //on click-and-drag mode, recording the slots used
  else if(user->openInv.recordAction)
  {
    if(mode == 5)
    {
      user->openInv.slotActions.push_back(slot);
    }
    else
    {
      user->openInv.recordAction = false;
    }
    return true;
  }

  if (!user->isOpenInv && windowID != 0)
  {
    return false;
  }

  sChunk* chunk = NULL;
  chunk = ServerInstance->map(user->pos.map)->getChunk(blockToChunk(user->openInv.x), blockToChunk(user->openInv.z));

  if (chunk == NULL)
  {
    return false;
  }

  chunk->changed = true;


  std::vector<User*>* otherUsers = NULL;
  OpenInvPtr currentInventory;
  std::vector<OpenInvPtr>& inv = inventory->openWorkbenches;

  for (size_t i = 0; i < inv.size(); i++)
  {
    if (inv[i]->x == user->openInv.x &&
        inv[i]->y == user->openInv.y &&
        inv[i]->z == user->openInv.z)
    {
      otherUsers = &inv[i]->users;
      currentInventory = inv[i];
      break;
    }
  }

  if (otherUsers == NULL || currentInventory == NULL)
  {
    return false;
  }


  Item* slotItem = NULL;

  if (slot > 9)
  {
    slotItem = &user->inv[slot - 1];
  }
  else
  {
    slotItem = &currentInventory->workbench[slot];
  }


  bool workbenchCrafting = false;
  
  //Empty slot and holding something
  if ((slotItem->getType() == -1 || (slotItem->getType() == user->inventoryHolding.getType() && slotItem->getHealth() == user->inventoryHolding.getHealth() && slotItem->getCount() < 64)) && user->inventoryHolding.getType() != -1)
  {
    //If accessing crafting output slot
    if (slotItem->getType() != -1 && slot == 0)
    {
      if (user->inventoryHolding.getType() == slotItem->getType() && 64 - user->inventoryHolding.getCount() >= slotItem->getCount())
      {
        user->inventoryHolding.decCount(-slotItem->getCount());

        for (uint8_t workbenchSlot = 1; workbenchSlot < 10; workbenchSlot++)
        {
          if (currentInventory->workbench[workbenchSlot].getType() != -1)
          {
            currentInventory->workbench[workbenchSlot].decCount();
            inventory->setSlot(user, windowID, workbenchSlot, &currentInventory->workbench[workbenchSlot]);
          }
        }
        workbenchCrafting = true;

      }
    }
    else
    {
      //ToDo: Make sure we have room for the items!

      //Make sure not putting anything to the crafting space
      if (slot != 0)
      {
        int16_t addCount = (64 - slotItem->getCount() >= user->inventoryHolding.getCount()) ? user->inventoryHolding.getCount() : 64 - slotItem->getCount();

        slotItem->decCount(0 - ((button) ? 1 : addCount));
        slotItem->setHealth(user->inventoryHolding.getHealth());
        slotItem->setType(user->inventoryHolding.getType());

        user->inventoryHolding.decCount((button) ? 1 : addCount);
      }
    }

  }
  //We are not holding anything, get the item we clicked
  else if (user->inventoryHolding.getType() == -1)
  {
    //If accessing crafting output slot, remove from input!
    if (slotItem->getType() != -1 && slot == 0)
    {
      user->inventoryHolding.setType(slotItem->getType());
      user->inventoryHolding.setCount(slotItem->getCount());
      user->inventoryHolding.setHealth(slotItem->getHealth());

      for (uint8_t workbenchSlot = 1; workbenchSlot < 10; workbenchSlot++)
      {
        if (currentInventory->workbench[workbenchSlot].getType() != -1)
        {
          currentInventory->workbench[workbenchSlot].decCount();

          inventory->setSlot(user, windowID, workbenchSlot, &currentInventory->workbench[workbenchSlot]);
        }
      }
      workbenchCrafting = true;

      
    }
    else
    {

      //Shift+click -> items to player inv
      //ToDo: from player inventory to chest
      if(!button && mode &&inventory-> isSpace(user, slotItem->getType(), slotItem->getCount()))
      {
        inventory->addItems(user, slotItem->getType(), slotItem->getCount(), slotItem->getHealth());
        slotItem->setCount(0);
      }
      else
      {
        user->inventoryHolding.setType(slotItem->getType());
        user->inventoryHolding.setHealth(slotItem->getHealth());
        user->inventoryHolding.setCount(slotItem->getCount());
        if (button == 1)
        {
          user->inventoryHolding.decCount(slotItem->getCount() >> 1);
        }
        slotItem->decCount(user->inventoryHolding.getCount());
      }
      
      if (slotItem->getCount() == 0)
      {
        slotItem->setHealth(0);
        slotItem->setType(-1);
      }
    }
  }
Exemplo n.º 12
0
bool BlockChest::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)
{
  uint8_t oldblock;
  uint8_t oldmeta;

  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  /* Check block below allows blocks placed on top */
  if (!this->isBlockStackable(oldblock))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  /* move the x,y,z coords dependent upon placement direction */
  if (!this->translateDirection(&x, &y, &z, map, direction))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  if (this->isUserOnBlock(x, y, z, map))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  if (!this->isBlockEmpty(x, y, z, map))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  // if there is a large chest around --> block
  {
    chestDataPtr _connectedChest;
    if(findConnectedChest(x, y, z, map, _connectedChest))
    {
      if(_connectedChest->large())
      {
        revertBlock(user, x, y, z, map);
        return true;
      }
    }
  }

  direction = user->relativeToBlock(x, y, z);

  //// Fix orientation  
  switch (direction)
  {
  case BLOCK_EAST:
    //direction = BLOCK_SOUTH;
    break;
  case BLOCK_BOTTOM:
    direction = BLOCK_WEST;
    break;
  case BLOCK_NORTH:
    direction = BLOCK_TOP;
    break;
  case BLOCK_SOUTH:
    //direction = BLOCK_NORTH;
    break;
  }
  

  int32_t connectedChestX, connectedChestZ;
  if(findConnectedChest(x, y, z, map, &connectedChestX, &connectedChestZ))
  {
    if(connectedChestX != x)
    {
      if(!(direction == 3 || direction == 2))
      {
        direction = 3;
      }
    }
    if(connectedChestZ != z)
    {
      if(!(direction == 4 || direction == 5))
      {
        direction = 4;
      }
    }

    ServerInstance->map(map)->setBlock(connectedChestX, y, connectedChestZ, (char)newblock, direction);
    ServerInstance->map(map)->sendBlockChange(connectedChestX, y, connectedChestZ, (char)newblock, direction);

    // create a new chest and connect it to another chest --> large chest
    chestDataPtr connectedChest;
    if(getChestByCoordinates(connectedChestX, y, connectedChestZ, map, connectedChest))
    {
      chestDataPtr newchest;
      if(!getChestByCoordinates(x, y, z, map, newchest))
      {
        sChunk* chunk = ServerInstance->map(map)->getChunk(blockToChunk(x), blockToChunk(z));
        if(chunk != NULL)
        {
          newchest = chestDataPtr(new chestData);
          newchest->items(connectedChest->items());
          newchest->x(x);
          newchest->y(y);
          newchest->z(z);
          chunk->chests.push_back(newchest);
        }
      } else {
        newchest->large(true);
      }
      connectedChest->large(true);
    }
  } else {
    // create a new (small) chest
    chestDataPtr newchest(new chestData);
    sChunk* chunk = ServerInstance->map(map)->getChunk(blockToChunk(x), blockToChunk(z));
    if(chunk != NULL)
    {
      newchest->x(x);
      newchest->y(y);
      newchest->z(z);
      chunk->chests.push_back(newchest);
    }
  }

  ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, direction);
  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)newblock, direction);
  return false;
}
Exemplo n.º 13
0
bool BlockChest::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)
{
  uint8_t block;
  uint8_t meta;

  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))
  {
    return true;
  }

  bool destroy = false;

  int chunk_x = blockToChunk(x);
  int chunk_z = blockToChunk(z);

  sChunk* chunk = ServerInstance->map(map)->loadMap(chunk_x, chunk_z);

  if (chunk == NULL)
  {
    return true;
  }

  for (uint32_t i = 0; i < chunk->chests.size(); i++)
  {
    if (chunk->chests[i]->x() == x &&
        chunk->chests[i]->y() == y &&
        chunk->chests[i]->z() == z)
    {
      if(!chunk->chests[i]->large())
      {
        // clean up a small chest
        int32_t item_i = 26;
        for(int32_t item_i = 26; 0 <= item_i; item_i--)
        {
          if ((*chunk->chests[i]->items())[(size_t)item_i]->getType() != -1)
          {
            ServerInstance->map(map)->createPickupSpawn(chunk->chests[i]->x(),
                chunk->chests[i]->y(),
                chunk->chests[i]->z(),
                (*chunk->chests[i]->items())[(size_t)item_i]->getType(),
                (*chunk->chests[i]->items())[(size_t)item_i]->getCount(),
                (*chunk->chests[i]->items())[(size_t)item_i]->getHealth(),
                NULL);
          }
          chunk->chests[i]->items()->pop_back();
        }
      } else {
        // size a large chest down
        for(uint32_t item_i = 53; 27-3 <= item_i; item_i--)
        {
          if ((*chunk->chests[i]->items())[item_i]->getType() != -1)
          {
            ServerInstance->map(map)->createPickupSpawn(chunk->chests[i]->x(),
                chunk->chests[i]->y(),
                chunk->chests[i]->z(),
                (*chunk->chests[i]->items())[item_i]->getType(),
                (*chunk->chests[i]->items())[item_i]->getCount(),
                (*chunk->chests[i]->items())[item_i]->getHealth(),
                NULL);
          }
          chunk->chests[i]->items()->pop_back();
        }
      }
      chunk->chests.erase(chunk->chests.begin() + i);

      break;
    }
  }

  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);
  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);
  this->spawnBlockItem(x, y, z, map, block);
  return false;

}
Exemplo n.º 14
0
bool BlockFurnace::onPlace(User* user, int16_t newblock, int32_t x, int8_t y, int32_t z, int map, int8_t direction)
{
  uint8_t oldblock;
  uint8_t oldmeta;

  if (!Mineserver::get()->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  /* Check block below allows blocks placed on top */
  if (!this->isBlockStackable(oldblock))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  /* move the x,y,z coords dependent upon placement direction */
  if (!this->translateDirection(&x, &y, &z, map, direction))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  if (this->isUserOnBlock(x, y, z, map))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  if (!this->isBlockEmpty(x, y, z, map))
  {
    revertBlock(user, x, y, z, map);
    return true;
  }

  direction = user->relativeToBlock(x, y, z);

  // Fix orientation

  //switch (direction)
  //{
  //case BLOCK_EAST:
  //  direction = BLOCK_SOUTH;
  //  break;
  //case BLOCK_BOTTOM:
  //  direction = BLOCK_EAST;
  //  break;
  //case BLOCK_NORTH:
  //  direction = BLOCK_NORTH;
  //  break;
  //case BLOCK_SOUTH:
  //  direction = BLOCK_BOTTOM;
  //  break;
  //}

  Mineserver::get()->map(map)->setBlock(x, y, z, (char)newblock, direction);
  Mineserver::get()->map(map)->sendBlockChange(x, y, z, (char)newblock, direction);


  int chunk_x = blockToChunk(x);
  int chunk_z = blockToChunk(z);
  sChunk* chunk = Mineserver::get()->map(map)->loadMap(chunk_x, chunk_z);

  if (chunk == NULL)
  {
    revertBlock(user, x, y, z, map);
  }
  return true;

  for (uint32_t i = 0; i < chunk->furnaces.size(); i++)
  {
    if (chunk->furnaces[i]->x == x &&
        chunk->furnaces[i]->y == y &&
        chunk->furnaces[i]->z == z)
    {
      chunk->furnaces.erase(chunk->furnaces.begin() + i);
      break;
    }
  }

  return false;
}
Exemplo n.º 15
0
bool Inventory::windowClick(User *user,int8_t windowID, int16_t slot, int8_t rightClick, int16_t actionNumber, int16_t itemID, int8_t itemCount,int16_t itemUses)
{  
  //Ack
  user->buffer << (int8_t)PACKET_TRANSACTION << (int8_t)windowID << (int16_t)actionNumber << (int8_t)1;

  //Mineserver::get()->logger()->log(1,"window: " + dtos(windowID) + " slot: " + dtos(slot) + " (" + dtos(actionNumber) + ") itemID: " + dtos(itemID));
  //Click outside the window
  if(slot == -999)
  {
    if(user->inventoryHolding.type != -1)
    {
      Mineserver::get()->map()->createPickupSpawn((int)user->pos.x, (int)user->pos.y, (int)user->pos.z, 
                                                  user->inventoryHolding.type, user->inventoryHolding.count,
                                                  user->inventoryHolding.health,user);
      user->inventoryHolding.count = 0;
      user->inventoryHolding.type  =-1;
      user->inventoryHolding.health= 0;
    }
    return true;
  }

  if(!user->isOpenInv && windowID != 0)
  {
    return false;
  }

  sChunk* chunk = NULL;
  if(windowID != 0)
  {
    chunk = Mineserver::get()->map()->chunks.getChunk(blockToChunk(user->openInv.x),blockToChunk(user->openInv.z));

    if(chunk == NULL)
    {
      return false;
    }

    chunk->changed = true;
  }

  std::vector<User*>* otherUsers = NULL;
  OpenInventory* currentInventory = NULL;

  if(windowID != WINDOW_PLAYER)
  {
    std::vector<OpenInventory*>* inv = NULL;
    switch(user->openInv.type)
    {
      case WINDOW_CHEST:
        inv = &openChests;
        break;
      case WINDOW_FURNACE:
        inv = &openFurnaces;
        break;
      case WINDOW_WORKBENCH:
        inv = &openWorkbenches;
        break;
    }

    for(uint32_t i = 0; i < inv->size(); i++)
    {
      if((*inv)[i]->x == user->openInv.x &&
         (*inv)[i]->y == user->openInv.y &&
         (*inv)[i]->z == user->openInv.z)
      {
        otherUsers = &(*inv)[i]->users;
        currentInventory = (*inv)[i];
        break;
      }
    }

    if(otherUsers == NULL || currentInventory == NULL)
    {
      return false;
    }
  }

  Item* slotItem = NULL;

  switch(windowID)
  {
     //Player inventory
    case WINDOW_PLAYER:
      slotItem=&user->inv[slot];
      break;
    case WINDOW_CHEST:
      if(slot>26)
      {
        slotItem=&user->inv[slot-18];
      }
      else
      {
        for(uint32_t i = 0; i < chunk->chests.size(); i ++)
        {
          if(chunk->chests[i]->x == user->openInv.x &&
             chunk->chests[i]->y == user->openInv.y &&
             chunk->chests[i]->z == user->openInv.z)
          {
            slotItem = &chunk->chests[i]->items[slot];
            break;
          }
        }
        //Create chest data if it doesn't exist
        if(slotItem == NULL)
        {
          chestData *newChest = new chestData;
          newChest->x = user->openInv.x;
          newChest->y = user->openInv.y;
          newChest->z = user->openInv.z;
          chunk->chests.push_back(newChest);
          slotItem = &newChest->items[slot];
        }
      }
      break;
    case WINDOW_LARGE_CHEST:
      if(slot>54)
      {
        slotItem=&user->inv[slot-47];
      }
      else
      {
        //ToDo: Handle large chest
      }
      break;
    case WINDOW_FURNACE:
      if(slot>3)
      {
        slotItem=&user->inv[slot+6];
      }
      else
      {
        for(uint32_t i = 0; i < chunk->furnaces.size(); i ++)
        {
          if(chunk->furnaces[i]->x == user->openInv.x &&
             chunk->furnaces[i]->y == user->openInv.y &&
             chunk->furnaces[i]->z == user->openInv.z)
          {
            slotItem = &chunk->furnaces[i]->items[slot];
          }
        }
        //Create furnace data if it doesn't exist
        if(slotItem == NULL)
        {
          furnaceData *newFurnace = new furnaceData;
          newFurnace->x = user->openInv.x;
          newFurnace->y = user->openInv.y;
          newFurnace->z = user->openInv.z;
          newFurnace->burnTime = 0;
          newFurnace->cookTime = 0;
          chunk->furnaces.push_back(newFurnace);
          slotItem = &newFurnace->items[slot];
        }
      }
      break;
    case WINDOW_WORKBENCH:
      if(slot > 9)
      {
        slotItem=&user->inv[slot-1];
      }
      else
      {
        slotItem=&currentInventory->workbench[slot];
      }
      break;
  }
  
  bool workbenchCrafting = false;
  bool playerCrafting    = false;

  //Empty slot and holding something
  if((itemID == -1 || (slotItem->type == user->inventoryHolding.type && slotItem->count < 64) ) && user->inventoryHolding.type != -1)
  {
    //If accessing crafting output slot
    if(slotItem->type != -1 && (windowID == WINDOW_WORKBENCH || windowID == WINDOW_PLAYER) && slot == 0)
    {
      if(user->inventoryHolding.type == slotItem->type && 64-user->inventoryHolding.count >= slotItem->count)
      {
        user->inventoryHolding.count += slotItem->count;
        if(windowID == WINDOW_WORKBENCH)
        {
          for(uint8_t workbenchSlot = 1; workbenchSlot < 10; workbenchSlot++)
          {
            if(currentInventory->workbench[workbenchSlot].type != -1)
            {
              currentInventory->workbench[workbenchSlot].count --;
              if(currentInventory->workbench[workbenchSlot].count == 0)
              {
                currentInventory->workbench[workbenchSlot] = Item();
              }
              setSlot(user, windowID, workbenchSlot, currentInventory->workbench[workbenchSlot].type, 
                                                     currentInventory->workbench[workbenchSlot].count, 
                                                     currentInventory->workbench[workbenchSlot].health);
            }
          }
          workbenchCrafting = true;
        }
        else
        {
          for(uint8_t playerSlot = 1; playerSlot < 5; playerSlot++)
          {
            if(user->inv[playerSlot].type != -1)
            {
              user->inv[playerSlot].count --;
              if(user->inv[playerSlot].count == 0)
              {
                user->inv[playerSlot] = Item();
              }
              setSlot(user, windowID, playerSlot, user->inv[playerSlot].type, 
                                                  user->inv[playerSlot].count, 
                                                  user->inv[playerSlot].health);
            }
          }
          playerCrafting = true;
        }
      }
    }
    else
    {
      //ToDo: Make sure we have room for the items!

      //Make sure not putting anything to the crafting space
      if((windowID != WINDOW_WORKBENCH && windowID != WINDOW_PLAYER) || slot != 0)
      {
        int16_t addCount = (64-slotItem->count>=user->inventoryHolding.count)?user->inventoryHolding.count:64-slotItem->count;

        slotItem->count  += ((rightClick)?1:addCount);
        slotItem->health  = user->inventoryHolding.health;
        slotItem->type    = user->inventoryHolding.type;

        user->inventoryHolding.count -= ((rightClick)?1:addCount);
        if(user->inventoryHolding.count == 0)
        {
          user->inventoryHolding.type  = -1;
          user->inventoryHolding.health= 0;
        }
      }
    }
    
  }
  else if(user->inventoryHolding.type == -1)
  {
    //If accessing crafting output slot, remove from input!
    if(slotItem->type != -1 && (windowID == WINDOW_WORKBENCH || windowID == WINDOW_PLAYER) && slot == 0)
    {
      user->inventoryHolding.type = slotItem->type;
      user->inventoryHolding.count = slotItem->count;
      user->inventoryHolding.health = slotItem->health;

      if(windowID == WINDOW_WORKBENCH)
      {
        for(uint8_t workbenchSlot = 1; workbenchSlot < 10; workbenchSlot++)
        {
          if(currentInventory->workbench[workbenchSlot].type != -1)
          {
            currentInventory->workbench[workbenchSlot].count --;
            if(currentInventory->workbench[workbenchSlot].count == 0)
            {
              currentInventory->workbench[workbenchSlot] = Item();
            }

            setSlot(user, windowID, workbenchSlot,currentInventory->workbench[workbenchSlot].type, 
                                                  currentInventory->workbench[workbenchSlot].count, 
                                                  currentInventory->workbench[workbenchSlot].health);
          }
        }
        workbenchCrafting = true;
      }
      else
      {
        for(uint8_t playerSlot = 1; playerSlot < 5; playerSlot++)
        {
          if(user->inv[playerSlot].type != -1)
          {
            user->inv[playerSlot].count --;
            if(user->inv[playerSlot].count == 0)
            {
              user->inv[playerSlot] = Item();
            }
            setSlot(user, windowID, playerSlot, user->inv[playerSlot].type, 
                                                user->inv[playerSlot].count, 
                                                user->inv[playerSlot].health);
          }
        }
        playerCrafting = true;
      }
    }
    else
    {
      user->inventoryHolding.type   = slotItem->type;
      user->inventoryHolding.health = slotItem->health;
      user->inventoryHolding.count  = slotItem->count;
      if(rightClick == 1)
      {
        user->inventoryHolding.count  -= slotItem->count>>1;
      }

      slotItem->count  -= user->inventoryHolding.count;
      if(slotItem->count == 0)
      {
        slotItem->health = 0;
        slotItem->type   =-1;
      }      
    }
  }
Exemplo n.º 16
0
bool Inventory::windowClick(User* user, int8_t windowID, int16_t slot, int8_t rightClick, int16_t actionNumber, int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t shift)
{
  //Ack
  user->buffer << Protocol::transaction( (int8_t)windowID, (int16_t)actionNumber, (int8_t)1 );

  //Click outside the window
  if (slot == -999)
  {
    if (user->inventoryHolding.getType() != -1)
    {
      Mineserver::get()->map(user->pos.map)->createPickupSpawn((int)user->pos.x, (int)user->pos.y, (int)user->pos.z,
          user->inventoryHolding.getType(), user->inventoryHolding.getCount(),
          user->inventoryHolding.getHealth(), user, false);
      user->inventoryHolding.setType(-1);
    }
    return true;
  }

  if (!user->isOpenInv && windowID != 0)
  {
    return false;
  }

  sChunk* chunk = NULL;
  if (windowID != 0)
  {
    chunk = Mineserver::get()->map(user->pos.map)->getChunk(blockToChunk(user->openInv.x), blockToChunk(user->openInv.z));

    if (chunk == NULL)
    {
      return false;
    }

    chunk->changed = true;
  }

  std::vector<User*>* otherUsers = NULL;
  OpenInvPtr currentInventory;

  if (windowID != WINDOW_PLAYER)
  {
    std::vector<OpenInvPtr>* pinv = NULL;
    switch (user->openInv.type)
    {
    case WINDOW_CHEST:
    case WINDOW_LARGE_CHEST:
      pinv = &openChests;
      break;
    case WINDOW_FURNACE:
      pinv = &openFurnaces;
      break;
    case WINDOW_WORKBENCH:
      pinv = &openWorkbenches;
      break;
    }

    std::vector<OpenInvPtr>& inv = *pinv;

    for (size_t i = 0; i < inv.size(); i++)
    {
      if (inv[i]->x == user->openInv.x &&
          inv[i]->y == user->openInv.y &&
          inv[i]->z == user->openInv.z)
      {
        otherUsers = &inv[i]->users;
        currentInventory = inv[i];
        break;
      }
    }

    if (otherUsers == NULL || currentInventory == NULL)
    {
      return false;
    }
  }

  Item* slotItem;
  furnaceDataPtr tempFurnace;

  switch (windowID)
  {
    //Player inventory
  case WINDOW_PLAYER:
    slotItem = &user->inv[slot];
    break;
  case WINDOW_CHEST:
    if (slot > 26)
    {
      slotItem = &user->inv[slot - 18];
    }
    else
    {
      for (uint32_t i = 0; i < chunk->chests.size(); i ++)
      {
        if (chunk->chests[i]->x() == user->openInv.x &&
            chunk->chests[i]->y() == user->openInv.y &&
            chunk->chests[i]->z() == user->openInv.z)
        {
          slotItem = (*chunk->chests[i]->items())[slot].get();
          break;
        }
      }
      //Create chest data if it doesn't exist
      if (slotItem == NULL)
      {
        chestDataPtr newChest(new chestData);
        newChest->x(user->openInv.x);
        newChest->y(user->openInv.y);
        newChest->z(user->openInv.z);
        chunk->chests.push_back(newChest);
        slotItem = (*newChest->items())[slot].get();
      }
    }
    break;
  case WINDOW_LARGE_CHEST:
    if (slot > 54)
    {
      slotItem = &user->inv[slot - 45];
    }
    else
    {
      //ToDo: Handle large chest
      for (uint32_t i = 0; i < chunk->chests.size(); i++)
      {
        //if(!chunk->chests[i]->large())
        //  continue;

        if(chunk->chests[i]->x() == user->openInv.x &&
          chunk->chests[i]->y() == user->openInv.y &&
          chunk->chests[i]->z() == user->openInv.z)
        {
          slotItem = (*chunk->chests[i]->items())[slot].get();
          break;
        }
      }
      if(slotItem == NULL)
      {
        chestDataPtr newChest(new chestData);
        newChest->x(user->openInv.x);
        newChest->y(user->openInv.y);
        newChest->z(user->openInv.z);
        newChest->large(true);
        chunk->chests.push_back(newChest);
        slotItem = (*newChest->items())[slot].get();
      }
    }
    break;
  case WINDOW_FURNACE:
    if (slot >= 3)
    {
      slotItem = &user->inv[slot + 6];
    }
    else
    {
      for (uint32_t i = 0; i < chunk->furnaces.size(); i ++)
      {
        if (chunk->furnaces[i]->x == user->openInv.x &&
            chunk->furnaces[i]->y == user->openInv.y &&
            chunk->furnaces[i]->z == user->openInv.z)
        {
          slotItem = &chunk->furnaces[i]->items[slot];
          tempFurnace = chunk->furnaces[i];
        }
      }
      //Create furnace data if it doesn't exist
      if (slotItem == NULL)
      {
        furnaceDataPtr newFurnace(new furnaceData);
        newFurnace->x = user->openInv.x;
        newFurnace->y = user->openInv.y;
        newFurnace->z = user->openInv.z;
        newFurnace->burnTime = 0;
        newFurnace->cookTime = 0;
        chunk->furnaces.push_back(newFurnace);
        slotItem = &newFurnace->items[slot];
        tempFurnace = newFurnace;
      }
    }
    break;
  case WINDOW_WORKBENCH:
    if (slot > 9)
    {
      slotItem = &user->inv[slot - 1];
    }
    else
    {
      slotItem = &currentInventory->workbench[slot];
    }
    break;
  }

  bool workbenchCrafting = false;
  bool playerCrafting    = false;

  if (windowID == WINDOW_PLAYER && slot >= 5 && slot <= 8)
  {
    // Armour slots are a strange case. Only a quantity of one should be allowed, so this must be checked for.
    if (slotItem->getType() == -1 && user->inventoryHolding.getType() > 0)
    {
      if (canBeArmour(slot, user->inventoryHolding.getType()))
      {
        slotItem->setType(user->inventoryHolding.getType());
        slotItem->setHealth(user->inventoryHolding.getHealth());
        slotItem->setCount(1);
        user->inventoryHolding.decCount();
      }
      else
      {
        slotItem->decCount(0);
        user->inventoryHolding.decCount(0); // Refresh both
      }
    }
    else if (slotItem->getType() > 0 && user->inventoryHolding.getType() == -1)
    {
      user->inventoryHolding.setType(slotItem->getType());
      user->inventoryHolding.setCount(slotItem->getCount());
      user->inventoryHolding.setHealth(slotItem->getHealth());
      slotItem->setType(-1);

    }
    else if (slotItem->getType() > 0 && user->inventoryHolding.getType() > 0 && user->inventoryHolding.getCount() == 1)
    {
      if (canBeArmour(slot, user->inventoryHolding.getType()))
      {
        uint16_t t_type = slotItem->getType();
        uint8_t t_count = slotItem->getCount();
        uint16_t t_health = slotItem->getHealth();
        slotItem->setCount(1);
        slotItem->setHealth(user->inventoryHolding.getHealth());
        slotItem->setType(user->inventoryHolding.getType());
        user->inventoryHolding.setCount(t_count);
        user->inventoryHolding.setHealth(t_health);
        user->inventoryHolding.setType(t_type);
      }
      else
      {
        slotItem->decCount(0);
        user->inventoryHolding.decCount(0); // Refresh both
      }
    }
    setSlot(user, WINDOW_CURSOR, 0, user->inventoryHolding.getType(), user->inventoryHolding.getCount(), user->inventoryHolding.getHealth());
    return false;
  }


  //Empty slot and holding something
  if ((slotItem->getType() == -1 || (slotItem->getType() == user->inventoryHolding.getType() && slotItem->getHealth() == user->inventoryHolding.getHealth() && slotItem->getCount() < 64)) && user->inventoryHolding.getType() != -1)
  {
    //If accessing crafting output slot
    if (slotItem->getType() != -1 && (windowID == WINDOW_WORKBENCH || windowID == WINDOW_PLAYER) && slot == 0)
    {
      if (user->inventoryHolding.getType() == slotItem->getType() && 64 - user->inventoryHolding.getCount() >= slotItem->getCount())
      {
        user->inventoryHolding.decCount(-slotItem->getCount());
        if (windowID == WINDOW_WORKBENCH)
        {
          for (uint8_t workbenchSlot = 1; workbenchSlot < 10; workbenchSlot++)
          {
            if (currentInventory->workbench[workbenchSlot].getType() != -1)
            {
              currentInventory->workbench[workbenchSlot].decCount();
              setSlot(user, windowID, workbenchSlot, currentInventory->workbench[workbenchSlot].getType(),
                      currentInventory->workbench[workbenchSlot].getCount(),
                      currentInventory->workbench[workbenchSlot].getHealth());
            }
          }
          workbenchCrafting = true;
        }
        else
        {
          for (uint8_t playerSlot = 1; playerSlot < 5; playerSlot++)
          {
            if (user->inv[playerSlot].getType() != -1)
            {
              user->inv[playerSlot].decCount();
              setSlot(user, windowID, playerSlot, user->inv[playerSlot].getType(),
                      user->inv[playerSlot].getCount(),
                      user->inv[playerSlot].getHealth());
            }
          }
          playerCrafting = true;
        }
      }
    }
    else
    {
      //ToDo: Make sure we have room for the items!

      //Make sure not putting anything to the crafting space
      if ((windowID != WINDOW_WORKBENCH && windowID != WINDOW_PLAYER) || slot != 0)
      {
        int16_t addCount = (64 - slotItem->getCount() >= user->inventoryHolding.getCount()) ? user->inventoryHolding.getCount() : 64 - slotItem->getCount();

        slotItem->decCount(0 - ((rightClick) ? 1 : addCount));
        slotItem->setHealth(user->inventoryHolding.getHealth());
        slotItem->setType(user->inventoryHolding.getType());

        user->inventoryHolding.decCount((rightClick) ? 1 : addCount);
      }
    }

  }
  else if (user->inventoryHolding.getType() == -1)
  {
    //If accessing crafting output slot, remove from input!
    if (slotItem->getType() != -1 && (windowID == WINDOW_WORKBENCH || windowID == WINDOW_PLAYER) && slot == 0)
    {
      user->inventoryHolding.setType(slotItem->getType());
      user->inventoryHolding.setCount(slotItem->getCount());
      user->inventoryHolding.setHealth(slotItem->getHealth());

      if (windowID == WINDOW_WORKBENCH)
      {
        for (uint8_t workbenchSlot = 1; workbenchSlot < 10; workbenchSlot++)
        {
          if (currentInventory->workbench[workbenchSlot].getType() != -1)
          {
            currentInventory->workbench[workbenchSlot].decCount();

            setSlot(user, windowID, workbenchSlot, currentInventory->workbench[workbenchSlot].getType(),
                    currentInventory->workbench[workbenchSlot].getCount(),
                    currentInventory->workbench[workbenchSlot].getHealth());
          }
        }
        workbenchCrafting = true;
      }
      else
      {
        for (uint8_t playerSlot = 1; playerSlot < 5; playerSlot++)
        {
          if (user->inv[playerSlot].getType() != -1)
          {
            user->inv[playerSlot].decCount();
          }
        }
        playerCrafting = true;
      }
    }
    else
    {
      user->inventoryHolding.setType(slotItem->getType());
      user->inventoryHolding.setHealth(slotItem->getHealth());
      user->inventoryHolding.setCount(slotItem->getCount());
      if (rightClick == 1)
      {
        user->inventoryHolding.decCount(slotItem->getCount() >> 1);
      }

      slotItem->decCount(user->inventoryHolding.getCount());
      if (slotItem->getCount() == 0)
      {
        slotItem->setHealth(0);
        slotItem->setType(-1);
      }
    }
  }
Exemplo n.º 17
0
void MapGen::ExpandBeaches(int x, int z, int map) 
{
  sChunk *chunk = Mineserver::get()->map(map)->chunks.getChunk(blockToChunk(x),blockToChunk(z));
  int beachExtentSqr = (beachExtent + 1) * (beachExtent + 1);
  int xBlockpos = x<<4;
  int zBlockpos = z<<4;
  
  int blockX, blockZ, h;
  uint8_t block = 0;
  uint8_t meta = 0;
  
  for(int bX = 0; bX < 16; bX++) 
  {
    for(int bZ = 0; bZ < 16; bZ++) 
    {
      blockX = xBlockpos+bX;
      blockZ = zBlockpos+bZ;

      h = heightmap[(bZ<<4)+bX];

      if(h < 0) 
        continue;

      bool found = false;
      for(int dx = -beachExtent; !found && dx <= beachExtent; dx++) 
      {
        for(int dz = -beachExtent; !found && dz <= beachExtent; dz++) 
        {
          for(int dh = -beachHeight; !found && dh <= 0; dh++) 
          {
            if(dx * dx + dz * dz + dh * dh > beachExtentSqr) 
              continue;

            int xx = bX + dx;
            int zz = bZ + dz;
            int hh = h + dh;
            if(xx < 0 || xx >= 15 || zz < 0 || zz >= 15 || hh < 0 || hh >= 127 ) 
              continue;

            //ToDo: add getBlock!!
            if( block == BLOCK_WATER || block == BLOCK_STATIONARY_WATER ) 
            {
              found = true;
              break;
            }
          }
        }
      }
      if(found) 
      {
        Mineserver::get()->map(map)->sendBlockChange(blockX, h, blockZ, BLOCK_SAND, 0);
        Mineserver::get()->map(map)->setBlock(blockX, h, blockZ, BLOCK_SAND, 0);

        Mineserver::get()->map(map)->getBlock(blockX, h-1, blockZ, &block, &meta);

        if( h > 0 && block == BLOCK_DIRT )
        {
          Mineserver::get()->map(map)->sendBlockChange(blockX, h-1, blockZ, BLOCK_SAND, 0);
          Mineserver::get()->map(map)->setBlock(blockX, h-1, blockZ, BLOCK_SAND, 0);
        }
      }
    }
  }
}
Exemplo n.º 18
0
int PacketHandler::change_sign(User* user)
{
  if (!user->buffer.haveData(16))
  {
    return PACKET_NEED_MORE_DATA;
  }
  int32_t x, z;
  int16_t y;
  std::string strings1, strings2, strings3, strings4;

  user->buffer >> x >> y >> z;

  if (!user->buffer.haveData(8))
  {
    return PACKET_NEED_MORE_DATA;
  }
  user->buffer >> strings1;
  if (!user->buffer.haveData(6))
  {
    return PACKET_NEED_MORE_DATA;
  }
  user->buffer >> strings2;
  if (!user->buffer.haveData(4))
  {
    return PACKET_NEED_MORE_DATA;
  }
  user->buffer >> strings3;
  if (!user->buffer.haveData(2))
  {
    return PACKET_NEED_MORE_DATA;
  }
  user->buffer >> strings4;

  //ToDo: Save signs!
  signDataPtr newSign(new signData);
  newSign->x = x;
  newSign->y = y;
  newSign->z = z;
  newSign->text1 = strings1;
  newSign->text2 = strings2;
  newSign->text3 = strings3;
  newSign->text4 = strings4;

  sChunk* chunk = ServerInstance->map(user->pos.map)->getChunk(blockToChunk(x), blockToChunk(z));

  if (chunk != NULL)
  {
    //Check if this sign data already exists and remove
    chunk->signs.erase(std::remove_if(chunk->signs.begin(), chunk->signs.end(), DataFinder<signData>(x,y,z)), chunk->signs.end());

    // Insert new sign
    chunk->signs.push_back(newSign);

    //Send sign packet to everyone
    Packet pkt;
    pkt << (int8_t)PACKET_SIGN << x << y << z;
    pkt << strings1 << strings2 << strings3 << strings4;
    user->sendAll(pkt);
  }

  LOG2(INFO, "Sign: " + strings1 + strings2 + strings3 + strings4);

  //No need to do anything
  user->buffer.removePacket();
  return PACKET_OK;
}
Exemplo n.º 19
0
bool User::updatePos(double x, double y, double z, double stance)
{
  if(nick.size() && logged)
  {
    //Do we send relative or absolute move values
    if(0)  //abs(x-this->pos.x)<127
           //&& abs(y-this->pos.y)<127
           //&& abs(z-this->pos.z)<127)
    {
      uint8 movedata[8];
      movedata[0] = 0x1f; //Relative move
      putSint32(&movedata[1], (sint32)this->UID);
      movedata[5] = (char)(x-this->pos.x);
      movedata[6] = (char)(y-this->pos.y);
      movedata[7] = (char)(z-this->pos.z);
      this->sendOthers(&movedata[0], 8);
    }
    else
    {
      this->pos.x      = x;
      this->pos.y      = y;
      this->pos.z      = z;
      this->pos.stance = stance;
      uint8 teleportData[19];
      teleportData[0]  = 0x22; //Teleport
      putSint32(&teleportData[1], this->UID);
      putSint32(&teleportData[5], (int)(this->pos.x*32));
      putSint32(&teleportData[9], (int)(this->pos.y*32));
      putSint32(&teleportData[13], (int)(this->pos.z*32));
      teleportData[17] = (char)this->pos.yaw;
      teleportData[18] = (char)this->pos.pitch;
      this->sendOthers(&teleportData[0], 19);
    }

    //Check if there are items in this chunk!
    sint32 chunk_x = blockToChunk((sint32)x);
    sint32 chunk_z = blockToChunk((sint32)z);
    uint32 chunkHash;
    Map::get().posToId(chunk_x, chunk_z, &chunkHash);
    if(Map::get().mapItems.count(chunkHash))
    {
      //Loop through items and check if they are close enought to be picked up
      for(sint32 i = Map::get().mapItems[chunkHash].size()-1; i >= 0; i--)
      {
        //No more than 2 blocks away
        if(abs((sint32)x-Map::get().mapItems[chunkHash][i]->pos.x()/32) < 2 &&
           abs((sint32)z-Map::get().mapItems[chunkHash][i]->pos.z()/32) < 2 &&
           abs((sint32)y-Map::get().mapItems[chunkHash][i]->pos.y()/32) < 2)
        {
          //Dont pickup own spawns right away
          if(Map::get().mapItems[chunkHash][i]->spawnedBy != this->UID ||
             Map::get().mapItems[chunkHash][i]->spawnedAt+2 < time(0))
          {
            //Check player inventory for space!
            if(checkInventory(Map::get().mapItems[chunkHash][i]->item,
                              Map::get().mapItems[chunkHash][i]->count))
            {
              //Send player collect item packet
              uint8 *packet = new uint8[9];
              packet[0] = PACKET_COLLECT_ITEM;
              putSint32(&packet[1], Map::get().mapItems[chunkHash][i]->EID);
              putSint32(&packet[5], this->UID);
        buffer.addToWrite(packet, 9);

              //Send everyone destroy_entity-packet
              packet[0] = PACKET_DESTROY_ENTITY;
              putSint32(&packet[1], Map::get().mapItems[chunkHash][i]->EID);
              //ToDo: Only send users in range
              this->sendAll(packet, 5);

              packet[0] = PACKET_ADD_TO_INVENTORY;
              putSint16(&packet[1], Map::get().mapItems[chunkHash][i]->item);
              packet[3] = Map::get().mapItems[chunkHash][i]->count;
              putSint16(&packet[4], Map::get().mapItems[chunkHash][i]->health);

        buffer.addToWrite(packet, 6);

              //We're done, release packet memory
              delete[] packet;


              Map::get().items.erase(Map::get().mapItems[chunkHash][i]->EID);
              delete Map::get().mapItems[chunkHash][i];
              Map::get().mapItems[chunkHash].erase(Map::get().mapItems[chunkHash].begin()+i);
            }
          }
        }
      }
    }


    //Chunk position changed, check for map updates
    if((int)(x/16) != curChunk.x() || (int)(z/16) != curChunk.z())
    {
      //This is not accurate chunk!!
      curChunk.x() = (int)(x/16);
      curChunk.z() = (int)(z/16);

      for(int mapx = -viewDistance+curChunk.x(); mapx <= viewDistance+curChunk.x(); mapx++)
      {
        for(int mapz = -viewDistance+curChunk.z(); mapz <= viewDistance+curChunk.z(); mapz++)
        {
          addQueue(mapx, mapz);
        }
      }

      for(unsigned int i = 0; i < mapKnown.size(); i++)
      {
        //If client has map data more than viesDistance+1 chunks away, remove it
        if(mapKnown[i].x() < curChunk.x()-viewDistance-1 ||
           mapKnown[i].x() > curChunk.x()+viewDistance+1 ||
           mapKnown[i].z() < curChunk.z()-viewDistance-1 ||
           mapKnown[i].z() > curChunk.z()+viewDistance+1)
          addRemoveQueue(mapKnown[i].x(), mapKnown[i].z());
      }
    }
  }

  this->pos.x      = x;
  this->pos.y      = y;
  this->pos.z      = z;
  this->pos.stance = stance;
  return true;
}
Exemplo n.º 20
0
int PacketHandler::complex_entities(User *user)
{
  if(user->buffer.size() < 12)
    return PACKET_NEED_MORE_DATA;

  int curpos = 0;
  unsigned int i;
  uint8 intArray[4];
  uint8 shortArray[2];

  std::copy(user->buffer.begin()+curpos, user->buffer.begin()+curpos+4, intArray);
  int x = getSint32(&intArray[0]);
  curpos += 4;
  std::copy(user->buffer.begin()+curpos, user->buffer.begin()+curpos+2, shortArray);
  int y = getSint16(&shortArray[0]);
  curpos += 2;
  std::copy(user->buffer.begin()+curpos, user->buffer.begin()+curpos+4, intArray);
  int z = getSint32(&intArray[0]);
  curpos += 4;

  std::copy(user->buffer.begin()+curpos, user->buffer.begin()+curpos+2, shortArray);
  int len = getSint16(&shortArray[0]);
  curpos += 2;

  // Wait for whole message
  if(user->buffer.size() < (unsigned int)curpos+len)
    return PACKET_NEED_MORE_DATA;

  //ToDo: check len
  uint8 *buffer = new uint8[len];
  for(i = 0; i < (uint32)len; i++)
  {
    buffer[i] = user->buffer[curpos+i];
  }
  curpos += len;

  user->buffer.erase(user->buffer.begin(), user->buffer.begin()+curpos);

  uint8 block, meta;
  Map::get().getBlock(x, y, z, &block, &meta);

  //We only handle chest for now
  if(block != BLOCK_CHEST)
  {
    delete[] buffer;
    return curpos;
  }


  //Calculate uncompressed size and allocate memory
  uLongf uncompressedSize   = ALLOCATE_NBTFILE; //buffer[len-3] + (buffer[len-2]<<8) + (buffer[len-1]<<16) + (buffer[len]<<24);
  uint8 *uncompressedBuffer = new uint8[uncompressedSize];
  
  //Initialize zstream to handle gzip format
  z_stream zstream;
  zstream.zalloc    = (alloc_func)0;
  zstream.zfree     = (free_func)0;
  zstream.opaque    = (voidpf)0;
  zstream.next_in   = buffer;
  zstream.next_out  = uncompressedBuffer;
  zstream.avail_in  = len;
  zstream.avail_out = uncompressedSize;
  zstream.total_in  = 0;
  zstream.total_out = 0;
  zstream.data_type = Z_BINARY;
  inflateInit2(&zstream, 1+MAX_WBITS);
  //Uncompress
  if(/*int state=*/inflate(&zstream, Z_FULL_FLUSH)!=Z_OK)
  {
      inflateEnd(&zstream);
  }
  //Get size
  uncompressedSize  = zstream.total_out;
  
  //Push data to NBT struct
  NBT_struct newObject;
  TAG_Compound(uncompressedBuffer, &newObject, true);

  //These are not needed anymore
  delete[] buffer;
  delete[] uncompressedBuffer;

  //Get chunk position
  int block_x = blockToChunk(x);
  int block_z = blockToChunk(z);
  uint32 chunkID;

  NBT_struct *theEntity = 0;


  //Load map
  if(Map::get().loadMap(block_x, block_z))
  {
    Map::get().posToId(block_x, block_z, &chunkID);
    NBT_struct mapData = Map::get().maps[chunkID];

    //Try to find entitylist from the chunk
    NBT_list *entitylist = get_NBT_list(&mapData, "TileEntities");

    //If list exists
    if(entitylist)
    {
      //Verify list type
      if(entitylist->tagId != TAG_COMPOUND)
      {
        //If wrong type, recreate
        freeNBT_list(entitylist);
        for(i = 0; i < mapData.lists.size(); i++)
        {
          if(mapData.lists[i].name == "TileEntities")
          {
            //Destroy old list
            freeNBT_list(&mapData.lists[i]);
            mapData.lists.erase(mapData.lists.begin()+i);
            break;
          }
        }
        
        //New list
        NBT_list newlisting;  
        newlisting.name   = "TileEntities";
        newlisting.tagId  = TAG_COMPOUND;
        newlisting.length = 0;
        mapData.lists.push_back(newlisting);

        entitylist = get_NBT_list(&mapData, "TileEntities");
      }

      NBT_struct **entities = (NBT_struct **)entitylist->items;
      bool entityExists     = false;
      int existingID        = -1;

      //Search for mathing entity in the list
      for(int i = 0; i < entitylist->length; i++)
      {
        NBT_struct *entity = entities[i];
        std::string id;

        //Get ID
        if(get_NBT_value(entity, "id", &id))
        {
          int entity_x, entity_y, entity_z;
          if(!get_NBT_value(entity, "x", &entity_x) ||
             !get_NBT_value(entity, "y", &entity_y) ||
             !get_NBT_value(entity, "z", &entity_z))
          {
            continue;
          }

          //Check for mathing blocktype and ID
          if(block == BLOCK_CHEST && id == "Chest")
          {
            if(x == entity_x && y == entity_y && z == entity_z)
            {
              entityExists = true;
              theEntity    = entity;
              existingID   = i;
              break;
            }
          }
        }
      } //End For entitylist

      //Generate struct
      theEntity = new NBT_struct;
      NBT_value value;

      //Push ID
      value.type  = TAG_STRING;
      value.name  = "id";
      std::string *name =  new std::string;
      value.value = (void *)name;
      *(std::string *)value.value = "Chest";
      theEntity->values.push_back(value);

      //Position
      value.type  = TAG_INT;
      value.name  = "x";
      value.value = (void *)new int;
      *(int *)value.value = x;
      theEntity->values.push_back(value);

      value.name  = "y";
      value.value = (void *)new int;
      *(int *)value.value = y;
      theEntity->values.push_back(value);

      value.name  = "z";
      value.value = (void *)new int;
      *(int *)value.value = z;
      theEntity->values.push_back(value);

      //Put special chest items
      if(block == BLOCK_CHEST)
      {
        NBT_list *newlist = get_NBT_list(&newObject, "Items");
        if(!newlist)
        {
          //std::cout << "Items not found!" << std::endl;
          return curpos;
        }
        NBT_list itemlist;
        itemlist.name   = "Items";
        itemlist.tagId  = TAG_COMPOUND;
        itemlist.length = newlist->length;
        itemlist.items  = (void **)new NBT_struct *[itemlist.length];

        NBT_struct **structlist = (NBT_struct **)itemlist.items;
        for(int i = 0; i < itemlist.length; i++)
        {
          structlist[i]        = new NBT_struct;
          char type_char;
          sint16 type_sint16;

          //Generate struct
          value.type             = TAG_BYTE;
          value.name             = "Count";          
          get_NBT_value((NBT_struct *)((NBT_struct **)newlist->items)[i], "Count", &type_char);
          value.value            = (void *)new char;
          *(char *)value.value   = type_char;
          structlist[i]->values.push_back(value);

          value.type             = TAG_BYTE;
          value.name             = "Slot";
          get_NBT_value((NBT_struct *)((NBT_struct **)newlist->items)[i], "Slot", &type_char);
          value.value            = (void *)new char;
          *(char *)value.value   = type_char;
          structlist[i]->values.push_back(value);

          value.type             = TAG_SHORT;
          value.name             = "Damage";          
          get_NBT_value((NBT_struct *)((NBT_struct **)newlist->items)[i], "Damage", &type_sint16);
          value.value            = (void *)new sint16;
          *(sint16 *)value.value = type_sint16;
          structlist[i]->values.push_back(value);

          value.type             = TAG_SHORT;
          value.name             = "id";
          get_NBT_value((NBT_struct *)((NBT_struct **)newlist->items)[i], "id", &type_sint16);
          value.value            = (void *)new sint16;
          *(sint16 *)value.value = type_sint16;
          structlist[i]->values.push_back(value);
        }

        theEntity->lists.push_back(itemlist);
      }
      
      //If entity doesn't exist in the list, resize the list to fit it in
      if(!entityExists)
      {
        
        //ToDo: try this!
        NBT_struct **newlist = new NBT_struct *[entitylist->length+1];
        NBT_struct **oldlist = (NBT_struct **)entitylist->items;
        uint8 *structbuffer  = new uint8[ALLOCATE_NBTFILE];        
        for(int i = 0; i < entitylist->length; i++)
        {
          newlist[i] = new NBT_struct;
          dumpNBT_struct(oldlist[i],structbuffer);
          TAG_Compound(structbuffer, newlist[i],true);
          freeNBT_struct(oldlist[i]);
          oldlist[i] = NULL;
        }
        
        delete [] structbuffer;
        entitylist->length++;
        entitylist->items = (void **)newlist;
        delete [] (NBT_struct **)oldlist;
        newlist[entitylist->length-1] = theEntity;
        
      }
      //If item exists, replace the old with the new
      else
      {
        //Destroy old entitylist
        NBT_struct **oldlist = (NBT_struct **)entitylist->items;
        freeNBT_struct(oldlist[existingID]);
        //Replace with the new
        oldlist[existingID]  = theEntity;
      }

      //Mark chunk as changed
      Map::get().mapChanged[chunkID] = true;
      
    } //If entity exists
  } //If loaded map

  //Send complex entity packet to others
  if(theEntity)
  {
    uint8 *structdump = new uint8[ALLOCATE_NBTFILE];
    uint8 *packetData = new uint8[ALLOCATE_NBTFILE];
    int dumped        = dumpNBT_struct(theEntity, structdump);
    uLongf written    = ALLOCATE_NBTFILE;

    z_stream zstream2;
    zstream2.zalloc    = Z_NULL;
    zstream2.zfree     = Z_NULL;
    zstream2.opaque    = Z_NULL;
    zstream2.next_out  = &packetData[13];
    zstream2.next_in   = structdump;
    zstream2.avail_in  = dumped;
    zstream2.avail_out = written;
    zstream2.total_out = 0;
    zstream2.total_in  = 0;
    deflateInit2(&zstream2, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15+MAX_WBITS, 8,
                 Z_DEFAULT_STRATEGY);

    if(int state=deflate(&zstream2,Z_FULL_FLUSH)!=Z_OK)
    {
      std::cout << "Error in deflate: " << state << std::endl;
      deflateEnd(&zstream2);
    }
    else
    {
      written = zstream2.total_out;
      packetData[0] = 0x3b; //Complex Entities
      putSint32(&packetData[1],x);
      putSint16(&packetData[5],y);
      putSint32(&packetData[7],z);
      putSint16(&packetData[11], (sint16)written);
      user->sendAll((uint8 *)&packetData[0], 13+written);
    }

    delete [] packetData;
    delete [] structdump;
  }





  return curpos;
}
Exemplo n.º 21
0
int PacketHandler::change_sign(User *user)
{
  if(!user->buffer.haveData(16))
    return PACKET_NEED_MORE_DATA;
  int32_t x,z;
  int16_t y;
  std::string strings1,strings2,strings3,strings4;

  user->buffer >> x >> y >> z;

  if(!user->buffer.haveData(8))
    return PACKET_NEED_MORE_DATA;
  user->buffer >> strings1;
  if(!user->buffer.haveData(6))
    return PACKET_NEED_MORE_DATA;
  user->buffer >> strings2;
  if(!user->buffer.haveData(4))
    return PACKET_NEED_MORE_DATA;
  user->buffer >> strings3;
  if(!user->buffer.haveData(2))
    return PACKET_NEED_MORE_DATA;
  user->buffer >> strings4;

  //ToDo: Save signs!
  signData *newSign = new signData;
  newSign->x = x;
  newSign->y = y;
  newSign->z = z;
  newSign->text1 = strings1;
  newSign->text2 = strings2;
  newSign->text3 = strings3;
  newSign->text4 = strings4;

  sChunk* chunk = Mineserver::get()->map(user->pos.map)->chunks.getChunk(blockToChunk(x),blockToChunk(z));

  if(chunk != NULL)
  {
    //Check if this sign data already exists and remove
    for(uint32_t i = 0; i < chunk->signs.size(); i++)
    {
      if(chunk->signs[i]->x == x && 
         chunk->signs[i]->y == y && 
         chunk->signs[i]->z == z)
      {
        //Erase existing data
        delete chunk->signs[i];
        chunk->signs.erase(chunk->signs.begin()+i);
        break;
      }
    }
    chunk->signs.push_back(newSign);

    //Send sign packet to everyone
    Packet pkt;
    pkt << (int8_t)PACKET_SIGN << x << y << z;
    pkt << strings1 << strings2 << strings3 << strings4;
    user->sendAll((uint8_t *)pkt.getWrite(), pkt.getWriteLen());
  }

  Mineserver::get()->logger()->log(LogType::LOG_INFO, "Packets", "Sign: " + strings1 + strings2 + strings3 + strings4);

  //No need to do anything
  user->buffer.removePacket();
  return PACKET_OK;
}