func (self *Player) gameTick() { ticker := time.NewTicker(PLAYER_TICK_FREQ * time.Millisecond) defer ticker.Stop() for { select { case <-ticker.C: if self.location == nil { continue } now := time.Now().UnixNano() delta := float64((now - self.lastUpdate) / 1000000) if self.velX != 0 || self.velY != 0 { velX, velY := float64(self.velX), float64(self.velY) if velX != 0 && velY != 0 { velX = velX * SQRT1_2 velY = velY * SQRT1_2 } self.x += velX * PLAYER_SPEED * delta self.y += velY * PLAYER_SPEED * delta self.lastUpdate = now } if self.godMode && rand.Intn(3) == 0 { self.outbound <- self.location.GetEvent(events.PARTICLE_MACRO, "0.5 -0.5 godmode 3 local", nil) self.location.Broadcast( self.location.GetEvent(events.PARTICLE_MACRO, "0.5 -0.5 godmode 3 "+self.ID(), self), ) } for _, portal := range self.location.Terrain.Portals { if entities.IsEntityCollidingWithPortal(portal, self) { log.Println("Player in contact with portal") var target string currentCoords := [2]float64{self.x, self.y} destX, destY := portal.DestX, portal.DestY if portal.Target == ".." { target = self.location.ParentID if len(self.coordStack) > 0 { coords := self.coordStack[len(self.coordStack)-1] self.x, self.y = coords[0], coords[1]+1 destX, destY = self.x, self.y self.coordStack = self.coordStack[:len(self.coordStack)-1] } } else if portal.Target == "." { target = self.location.ID() if len(self.coordStack) > 0 { self.coordStack[len(self.coordStack)-1] = currentCoords } self.x, self.y = portal.DestX, portal.DestY } else { target = self.location.ID() + "," + portal.Target self.coordStack = append(self.coordStack, currentCoords) self.x, self.y = portal.DestX, portal.DestY } parent, type_, x, y := regions.GetRegionData(target) self.sendToLocation(parent, type_, x, y, destX, destY) } } if self.effectTTL > 0 { self.effectTTL-- if self.effectTTL == 0 { self.outbound <- self.location.GetEvent(events.EFFECT_CLEAR, "", nil) } } case <-self.closing: self.closing <- true return } } }
func HandleCheat(message string, player *Player) bool { if len(message) == 0 || message[0] != '/' { return false } spl := strings.SplitN(message[1:], " ", 2) // All command have at least two components. if len(spl) < 2 { return false } // All commands must start with a three-letter directive. if len(spl[0]) != 3 { return false } log.Println("Reading cheat code '" + spl[0] + "' with body '" + spl[1] + "'") switch spl[0] { case "get": switch spl[1] { case "#health": sayToPlayer(strconv.Itoa(int(player.GetHealth())), player) return true } case "pan": if spl[1] != "sure" { sayToPlayer("You must be sure.", player) return true } pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) panic("Debug Panic") case "hea": newHealth, err := strconv.ParseInt(spl[1], 10, 0) if err != nil { sayToPlayer("Invalid health", player) return true } player.IncrementHealth(int(newHealth) - int(player.GetHealth())) sayToPlayer("Updating health to "+strconv.Itoa(int(player.GetHealth())), player) return true case "giv": ok, slot := player.inventory.Give(spl[1]) if !ok { sayToPlayer("Item could not be given", player) } else { sayToPlayer("Item is in slot "+strconv.Itoa(slot), player) player.UpdateInventory() } return true case "tel": telSplit := strings.SplitN(spl[1], " ", 3) xPos, err := strconv.ParseUint(telSplit[0], 10, 0) if err != nil { return false } yPos, err := strconv.ParseUint(telSplit[1], 10, 0) if err != nil { return false } player.x = float64(xPos) player.y = float64(yPos) player.velX = 0 player.velY = 0 player.dirX = 0 player.dirY = 0 // If the player is already in the region, don't run sendToLocation if telSplit[2] != player.location.ID() { parentID, type_, x, y := regions.GetRegionData(telSplit[2]) player.sendToLocation(parentID, type_, x, y, float64(xPos), float64(yPos)) // TODO: make sure xPos and yPos are within the region // TODO: warn the user if those coords are hitmapped. } return true case "nam": if safe, _ := regexp.MatchString("^[a-zA-Z0-9 ]+$", spl[1]); !safe { sayToPlayer("Invalid name", player) return true } player.nametag = spl[1] pX, pY := player.BlockingPosition() player.location.Broadcast( player.location.GetEvent( events.ENTITY_UPDATE, fmt.Sprintf( "%s\n%f %f", player.BlockingString(), pX, pY, ), player, ), ) player.outbound_raw <- "epuevt:local\n{\"nametag\":\"" + spl[1] + "\"}" return true case "epu": epuSplit := strings.SplitN(spl[1], " ", 2) if safe, _ := regexp.MatchString("^[a-zA-Z0-9\\.]+$", epuSplit[0]); !safe { sayToPlayer("Invalid entity key", player) return true } if safe, _ := regexp.MatchString("^[a-zA-Z0-9\\._\\-]+$", epuSplit[1]); !safe { sayToPlayer("Invalid entity value", player) return true } pX, pY := player.BlockingPosition() player.location.Broadcast( player.location.GetEvent( events.ENTITY_UPDATE, fmt.Sprintf( "{\"%s\":\"%s\"}\n%f %f", epuSplit[0], epuSplit[1], pX, pY, ), player, ), ) player.outbound_raw <- "epuevt:local\n{\"" + epuSplit[0] + "\":\"" + epuSplit[1] + "\"}" return true case "god": switch spl[1] { case "on": player.godMode = true case "off": player.godMode = false } return true case "efx": player.outbound_raw <- "efxevt:local\n" + spl[1] return true case "efc": player.outbound_raw <- "efcevt:local\n" return true } return false }