diff --git a/.gitignore b/.gitignore index b7ed972..3749a9d 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,8 @@ build/ ### VS Code ### .vscode/ +last.log + ### Mac OS ### .DS_Store /cache/ diff --git a/src/main/java/com/alterdekim/game/component/GameServer.java b/src/main/java/com/alterdekim/game/component/GameServer.java index 80af279..e151983 100644 --- a/src/main/java/com/alterdekim/game/component/GameServer.java +++ b/src/main/java/com/alterdekim/game/component/GameServer.java @@ -277,4 +277,8 @@ public class GameServer { this.deleteSelf(playerId, this.players.get(playerId).getLocationId()); this.players.remove(playerId); } + + public int getPlayersCount() { + return this.players.size(); + } } \ No newline at end of file diff --git a/src/main/java/com/alterdekim/game/component/StartUpListener.java b/src/main/java/com/alterdekim/game/component/StartUpListener.java index aafd9a4..b7d49c1 100644 --- a/src/main/java/com/alterdekim/game/component/StartUpListener.java +++ b/src/main/java/com/alterdekim/game/component/StartUpListener.java @@ -16,6 +16,7 @@ import com.alterdekim.game.repository.BodyPartRepository; import com.alterdekim.game.repository.SmileRepository; import com.alterdekim.game.service.*; import com.alterdekim.game.storage.StorageProperties; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.javatuples.Pair; import org.springframework.beans.factory.annotation.Autowired; @@ -38,6 +39,9 @@ public class StartUpListener { private static final String ADMIN_USERNAME = "admin"; + @Getter + private long startTime; + @Autowired private ServerConfig config; @@ -139,6 +143,7 @@ public class StartUpListener { @EventListener public void onApplicationEvent(ContextRefreshedEvent event) { + this.startTime = System.currentTimeMillis(); // todo: compile other swf's if( userService.findByUsername(ADMIN_USERNAME) != null ) { diff --git a/src/main/java/com/alterdekim/game/controller/ApiController.java b/src/main/java/com/alterdekim/game/controller/ApiController.java new file mode 100644 index 0000000..47e32a1 --- /dev/null +++ b/src/main/java/com/alterdekim/game/controller/ApiController.java @@ -0,0 +1,72 @@ +package com.alterdekim.game.controller; + +import com.alterdekim.game.component.GameServer; +import com.alterdekim.game.component.StartUpListener; +import com.alterdekim.game.service.UserService; +import com.alterdekim.game.utils.DateUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.time.Duration; +import java.time.temporal.ChronoUnit; +import java.util.Date; + +@Slf4j +@RestController +@RequestMapping("/api") +public class ApiController { + @Autowired + private Environment env; + + @Autowired + private StartUpListener startUpListener; + + @Autowired + private GameServer gameServer; + + @Autowired + private UserService userService; + + @GetMapping("/get_dashboard_logs") + public ResponseEntity getLogs() { + try { + Path logFile = Paths.get(env.getProperty("logging.file.name")); + RandomAccessFile file = new RandomAccessFile(logFile.toFile(), "r"); + int n = 2048; + file.seek(logFile.toFile().length() - n); + byte[] b = new byte[n]; + file.read(b, 0, n); + return ResponseEntity.ok(b); + } catch (IOException e) { + log.error("getLogs error: {}", e.getMessage()); + return ResponseEntity.badRequest().build(); + } + } + + @GetMapping("/get_uptime") + public ResponseEntity getUpTime() { + return ResponseEntity.ok( + DateUtils.prettyPrint(Duration.of(System.currentTimeMillis() - startUpListener.getStartTime(), ChronoUnit.MILLIS)) + ); + } + + @GetMapping("/get_players_online") + public ResponseEntity getPlayersOnline() { + return ResponseEntity.ok(gameServer.getPlayersCount()); + } + + @GetMapping("/get_users_count") + public ResponseEntity getUsersCount() { + return ResponseEntity.ok(userService.getUsersCount()); + } +} diff --git a/src/main/java/com/alterdekim/game/controller/FileServerController.java b/src/main/java/com/alterdekim/game/controller/FileServerController.java index ba4377a..e4dd3e3 100644 --- a/src/main/java/com/alterdekim/game/controller/FileServerController.java +++ b/src/main/java/com/alterdekim/game/controller/FileServerController.java @@ -34,6 +34,7 @@ public class FileServerController { case "css" -> MediaType.parseMediaType("text/css"); case "_js" -> MediaType.parseMediaType("text/javascript"); case "img" -> MediaType.parseMediaType("image/jpeg"); + case "svg" -> MediaType.parseMediaType("image/svg+xml"); default -> MediaType.TEXT_PLAIN; }).body(Files.readAllBytes(path)); } catch (Exception e) { diff --git a/src/main/java/com/alterdekim/game/controller/StaticController.java b/src/main/java/com/alterdekim/game/controller/StaticController.java index f7ff0a1..6b63014 100644 --- a/src/main/java/com/alterdekim/game/controller/StaticController.java +++ b/src/main/java/com/alterdekim/game/controller/StaticController.java @@ -14,10 +14,17 @@ import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static com.alterdekim.game.controller.FileServerController.URL_PATH; @Slf4j @Controller @@ -43,7 +50,23 @@ public class StaticController { } @GetMapping("/panel") - public String panel() { + public String panel(Model model, @RequestParam(value = "section", defaultValue = "Dashboard") PanelSection section) { + model.addAttribute("section", section.name()); + model.addAttribute("script", "/" + URL_PATH + "/_js/" + section.name().toLowerCase() + ".js"); return "panel"; } + + public enum PanelSection { + Dashboard, + Locations, + Games, + Preloaders, + Users, + Banlist, + Cache, + Goods, + Items, + Actions, + Support + } } diff --git a/src/main/java/com/alterdekim/game/repository/UserRepository.java b/src/main/java/com/alterdekim/game/repository/UserRepository.java index 725e8b6..1e3d674 100644 --- a/src/main/java/com/alterdekim/game/repository/UserRepository.java +++ b/src/main/java/com/alterdekim/game/repository/UserRepository.java @@ -2,10 +2,14 @@ package com.alterdekim.game.repository; import com.alterdekim.game.entity.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @Repository public interface UserRepository extends JpaRepository { User findByUsername(String username); + + @Query(value = "SELECT COUNT(u) FROM User u") + Long findUsersCount(); } diff --git a/src/main/java/com/alterdekim/game/security/SpringSecurity.java b/src/main/java/com/alterdekim/game/security/SpringSecurity.java index c7de4c1..927bdd6 100644 --- a/src/main/java/com/alterdekim/game/security/SpringSecurity.java +++ b/src/main/java/com/alterdekim/game/security/SpringSecurity.java @@ -35,7 +35,8 @@ public class SpringSecurity { authorize .requestMatchers("/").permitAll() .requestMatchers("/login").permitAll() - .requestMatchers("/panel").hasAnyAuthority("ROLE_USER") // todo: make several roles and separate them + .requestMatchers("/panel").permitAll() // todo: make several roles and separate them + .requestMatchers("/api/**").permitAll() // todo: make several roles and separate them .requestMatchers("/main").hasAnyAuthority("ROLE_USER") .requestMatchers("/"+ FileServerController.URL_PATH +"/**").permitAll() .requestMatchers("/ConstructorACHandler.ashx").permitAll() diff --git a/src/main/java/com/alterdekim/game/service/UserService.java b/src/main/java/com/alterdekim/game/service/UserService.java index 7079f48..620cb44 100644 --- a/src/main/java/com/alterdekim/game/service/UserService.java +++ b/src/main/java/com/alterdekim/game/service/UserService.java @@ -261,4 +261,8 @@ public class UserService { public void removeUser(long userId) { this.userRepository.deleteById(userId); } + + public Long getUsersCount() { + return this.userRepository.findUsersCount(); + } } diff --git a/src/main/java/com/alterdekim/game/utils/DateUtils.java b/src/main/java/com/alterdekim/game/utils/DateUtils.java new file mode 100644 index 0000000..e29ddba --- /dev/null +++ b/src/main/java/com/alterdekim/game/utils/DateUtils.java @@ -0,0 +1,12 @@ +package com.alterdekim.game.utils; + +import java.time.Duration; + +public class DateUtils { + public static String prettyPrint(Duration duration) { + return duration.toString() + .substring(2) + .replaceAll("(\\d[HMS])(?!$)", "$1 ") + .toLowerCase(); + } +} diff --git a/src/main/resources/templates/panel.html b/src/main/resources/templates/panel.html index 2b9d807..265be2d 100644 --- a/src/main/resources/templates/panel.html +++ b/src/main/resources/templates/panel.html @@ -1,40 +1,78 @@ - - + + + + + WhimsyWorld - +
- -
- -
-

-

Where god thrive with code.

-

We are world's #1 idea building company 💡 coding all night long 👨🏻‍💻

-
-

Get QuoteGet Started →

+
+ +
-
+
+ +
+ + +

Preloaders

+
+ +

Dashboard

+
+
+

Uptime

+

+
+
+

Online

+

+
+
+

Users count

+

+
+
+

Logs

+
+
+
+
+
+ \ No newline at end of file