func (c *ClientState) MouseAction(button glfw.MouseButton, down bool) { if button == glfw.MouseButtonLeft { c.isLeftDown = down } else if button == glfw.MouseButtonRight && down { e := c.targetEntity() if ne, ok := e.(NetworkComponent); ok { c.network.Write(&protocol.UseEntity{ TargetID: protocol.VarInt(ne.EntityID()), Type: 0, // Interact }) return } if c.playerInventory.Items[c.currentHotbarSlot+invPlayerHotbarOffset] != nil { c.network.Write(&protocol.UseItem{ Hand: 0, }) } pos, b, face, cur := c.targetBlock() if b.Is(Blocks.Air) { return } c.entity.SwingArm() c.network.Write(&protocol.ArmSwing{}) c.network.Write(&protocol.PlayerBlockPlacement{ Location: protocol.NewPosition(pos.X, pos.Y, pos.Z), Face: protocol.VarInt(directionToProtocol(face)), CursorX: byte(cur.X() * 16), CursorY: byte(cur.Y() * 16), CursorZ: byte(cur.Z() * 16), }) } }
func (c *ClientState) armTick() { pos, b, face, _ := c.targetBlock() if c.isLeftDown { c.swingTimer -= c.delta if c.swingTimer < 0 { c.swingTimer = 15 c.entity.SwingArm() c.network.Write(&protocol.ArmSwing{}) e := c.targetEntity() if ne, ok := e.(NetworkComponent); ok { c.network.Write(&protocol.UseEntity{ TargetID: protocol.VarInt(ne.EntityID()), Type: 1, // Attack }) return } if !b.Is(Blocks.Air) { name, vol, pitch := b.DigSound() PlaySoundAt(name, vol, pitch, pos.Vec()) } } if b != c.currentBreakingBlock || pos != c.currentBreakingPos { c.currentBreakingBlock = Blocks.Air.Base c.network.Write(&protocol.PlayerDigging{ Status: 1, // Cancel Location: protocol.NewPosition(pos.X, pos.Y, pos.Z), Face: directionToProtocol(face), }) c.killBreakEntity() } if c.currentBreakingBlock.Is(Blocks.Air) { if math.IsInf(b.Hardness(), 1) { return } c.network.Write(&protocol.PlayerDigging{ Status: 0, // Start Location: protocol.NewPosition(pos.X, pos.Y, pos.Z), Face: directionToProtocol(face), }) c.breakTime = b.Hardness() * 1.5 * 60.0 c.maxBreakTime = c.breakTime c.currentBreakingBlock = b c.currentBreakingPos = pos c.breakEntity = newBlockBreakEntity() c.breakEntity.SetPosition(pos) c.breakEntity.(BlockBreakComponent).Update() } else { c.breakTime -= c.delta if c.breakTime < 0 { c.breakTime = 0 c.currentBreakingBlock = Blocks.Air.Base c.network.Write(&protocol.PlayerDigging{ Status: 2, // Finish Location: protocol.NewPosition(pos.X, pos.Y, pos.Z), Face: directionToProtocol(face), }) chunkMap.SetBlock(Blocks.Air.Base, pos.X, pos.Y, pos.Z) chunkMap.UpdateBlock(pos.X, pos.Y, pos.Z) c.killBreakEntity() name, vol, pitch := b.BreakSound() PlaySoundAt(name, vol, pitch, pos.Vec()) } else { stage := int(9 - math.Min(9, 10*(c.breakTime/c.maxBreakTime))) if stage != c.breakEntity.(BlockBreakComponent).Stage() { c.breakEntity.(BlockBreakComponent).SetStage(stage) c.breakEntity.(BlockBreakComponent).Update() } } } } else if !c.currentBreakingBlock.Is(Blocks.Air) { c.currentBreakingBlock = Blocks.Air.Base c.network.Write(&protocol.PlayerDigging{ Status: 1, // Cancel Location: protocol.NewPosition(pos.X, pos.Y, pos.Z), Face: directionToProtocol(face), }) c.killBreakEntity() } }