Esempio n. 1
0
func DropItem(x, y, z float64, itemType int16, data uint8) {
	c := storage.GetChunkContaining(int32(x), int32(z))
	defer storage.ReleaseChunkContaining(int32(x), int32(z))

	ent := chunk.NewItemDrop(x, y, z, &player.InventoryItem{Type: itemType, Damage: int16(data), Count: 1})
	c.SpawnEntity(chunk.Entity(ent))

	var buf bytes.Buffer
	ent.SpawnPacket(&buf)
	SendToAllNearChunk(c.X, c.Z, protocol.BakedPacket(buf.Bytes()))
}
Esempio n. 2
0
func EntitySpawnPacket(ent Entity) protocol.Packet {
	var buf bytes.Buffer
	ent.SpawnPacket(&buf)
	return protocol.BakedPacket(buf.Bytes())
}
Esempio n. 3
0
func dispatchPacket(p Player, packet protocol.Packet) {
	switch pkt := packet.(type) {
	case protocol.KeepAlive:
		return
	case protocol.LoginRequest:
		if pkt.EntityID != protocol.PROTOCOL_VERSION {
			p.SendPacketSync(protocol.Kick{Reason: "Your minecraft version isn't the one I expected."})
			return
		}
		if pkt.Username != p.Username() {
			p.SendPacketSync(protocol.Kick{Reason: fmt.Sprint("Your username doesn't match the one you told me earlier. (", pkt.Username, " != ", p.Username(), ")")})
			return
		}
		req, _ := http.Get(fmt.Sprintf("http://session.minecraft.net/game/checkserver.jsp?user=%s&serverId=%x", p.Username(), p.getLoginToken()))
		buf := make([]byte, 3)
		req.Body.Read(buf)
		if string(buf) == "YES" {
			p.(*_player).authenticated = true
			if OnlinePlayerCount >= config.Config.NumSlots {
				p.SendPacketSync(protocol.Kick{Reason: "Server is full!"})
				return
			}
			OnlinePlayerCount++
			p.SendPacketSync(protocol.LoginRequest{
				EntityID:   p.ID(),
				LevelType:  "default",
				ServerMode: protocol.Survival,
				Dimension:  protocol.Overworld,
				Difficulty: protocol.Peaceful,
				MaxPlayers: uint8(config.Config.NumSlots), // If you have more than 255 slots, I applaud you.
			})
			p.(*_player).stored = storage.GetPlayer(p.Username())
			if p.(*_player).stored.Abilities.InstaBuild {
				p.SetGameMode(protocol.Creative)
			} else {
				p.SetGameMode(protocol.Survival)
			}
			p.sendWorldData()
			log.Print(p.Username(), " connected.")
			if customLoginMessage(p) != "" {
				SendToAll(protocol.Chat{Message: fmt.Sprintf(customLoginMessage(p), formatUsername(p))})
			} else {
				SendToAll(protocol.Chat{Message: fmt.Sprintf("%s connected.", formatUsername(p))})
			}
			var otherPlayers bytes.Buffer
			for _, player := range players {
				if player.Authenticated() && player != p {
					player.SpawnPacket(&otherPlayers)
				}
			}
			p.SendPacketSync(protocol.BakedPacket(otherPlayers.Bytes()))
			SendToAllExcept(p, EntitySpawnPacket(p))
		} else {
			p.SendPacketSync(protocol.Kick{Reason: "Failed to verify username!"})
		}
	case protocol.Chat:
		if pkt.Message[0] == '/' {
			handleCommand(p, string(pkt.Message[1:]))
		} else {
			log.Printf("<%s> %s", p.Username(), pkt.Message)
			SendToAll(protocol.Chat{Message: fmt.Sprintf("%s %s", bracketUsername(p), pkt.Message)})
		}
	case protocol.Handshake:
		data := strings.Split(pkt.Data, ";")
		p.setUsername(data[0])
		p.SendPacketSync(protocol.Handshake{fmt.Sprintf("%016x", p.getLoginToken())})
	case protocol.Flying:
		// TODO
	case protocol.PlayerPosition:
		p.SendPosition(pkt.X, pkt.Y1, pkt.Z)
		// TODO: validation
	case protocol.PlayerLook:
		p.SendAngles(pkt.Yaw, pkt.Pitch)
	case protocol.PlayerPositionLook:
		p.SendAngles(pkt.Yaw, pkt.Pitch)
		p.SendPosition(pkt.X, pkt.Y1, pkt.Z)
		// TODO: validation
	case protocol.PlayerDigging:
		switch pkt.Status {
		case 0:
			if p.(*_player).stored.Abilities.InstaBuild {
				if GetBlockAt(pkt.X, int32(pkt.Y), pkt.Z) != block.Bedrock {
					PlayerSetBlockAt(pkt.X, int32(pkt.Y), pkt.Z, block.Air, 0)
				}
			}
		case 2:
			blockType := GetBlockAt(pkt.X, int32(pkt.Y), pkt.Z)
			if blockType != block.Bedrock {
				item := blockType.ItemDrop()

				if item != 0 {
					DropItem(float64(pkt.X)+0.5, float64(pkt.Y)+0.5, float64(pkt.Z)+0.5, item, GetBlockDataAt(pkt.X, int32(pkt.Y), pkt.Z))
				}

				PlayerSetBlockAt(pkt.X, int32(pkt.Y), pkt.Z, block.Air, 0)
			}
		}
		// TODO: validation
	case protocol.Animation:
		if pkt.EID == p.ID() && pkt.Animation == 1 {
			SendToAllExcept(p, pkt)
		}
	case protocol.PlayerAbilities:
		p.(*_player).stored.Abilities.Flying = p.(*_player).stored.Abilities.MayFly && pkt.Flying
	case protocol.ServerListPing:
		p.SendPacketSync(protocol.Kick{Reason: fmt.Sprintf("%s§%d§%d", config.Config.ServerDescription, OnlinePlayerCount, config.Config.NumSlots)})
	case protocol.Kick:
		log.Print(p.Username(), " disconnected.")
		SendToAll(protocol.Chat{Message: fmt.Sprintf("%s disconnected.", formatUsername(p))})
	default:
		panic(fmt.Sprintf("%T %v", packet, packet))
	}
}