longpoll api update, waiting list update, chat update, online status
This commit is contained in:
parent
89fde1afc9
commit
ff0fbe06ac
5
pom.xml
5
pom.xml
@ -75,6 +75,11 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-security</artifactId>
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-collections4</artifactId>
|
||||||
|
<version>4.4</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -1,30 +1,233 @@
|
|||||||
package com.alterdekim.game.component;
|
package com.alterdekim.game.component;
|
||||||
|
|
||||||
import com.alterdekim.game.dto.LongPollResult;
|
import com.alterdekim.game.dto.*;
|
||||||
|
import com.alterdekim.game.entities.Chat;
|
||||||
|
import com.alterdekim.game.entities.Room;
|
||||||
|
import com.alterdekim.game.entities.RoomPlayer;
|
||||||
|
import com.alterdekim.game.entities.User;
|
||||||
|
import com.alterdekim.game.service.*;
|
||||||
|
import com.alterdekim.game.util.Hash;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Getter
|
@Getter
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class LongPoll {
|
public class LongPoll {
|
||||||
|
|
||||||
private final BlockingQueue<LongPollingSession> longPollingQueue = new ArrayBlockingQueue<>(100);
|
private final Integer iterations = 6;
|
||||||
|
|
||||||
@Scheduled(fixedRate = 5000)
|
private final BlockingQueue<LongPollingSession> longPollingQueue = new ArrayBlockingQueue<>(100);
|
||||||
|
private final ConcurrentHashMap<Long, LongPollConfig> map = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserServiceImpl userService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ChatServiceImpl chatService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RoomServiceImpl roomService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RoomPlayerServiceImpl roomPlayerService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private FriendServiceImpl friendService;
|
||||||
|
|
||||||
|
@Scheduled(fixedRate = 3000)
|
||||||
private void longPoll() {
|
private void longPoll() {
|
||||||
|
getLongPollingQueue().removeIf(e -> e.getDeferredResult().isSetOrExpired());
|
||||||
|
roomService.clearEmptyRooms();
|
||||||
|
getMap().keySet().forEach(k -> {
|
||||||
|
if( (System.currentTimeMillis() - getMap().get(k).getLastRequest()) >= 60000 ) getMap().remove(k);
|
||||||
|
});
|
||||||
getLongPollingQueue().forEach(longPollingSession -> {
|
getLongPollingQueue().forEach(longPollingSession -> {
|
||||||
try {
|
try {
|
||||||
longPollingSession.getDeferredResult().setResult(new LongPollResult());
|
if( !map.containsKey(longPollingSession.getUserId())) map.put(longPollingSession.getUserId(), new LongPollConfig(0L,new ArrayList<>(), 0, Hash.rnd(), new ArrayList<>(), System.currentTimeMillis()));
|
||||||
|
LongPollConfig config = map.get(longPollingSession.getUserId());
|
||||||
|
LongPollResult result = process(longPollingSession.getUserId(), config);
|
||||||
|
if( !result.getRooms().isEmpty() )
|
||||||
|
config.setRooms(result.getRooms().stream().filter(r -> r.getAction() == RoomResultState.ADD_CHANGE).map(r -> new RoomResult(r.getId(), r.getPlayerCount(), r.getPlayers())).collect(Collectors.toList()));
|
||||||
|
if( !result.getFriends().isEmpty() )
|
||||||
|
config.setFriends_online(result.getFriends().stream().filter(r -> r.getAction() == FriendState.ADD).map(r -> new UserResult(r.getId(), r.getUsername())).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
config.setSession_pass(config.getSession_pass()+1);
|
||||||
|
|
||||||
|
if( !result.getFriends().isEmpty() || !result.getRooms().isEmpty() || !result.getMessages().isEmpty() || config.getSession_pass() >= iterations) {
|
||||||
|
longPollingSession.getDeferredResult().setResult(result);
|
||||||
|
config.setSession_pass(0);
|
||||||
|
}
|
||||||
|
map.put(longPollingSession.getUserId(), config);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e.getMessage(), e);
|
log.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
getLongPollingQueue().removeIf(e -> e.getDeferredResult().isSetOrExpired());
|
getLongPollingQueue().removeIf(e -> e.getDeferredResult().isSetOrExpired());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private LongPollResult process(Long userId, LongPollConfig config) {
|
||||||
|
userService.updateOnline(userId);
|
||||||
|
|
||||||
|
Integer onlineCount = userService.countByIsOnline();
|
||||||
|
List<Chat> results;
|
||||||
|
List<UserResult> users = new ArrayList<>();
|
||||||
|
List<RoomResult> clientRooms = config.getRooms();
|
||||||
|
List<RoomResultV2> roomResults = new ArrayList<>();
|
||||||
|
List<UserResult> clientFriends = config.getFriends_online();
|
||||||
|
List<FriendResult> friendsResult = new ArrayList<>();
|
||||||
|
|
||||||
|
results = chatService.getAfterLastChatId(config.getLast_chat_id());
|
||||||
|
|
||||||
|
if( !results.isEmpty() ) {
|
||||||
|
users = results.stream()
|
||||||
|
.map(Chat::getUserId)
|
||||||
|
.distinct()
|
||||||
|
.map(l -> userService.findById(l))
|
||||||
|
.map(u -> new UserResult(u.getId(), u.getUsername()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
results = results.stream().peek(c -> {
|
||||||
|
String message = c.getMessage();
|
||||||
|
for (int i = 0; i < message.length(); i++) {
|
||||||
|
if (message.charAt(i) == '@') {
|
||||||
|
int u = message.substring(i).indexOf(' ') + i;
|
||||||
|
String username = message.substring(i + 1, u);
|
||||||
|
User user = userService.findByUsername(username);
|
||||||
|
if (user != null) {
|
||||||
|
Long uid = user.getId();
|
||||||
|
message = message.substring(0, i) + "<a href=\"/profile/" + uid + "\" class=\"chat-history-user\"><span class=\"_nick\">" + username + "</span></a>" + message.substring(u + 1);
|
||||||
|
} else {
|
||||||
|
message = message.substring(0, i) + username + message.substring(u + 1);
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.setMessage(message);
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
if( !clientRooms.isEmpty() ) {
|
||||||
|
List<RoomResult> rooms = roomService.getAllActive().stream()
|
||||||
|
.map( r -> new RoomResult(r.getId(), r.getPlayerCount(), roomPlayerService.findByRoomId(r.getId()).stream()
|
||||||
|
.map(p -> userService.findById(p.getUserId()))
|
||||||
|
.map(p -> new UserResult(p.getId(), p.getUsername()))
|
||||||
|
.collect(Collectors.toList())))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if( !isEqualListRoom(rooms, clientRooms) ) {
|
||||||
|
List<RoomResult> rr = new ArrayList<>(rooms);
|
||||||
|
List<RoomResultV2> resultV2List = new ArrayList<>();
|
||||||
|
for( RoomResult r : clientRooms ) {
|
||||||
|
if( rooms.stream().noneMatch(t -> t.getId().longValue() == r.getId().longValue()) ) {
|
||||||
|
resultV2List.add(new RoomResultV2(RoomResultState.REMOVE, r.getId(), r.getPlayerCount(), r.getPlayers()));
|
||||||
|
} else {
|
||||||
|
RoomResult r1 = rooms.stream().filter( t -> t.getId().longValue() == r.getId().longValue()).findFirst().get();
|
||||||
|
if( !isEqual(r, r1) ) {
|
||||||
|
resultV2List.add(new RoomResultV2(RoomResultState.ADD_CHANGE, r1.getId(), r1.getPlayerCount(), r1.getPlayers()));
|
||||||
|
}
|
||||||
|
rr.remove(r1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for( RoomResult r : rr ) {
|
||||||
|
resultV2List.add(new RoomResultV2(RoomResultState.ADD_CHANGE, r.getId(), r.getPlayerCount(), r.getPlayers()));
|
||||||
|
}
|
||||||
|
roomResults = resultV2List.stream().sorted(Comparator.comparingLong(RoomResultV2::getId)).collect(Collectors.toList());
|
||||||
|
} else {
|
||||||
|
roomResults = new ArrayList<>();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
List<Room> rooms = roomService.getAllActive();
|
||||||
|
roomResults = rooms.stream()
|
||||||
|
.map( r -> new RoomResultV2(RoomResultState.ADD_CHANGE, r.getId(), r.getPlayerCount(), roomPlayerService.findByRoomId(r.getId()).stream()
|
||||||
|
.map(p -> userService.findById(p.getUserId()))
|
||||||
|
.map(p -> new UserResult(p.getId(), p.getUsername()))
|
||||||
|
.collect(Collectors.toList())))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !clientFriends.isEmpty() ) {
|
||||||
|
List<UserResult> userResults = friendService.getFriendsOfUserId(userId)
|
||||||
|
.stream()
|
||||||
|
.map(id -> userService.findById(id))
|
||||||
|
.map(u -> new UserResult(u.getId(), u.getUsername()))
|
||||||
|
.filter(f -> getMap().keySet().stream().anyMatch(l -> l.longValue() == f.getId().longValue()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if( !isEqualListUser(userResults, clientFriends) ) {
|
||||||
|
List<UserResult> urr = new ArrayList<>(userResults);
|
||||||
|
List<FriendResult> fr = new ArrayList<>();
|
||||||
|
for( UserResult r : clientFriends ) {
|
||||||
|
if( userResults.stream().noneMatch(t -> t.getId().longValue() == r.getId().longValue()) ) {
|
||||||
|
fr.add(new FriendResult(FriendState.REMOVE, r.getId(), r.getUsername()));
|
||||||
|
} else {
|
||||||
|
UserResult r1 = userResults.stream().filter( t -> t.getId().longValue() == r.getId().longValue()).findFirst().get();
|
||||||
|
if( !isEqualUser(r, r1) ) {
|
||||||
|
fr.add(new FriendResult(FriendState.ADD, r1.getId(), r1.getUsername()));
|
||||||
|
}
|
||||||
|
urr.remove(r1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for( UserResult r : urr ) {
|
||||||
|
fr.add(new FriendResult(FriendState.ADD, r.getId(), r.getUsername()));
|
||||||
|
}
|
||||||
|
friendsResult = fr.stream().sorted(Comparator.comparingLong(FriendResult::getId)).collect(Collectors.toList());
|
||||||
|
} else {
|
||||||
|
friendsResult = new ArrayList<>();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
friendsResult = friendService.getFriendsOfUserId(userId)
|
||||||
|
.stream()
|
||||||
|
.map(id -> userService.findById(id))
|
||||||
|
.filter(f -> getMap().keySet().stream().anyMatch(l -> l.longValue() == f.getId().longValue()))
|
||||||
|
.map(f -> new FriendResult(FriendState.ADD, f.getId(), f.getUsername()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LongPollResult(onlineCount, results, users, roomResults, friendsResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean isEqual(RoomResult r1, RoomResult r2) {
|
||||||
|
return r1.getId().longValue() == r2.getId().longValue() &&
|
||||||
|
r1.getPlayerCount().intValue() == r2.getPlayerCount().intValue() &&
|
||||||
|
isEqualListUser(r1.getPlayers(), r2.getPlayers());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean isEqualUser(UserResult r1, UserResult r2) {
|
||||||
|
return r1.getId().longValue() == r2.getId().longValue() &&
|
||||||
|
r1.getUsername().equals(r2.getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean isEqualListRoom(List<RoomResult> r1, List<RoomResult> r2) {
|
||||||
|
r1 = r1.stream().sorted(Comparator.comparingLong(RoomResult::getId)).collect(Collectors.toList());
|
||||||
|
r2 = r2.stream().sorted(Comparator.comparingLong(RoomResult::getId)).collect(Collectors.toList());
|
||||||
|
if( r1.size() != r2.size() ) return false;
|
||||||
|
for( int i = 0; i < r1.size(); i++ ) {
|
||||||
|
if( !isEqual(r1.get(i), r2.get(i)) ) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean isEqualListUser(List<UserResult> r1, List<UserResult> r2) {
|
||||||
|
r1 = r1.stream().sorted(Comparator.comparingLong(UserResult::getId)).collect(Collectors.toList());
|
||||||
|
r2 = r2.stream().sorted(Comparator.comparingLong(UserResult::getId)).collect(Collectors.toList());
|
||||||
|
if( r1.size() != r2.size() ) return false;
|
||||||
|
for( int i = 0; i < r1.size(); i++ ) {
|
||||||
|
if( r1.get(i).getId().longValue() != r2.get(i).getId().longValue() ||
|
||||||
|
!r1.get(i).getUsername().equals(r2.get(i).getUsername()) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.alterdekim.game.component;
|
||||||
|
|
||||||
|
import com.alterdekim.game.dto.RoomResult;
|
||||||
|
import com.alterdekim.game.dto.UserResult;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class LongPollConfig {
|
||||||
|
private Long last_chat_id;
|
||||||
|
private List<RoomResult> rooms;
|
||||||
|
private Integer session_pass;
|
||||||
|
private String poll_token;
|
||||||
|
private List<UserResult> friends_online;
|
||||||
|
private Long lastRequest;
|
||||||
|
}
|
@ -7,8 +7,7 @@ import org.springframework.web.context.request.async.DeferredResult;
|
|||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Getter
|
@Getter
|
||||||
|
|
||||||
public class LongPollingSession {
|
public class LongPollingSession {
|
||||||
private Long last_chat_id;
|
private Long userId;
|
||||||
private DeferredResult<LongPollResult> deferredResult;
|
private DeferredResult<LongPollResult> deferredResult;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.alterdekim.game.controller;
|
|||||||
|
|
||||||
|
|
||||||
import com.alterdekim.game.component.LongPoll;
|
import com.alterdekim.game.component.LongPoll;
|
||||||
|
import com.alterdekim.game.component.LongPollConfig;
|
||||||
import com.alterdekim.game.component.LongPollingSession;
|
import com.alterdekim.game.component.LongPollingSession;
|
||||||
import com.alterdekim.game.dto.*;
|
import com.alterdekim.game.dto.*;
|
||||||
import com.alterdekim.game.entities.Chat;
|
import com.alterdekim.game.entities.Chat;
|
||||||
@ -20,10 +21,9 @@ import org.springframework.web.context.request.async.DeferredResult;
|
|||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.util.HashMap;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -51,17 +51,6 @@ public class APIController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private LongPoll longPoll;
|
private LongPoll longPoll;
|
||||||
|
|
||||||
@GetMapping("/api/v1/games/list")
|
|
||||||
public ResponseEntity<List<RoomResult>> gamesList() {
|
|
||||||
List<RoomResult> results = roomService.getAll()
|
|
||||||
.stream()
|
|
||||||
.map(room -> new RoomResult(room.getId(), room.getPlayerCount(), roomPlayerService.findByRoomId(room.getId()).stream()
|
|
||||||
.map(p -> userService.findById(p.getId()))
|
|
||||||
.map(p -> new UserResult(p.getId(), p.getUsername())).collect(Collectors.toList())))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
return ResponseEntity.ok(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/api/v1/chat/history/{count}/")
|
@GetMapping("/api/v1/chat/history/{count}/")
|
||||||
public ResponseEntity<ChatResult> chatList(@PathVariable Integer count ) {
|
public ResponseEntity<ChatResult> chatList(@PathVariable Integer count ) {
|
||||||
List<Chat> results = chatService.getLastChats(count);
|
List<Chat> results = chatService.getLastChats(count);
|
||||||
@ -132,11 +121,24 @@ public class APIController {
|
|||||||
return ResponseEntity.accepted().build();
|
return ResponseEntity.accepted().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/async/notify/get/")
|
@PostMapping("/api/v1/rooms/create/")
|
||||||
|
public ResponseEntity<String> createRoom( @RequestParam("is_private") Boolean is_private,
|
||||||
|
@RequestParam("players_count") Integer players_count) {
|
||||||
|
if( !(players_count >= 2 && players_count <= 5) ) return ResponseEntity.badRequest().build();
|
||||||
|
Long id = roomService.createRoom(new Room(players_count, is_private, "0"));
|
||||||
|
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
Long userId = userService.findByUsername(((org.springframework.security.core.userdetails.User) auth.getPrincipal()).getUsername()).getId();
|
||||||
|
roomPlayerService.leaveByUserId(userId);
|
||||||
|
roomPlayerService.joinRoom(id, userId);
|
||||||
|
return ResponseEntity.accepted().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/async/notify/get/")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public DeferredResult<LongPollResult> getNotify(@RequestParam("last_chat_id") Long last_chat_id,
|
public DeferredResult<LongPollResult> getNotify(@RequestParam("last_chat_id") Long last_chat_id,
|
||||||
@RequestParam("accessToken") String accessToken,
|
@RequestParam("accessToken") String accessToken,
|
||||||
@RequestParam("uid") Long userId) {
|
@RequestParam("uid") Long userId,
|
||||||
|
@RequestParam("poll_token") String poll_token) {
|
||||||
try {
|
try {
|
||||||
User u = userService.findById(userId);
|
User u = userService.findById(userId);
|
||||||
if (u == null) return null;
|
if (u == null) return null;
|
||||||
@ -145,48 +147,22 @@ public class APIController {
|
|||||||
} catch ( Exception e ) {
|
} catch ( Exception e ) {
|
||||||
log.error(e.getMessage(), e);
|
log.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
if( poll_token.length() != 32 ) return null;
|
||||||
final DeferredResult<LongPollResult> deferredResult = new DeferredResult<>();
|
final DeferredResult<LongPollResult> deferredResult = new DeferredResult<>();
|
||||||
longPoll.getLongPollingQueue().add(new LongPollingSession(last_chat_id, deferredResult));
|
if( longPoll.getMap().containsKey(userId) ){
|
||||||
/*Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
LongPollConfig c = longPoll.getMap().get(userId);
|
||||||
Long userId = userService.findByUsername(((org.springframework.security.core.userdetails.User) authentication.getPrincipal()).getUsername()).getId();
|
if( !c.getPoll_token().equals(poll_token) ) {
|
||||||
userService.updateOnline(userId);
|
c = new LongPollConfig(last_chat_id, new ArrayList<>(), 0, poll_token, new ArrayList<>(), System.currentTimeMillis());
|
||||||
|
longPoll.getLongPollingQueue().removeIf(q -> q.getUserId().longValue() == userId.longValue());
|
||||||
Integer onlineCount = userService.countByIsOnline();
|
|
||||||
List<Chat> results = chatService.getAfterLastChatId(last_chat_id);
|
|
||||||
List<UserResult> users = results.stream()
|
|
||||||
.map(Chat::getUserId)
|
|
||||||
.distinct()
|
|
||||||
.map( l -> userService.findById(l) )
|
|
||||||
.map( u -> new UserResult(u.getId(), u.getUsername()) )
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
results = results.stream().map( c -> {
|
|
||||||
String message = c.getMessage();
|
|
||||||
for( int i = 0; i < message.length(); i++ ) {
|
|
||||||
if( message.charAt(i) == '@' ) {
|
|
||||||
int u = message.substring(i).indexOf(' ') + i;
|
|
||||||
String username = message.substring(i+1, u);
|
|
||||||
User user = userService.findByUsername(username);
|
|
||||||
if( user != null ) {
|
|
||||||
Long uid = user.getId();
|
|
||||||
message = message.substring(0, i) + "<a href=\"/profile/" + uid + "\" class=\"chat-history-user\"><span class=\"_nick\">" + username + "</span></a>" + message.substring(u + 1);
|
|
||||||
} else {
|
|
||||||
message = message.substring(0, i) + username + message.substring(u + 1);
|
|
||||||
}
|
|
||||||
i = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
c.setMessage(message);
|
c.setLast_chat_id(last_chat_id);
|
||||||
return c;
|
c.setSession_pass(0);
|
||||||
}).collect(Collectors.toList());
|
c.setLastRequest(System.currentTimeMillis());
|
||||||
// Room stuff
|
longPoll.getMap().put(userId, c);
|
||||||
|
} else {
|
||||||
List<Room> rooms = roomService.getAllActive();
|
longPoll.getMap().put(userId, new LongPollConfig(last_chat_id, new ArrayList<>(), 0, poll_token, new ArrayList<>(), System.currentTimeMillis()));
|
||||||
List<RoomResult> roomResults = rooms.stream()
|
}
|
||||||
.map( r -> new RoomResult(r.getId(), r.getPlayerCount(), roomPlayerService.findByRoomId(r.getId()).stream()
|
longPoll.getLongPollingQueue().add(new LongPollingSession(userId, deferredResult));
|
||||||
.map(p -> userService.findById(p.getId()))
|
|
||||||
.map(p -> new UserResult(p.getId(), p.getUsername())).collect(Collectors.toList())))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
return ResponseEntity.ok(new LongPollResult(onlineCount, results, users, roomResults));*/
|
|
||||||
return deferredResult;
|
return deferredResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ public class StaticController {
|
|||||||
User u = userService.findByUsername(((org.springframework.security.core.userdetails.User) authentication.getPrincipal()).getUsername());
|
User u = userService.findByUsername(((org.springframework.security.core.userdetails.User) authentication.getPrincipal()).getUsername());
|
||||||
Long userId = u.getId();
|
Long userId = u.getId();
|
||||||
String apiKey = Hash.sha256((u.getId() + u.getUsername() + u.getPassword()).getBytes());
|
String apiKey = Hash.sha256((u.getId() + u.getUsername() + u.getPassword()).getBytes());
|
||||||
model.addAttribute("auth_obj", new AuthApiObject(apiKey, userId));
|
model.addAttribute("auth_obj", new AuthApiObject(apiKey, userId, Hash.rnd()));
|
||||||
} catch ( Exception e ) {
|
} catch ( Exception e ) {
|
||||||
log.error(e.getMessage(), e);
|
log.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
@ -10,4 +10,5 @@ import lombok.NoArgsConstructor;
|
|||||||
public class AuthApiObject {
|
public class AuthApiObject {
|
||||||
private String accessToken;
|
private String accessToken;
|
||||||
private Long uid;
|
private Long uid;
|
||||||
|
private String poll_token;
|
||||||
}
|
}
|
||||||
|
14
src/main/java/com/alterdekim/game/dto/FriendResult.java
Normal file
14
src/main/java/com/alterdekim/game/dto/FriendResult.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package com.alterdekim.game.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public class FriendResult {
|
||||||
|
private FriendState action;
|
||||||
|
private Long id;
|
||||||
|
private String username;
|
||||||
|
}
|
6
src/main/java/com/alterdekim/game/dto/FriendState.java
Normal file
6
src/main/java/com/alterdekim/game/dto/FriendState.java
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package com.alterdekim.game.dto;
|
||||||
|
|
||||||
|
public enum FriendState {
|
||||||
|
ADD,
|
||||||
|
REMOVE
|
||||||
|
}
|
@ -14,5 +14,6 @@ public class LongPollResult {
|
|||||||
private Integer onlineCount;
|
private Integer onlineCount;
|
||||||
private List<Chat> messages;
|
private List<Chat> messages;
|
||||||
private List<UserResult> users;
|
private List<UserResult> users;
|
||||||
private List<RoomResult> rooms;
|
private List<RoomResultV2> rooms;
|
||||||
|
private List<FriendResult> friends;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.alterdekim.game.dto;
|
||||||
|
|
||||||
|
public enum RoomResultState {
|
||||||
|
ADD_CHANGE,
|
||||||
|
REMOVE
|
||||||
|
}
|
17
src/main/java/com/alterdekim/game/dto/RoomResultV2.java
Normal file
17
src/main/java/com/alterdekim/game/dto/RoomResultV2.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package com.alterdekim.game.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public class RoomResultV2 {
|
||||||
|
private RoomResultState action;
|
||||||
|
private Long id;
|
||||||
|
private Integer playerCount;
|
||||||
|
private List<UserResult> players;
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.alterdekim.game.repository;
|
||||||
|
|
||||||
|
import com.alterdekim.game.entities.FriendStatus;
|
||||||
|
import com.alterdekim.game.entities.Room;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface FriendRepository extends JpaRepository<FriendStatus, Long> {
|
||||||
|
@Query(value = "SELECT IF(f.firstUserId = :userId, f.secondUserId, f.firstUserId) FROM FriendStatus f WHERE (f.firstUserId = :userId OR f.secondUserId = :userId) AND f.status = 2")
|
||||||
|
List<Long> getFriendsOfUserId(@Param("userId") Long userId);
|
||||||
|
}
|
@ -3,11 +3,22 @@ package com.alterdekim.game.repository;
|
|||||||
import com.alterdekim.game.entities.Room;
|
import com.alterdekim.game.entities.Room;
|
||||||
import com.alterdekim.game.entities.RoomPlayer;
|
import com.alterdekim.game.entities.RoomPlayer;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface RoomPlayerRepository extends JpaRepository<RoomPlayer, Long> {
|
public interface RoomPlayerRepository extends JpaRepository<RoomPlayer, Long> {
|
||||||
List<RoomPlayer> findByRoomId(Long roomId);
|
|
||||||
|
@Query(value = "SELECT new RoomPlayer(r.id, r.roomId, r.userId) FROM RoomPlayer r WHERE r.roomId = :roomId ORDER BY r.userId ASC")
|
||||||
|
List<RoomPlayer> findByRoomId(@Param("roomId") Long roomId);
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Modifying
|
||||||
|
@Query(value = "DELETE FROM RoomPlayer r WHERE r.userId = :userId")
|
||||||
|
void deleteAllByUserId(@Param("userId") Long userId);
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,22 @@ package com.alterdekim.game.repository;
|
|||||||
import com.alterdekim.game.entities.Room;
|
import com.alterdekim.game.entities.Room;
|
||||||
import com.alterdekim.game.entities.User;
|
import com.alterdekim.game.entities.User;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface RoomRepository extends JpaRepository<Room, Long> {
|
public interface RoomRepository extends JpaRepository<Room, Long> {
|
||||||
|
|
||||||
@Query(value = "SELECT r FROM Room r WHERE r.isPrivate = false")
|
@Query(value = "SELECT r FROM Room r WHERE r.isPrivate = false ORDER BY r.id ASC")
|
||||||
List<Room> findAllByActiveTrue();
|
List<Room> findAllByActiveTrue();
|
||||||
|
|
||||||
|
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||||
|
@Modifying
|
||||||
|
@Query(value = "DELETE FROM room WHERE room.id NOT IN (SELECT t.room_id FROM (SELECT COUNT(id) as UID, room_id FROM room_player GROUP BY room_id) t)", nativeQuery = true)
|
||||||
|
void clearEmptyRooms();
|
||||||
}
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.alterdekim.game.service;
|
||||||
|
|
||||||
|
import com.alterdekim.game.repository.FriendRepository;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class FriendServiceImpl {
|
||||||
|
private final FriendRepository repository;
|
||||||
|
|
||||||
|
public List<Long> getFriendsOfUserId(Long userId) {
|
||||||
|
return repository.getFriendsOfUserId(userId);
|
||||||
|
}
|
||||||
|
}
|
@ -24,4 +24,12 @@ public class RoomPlayerServiceImpl implements RoomPlayerService{
|
|||||||
public List<RoomPlayer> findByRoomId(Long roomId) {
|
public List<RoomPlayer> findByRoomId(Long roomId) {
|
||||||
return repository.findByRoomId(roomId);
|
return repository.findByRoomId(roomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void joinRoom(Long id, Long userId) {
|
||||||
|
repository.save(new RoomPlayer(id, userId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void leaveByUserId(Long userId) {
|
||||||
|
repository.deleteAllByUserId(userId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import com.alterdekim.game.repository.RoomRepository;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class RoomServiceImpl implements RoomService {
|
public class RoomServiceImpl implements RoomService {
|
||||||
@ -22,4 +23,16 @@ public class RoomServiceImpl implements RoomService {
|
|||||||
public List<Room> getAllActive() {
|
public List<Room> getAllActive() {
|
||||||
return roomRepository.findAllByActiveTrue();
|
return roomRepository.findAllByActiveTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<Room> findById(Long id) {
|
||||||
|
return roomRepository.findById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long createRoom(Room room) {
|
||||||
|
return roomRepository.save(room).getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearEmptyRooms() {
|
||||||
|
roomRepository.clearEmptyRooms();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package com.alterdekim.game.util;
|
package com.alterdekim.game.util;
|
||||||
|
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
public class Hash {
|
public class Hash {
|
||||||
public static String sha256( byte[] b ) throws Exception {
|
public static String sha256( byte[] b ) throws Exception {
|
||||||
@ -19,4 +22,12 @@ public class Hash {
|
|||||||
}
|
}
|
||||||
return hexString.toString();
|
return hexString.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String rnd() {
|
||||||
|
return IntStream.generate(() -> new Random().nextInt(0, 62))
|
||||||
|
.limit(32)
|
||||||
|
.boxed()
|
||||||
|
.map(i -> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".charAt(i)+"")
|
||||||
|
.collect(Collectors.joining());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
414
src/main/resources/static/css/games.css
Normal file
414
src/main/resources/static/css/games.css
Normal file
@ -0,0 +1,414 @@
|
|||||||
|
.grid {
|
||||||
|
display: grid !important;
|
||||||
|
grid-template-columns: repeat(12,1fr);
|
||||||
|
grid-column-gap: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.g-col-4 {
|
||||||
|
grid-column-end: span 4;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.g-col-8 {
|
||||||
|
grid-column-end: span 8;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block {
|
||||||
|
display: block;
|
||||||
|
border-bottom: 2px solid rgba(0,0,0,.1);
|
||||||
|
border-radius: 5px;
|
||||||
|
padding-top: .1px;
|
||||||
|
padding-bottom: .1px;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 1px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 1000px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-size: 18px;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block-content {
|
||||||
|
justify-content: center;
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.market {
|
||||||
|
height: 160px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transparent-override {
|
||||||
|
background-color: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-glowing {
|
||||||
|
color: rgba(55, 188, 157, 1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mission-one {
|
||||||
|
margin-top: 10px;
|
||||||
|
border-top: 1px solid #e9eaec;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mission-target>span {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mission-block>span {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
margin-top: 5px;
|
||||||
|
height: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
background-color: rgba(55, 188, 157, 1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mission-block, .mission-target {
|
||||||
|
font-size: 13px;
|
||||||
|
margin-top: 5px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mission-text {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.friend-search {
|
||||||
|
margin: 20px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-list-message {
|
||||||
|
text-align: center;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-list-message>p {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title > span {
|
||||||
|
color: #a7adb5;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-history {
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
width: 100%;
|
||||||
|
height: 280px;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
#market-carousel {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-title-text {
|
||||||
|
font-size: 19px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-body-text {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-item-body {
|
||||||
|
padding: 0 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-item-background {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-history-one {
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-history-info {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 5px;
|
||||||
|
color: #989aa4;
|
||||||
|
transform: translateY(1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-history-user {
|
||||||
|
padding: 0 6px;
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: #b9bac1;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-history-user>._nick {
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-history-text {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-history-one>* {
|
||||||
|
font-size: 14px;
|
||||||
|
vertical-align: middle;
|
||||||
|
line-height: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-history-info>.time {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-input {
|
||||||
|
margin: 20px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.games-room-one {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
position: relative;
|
||||||
|
border-top: 1px solid;
|
||||||
|
border-color: #e6e6e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.games-room-one-body {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.games-room-one-body-head {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.games-room-one-body-head-info {
|
||||||
|
flex-grow: 999;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.games-room-one-body-members {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
margin-top: 13px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.games-room-one-body-members-one {
|
||||||
|
position: relative;
|
||||||
|
margin: 0 5px;
|
||||||
|
width: calc(20% - 2 * 5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.games-room-one-body-members-one-nick {
|
||||||
|
margin-top: 5px;
|
||||||
|
height: 21px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 21px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.games-room-one-body-members-one-nick > a {
|
||||||
|
color: #656d78;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.games-room-one-body-members-one-nick > span {
|
||||||
|
color: #656d78;
|
||||||
|
font-size: 14px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.games-room-one-body-members-one-avatar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
margin: auto;
|
||||||
|
border-radius: 100%;
|
||||||
|
width: 75px;
|
||||||
|
height: 75px;
|
||||||
|
background: center/cover no-repeat;
|
||||||
|
font: 50px Ionicons;
|
||||||
|
}
|
||||||
|
|
||||||
|
.games-room-one-body-head-info > ._type > div {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.games-room-one-body-head-info > ._with_wormhole > div {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
._slot_join {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#waiting_list > .title {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#waiting_list > .title > a {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.modal-open > :not(.modal) {
|
||||||
|
-webkit-filter: blur(3px);
|
||||||
|
-moz-filter: blur(3px);
|
||||||
|
-o-filter: blur(3px);
|
||||||
|
-ms-filter: blur(3px);
|
||||||
|
filter: blur(3px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-creation-modal-modes {
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
flex-shrink: 0;
|
||||||
|
border-radius: 5px 0 0 5px;
|
||||||
|
padding: 10px 15px 10px 10px;
|
||||||
|
width: 250px;
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-creation-modal-block {
|
||||||
|
flex-shrink: 0;
|
||||||
|
position: relative;
|
||||||
|
left: -5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 20px 0;
|
||||||
|
width: 375px;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0 0 25px rgba(0,0,0,.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-creation-modal-body {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
box-shadow: 0 0 100px rgba(0,0,0,.333);
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 620px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-creation-modal-modes-one._regular._selected {
|
||||||
|
background: #8cc152;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-creation-modal-modes-one._selected {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-creation-modal-modes-one {
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 10px 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-creation-modal-modes-one-title {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-creation-modal-modes-one-subtitle {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 15px;
|
||||||
|
opacity: .85;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-creation-modal-block-title {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-top: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
position: relative;
|
||||||
|
margin-left: 20px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-creation-modal-block-subtitle {
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-left: 20px;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
position: relative;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-switch-game {
|
||||||
|
transform: scale(1.2);
|
||||||
|
margin-left: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-check-input:checked {
|
||||||
|
background-color: #37bc9d;
|
||||||
|
border-color: #37bc9d;
|
||||||
|
}
|
||||||
|
|
||||||
|
#players-count-range, .players-range-value {
|
||||||
|
margin-left: 20px;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-range::-webkit-slider-thumb {
|
||||||
|
background-color: #37bc9d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reply-button {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.friend-one {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.friend-one > span {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.friend-one > ion-icon {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #37bc9d;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
110
src/main/resources/static/css/index.css
Normal file
110
src/main/resources/static/css/index.css
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
.navbar-brand-custom {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-brand-custom:hover {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar {
|
||||||
|
background-color: #37bc9d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline-primary {
|
||||||
|
border-color: transparent;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: rgba(255,255,255,.85);
|
||||||
|
color: #37bc9d;
|
||||||
|
border-color: rgba(255,255,255,.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-color: #ffffff;
|
||||||
|
color: #37bc9d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline-primary:hover {
|
||||||
|
background-color: rgba(255, 255, 255,0.25);
|
||||||
|
border-color: rgba(255, 255, 255,0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
font: 700 3.5em Montserrat;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title-small {
|
||||||
|
margin-top: .7em;
|
||||||
|
font: 500 1.32em/1.4em Montserrat;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-billboard {
|
||||||
|
background-color: #37bc9d;
|
||||||
|
height: 700px;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-button {
|
||||||
|
color: #5b5d67;
|
||||||
|
background-color: #fff;
|
||||||
|
border-color: #fff;
|
||||||
|
font: 600 1.5rem Montserrat;
|
||||||
|
padding: 0 0.9em;
|
||||||
|
height: 2.1em;
|
||||||
|
align-items: center;
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-button:hover {
|
||||||
|
color: #5b5d67;
|
||||||
|
background-color: rgba(255, 255, 255, 0.85);
|
||||||
|
border-color: rgba(255, 255, 255, 0.85);
|
||||||
|
font: 600 1.5rem Montserrat;
|
||||||
|
padding: 0 0.9em;
|
||||||
|
height: 2.1em;
|
||||||
|
align-items: center;
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-main-button {
|
||||||
|
margin-top: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title-second {
|
||||||
|
margin-top: 1.25em;
|
||||||
|
margin-right: 0px;
|
||||||
|
margin-bottom: 1.25em;
|
||||||
|
margin-left: 0px;
|
||||||
|
font: 700 3.25em Montserrat;
|
||||||
|
color: #26272b;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.billboard-img {
|
||||||
|
box-shadow: 0 0 100px rgba(0,0,0,.33);
|
||||||
|
width: 900px;
|
||||||
|
overflow: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.billboard-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin: 0 0 .4em;
|
||||||
|
font: 700 2em Montserrat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col_text {
|
||||||
|
font-size: 1.1em;
|
||||||
|
text-align: left;
|
||||||
|
}
|
@ -1,10 +1,119 @@
|
|||||||
$.fn.pressEnter = function(fn) {
|
var isPollingActive = true;
|
||||||
|
|
||||||
|
function createRoom() {
|
||||||
|
let isprivate = $("#flexSwitchCheckDefault").is(':checked');
|
||||||
|
let playerscnt = $("#players-count-range").val();
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/v1/rooms/create/",
|
||||||
|
data: {
|
||||||
|
is_private: isprivate,
|
||||||
|
players_count: playerscnt
|
||||||
|
},
|
||||||
|
method: "POST"
|
||||||
|
}).done(function(data) {
|
||||||
|
$("#game-creation-menu-modal").modal('hide');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function successPolling(data) {
|
||||||
|
console.log(data);
|
||||||
|
let onlineCount = data.onlineCount;
|
||||||
|
$(".chat-title").find("span").html(onlineCount + " online");
|
||||||
|
let messages = data.messages;
|
||||||
|
let users = data.users;
|
||||||
|
let rooms = data.rooms;
|
||||||
|
let friends = data.friends;
|
||||||
|
if( messages.length > 0 ) {
|
||||||
|
last_chat_id = messages[0].id;
|
||||||
|
}
|
||||||
|
for( let i = 0; i < messages.length; i++ ) {
|
||||||
|
let obj = messages[i];
|
||||||
|
let time = parseTime(obj.createdAt);
|
||||||
|
let username = findUser(users, obj.userId).username;
|
||||||
|
let userid = obj.userId;
|
||||||
|
let msgtext = obj.message;
|
||||||
|
let html = '<div class="chat-history-one"><div class="chat-history-info"><span class="time">'+time+'</span><ion-icon name="arrow-undo-outline" class="reply-button" data-userid="'+userid+'" data-username="'+username+'" onClick="replyButtonClicked(this)"></ion-icon></div><span><span class="chat-history-text chat-history-content-message"><span class="formatter"><a href="/profile/'+userid+'" class="chat-history-user"><span class="_nick">'+username+'</span></a><ion-icon name="remove-outline"></ion-icon><span>'+msgtext+'</span></span></span></span></div>';
|
||||||
|
$(".chat-history").append(html);
|
||||||
|
}
|
||||||
|
for( let i = 0; i < rooms.length; i++ ) {
|
||||||
|
let room = rooms[i];
|
||||||
|
if( room.action == 'ADD_CHANGE' ) {
|
||||||
|
let room_p_html = '';
|
||||||
|
for( let u = 0; u < room.players.length; u++ ) {
|
||||||
|
let room_player = room.players[u];
|
||||||
|
room_p_html += '<div class="games-room-one-body-members-one"><div class="games-room-one-body-members-one-avatar" style="background-image: url("https://i.dogecdn.wtf/7lurfckMFrYXm4gf");"><a href="/profile/'+room_player.id+'"></a><div class="_online"></div></div><div class="games-room-one-body-members-one-nick"><a href="/profile/'+room_player.id+'">'+room_player.username+'</a></div></div>';
|
||||||
|
}
|
||||||
|
for( let u = 0; u < (room.playerCount - room.players.length); u++ ) {
|
||||||
|
room_p_html += '<div class="games-room-one-body-members-one _slot_join"><div class="games-room-one-body-members-one-avatar"><ion-icon name="add-outline" style="color: #656d78;"></ion-icon></div><div class="games-room-one-body-members-one-nick"><span>Join</span></div></div>';
|
||||||
|
}
|
||||||
|
let room_html = '<div class="games-room-one" data-room-id="'+room.id+'"><div class="games-room-one-body"><div class="games-room-one-body-head"><div class="games-room-one-body-head-info"><div class="_type"><div>Game</div></div></div><div class="games-room-one-body-head-actions"></div></div><div class="games-room-one-body-members">'+room_p_html+'</div></div></div>';
|
||||||
|
let has_element = false;
|
||||||
|
$(".games-room-one").each(function() {
|
||||||
|
if( $(this).attr("data-room-id") == room.id ) {
|
||||||
|
$(this).replaceWith(room_html);
|
||||||
|
has_element = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if( !has_element ) {
|
||||||
|
$(".rooms-list").append(room_html);
|
||||||
|
}
|
||||||
|
} else if( room.action == 'REMOVE' ) {
|
||||||
|
$(".games-room-one").each(function() {
|
||||||
|
if( $(this).attr("data-room-id") == room.id ) {
|
||||||
|
$(this).remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for( let i = 0; i < friends.length; i++ ) {
|
||||||
|
let friend = friends[i];
|
||||||
|
if( friend.action == 'ADD' ) {
|
||||||
|
let fr_html = '<div class="friend-one" data-friend-id="'+friend.id+'"><a href="/profile/'+friend.id+'" class="navbar-btn"><img class="navbar-profile-img" src="https://avatars.githubusercontent.com/u/102559365?v=4"></a><span>'+friend.username+'</span><ion-icon name="person-add-outline" role="img" class="md hydrated"></ion-icon></div>';
|
||||||
|
$(".friends-online-list").append(fr_html);
|
||||||
|
} else if( friend.action == 'REMOVE' ) {
|
||||||
|
$(".friend-one").each(function() {
|
||||||
|
if( $(this).attr("data-friend-id") == friend.id ) {
|
||||||
|
$(this).remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var clh = $('#chat_list').find(".chat-history");
|
||||||
|
clh.scrollTop(clh.prop("scrollHeight"));
|
||||||
|
$("#chat_list").find(".chat-history").css("display", "");
|
||||||
|
$("#chat_list").find(".message-input").css("display", "");
|
||||||
|
$("#chat_list").find(".block-content").css("display", "none");
|
||||||
|
}
|
||||||
|
|
||||||
|
function pollServer() {
|
||||||
|
let accessToken = $("api-tag").attr("data-access-token");
|
||||||
|
let uid = $("api-tag").attr("data-uid");
|
||||||
|
let poll_token = $("api-tag").attr("data-poll-token");
|
||||||
|
if (isPollingActive) {
|
||||||
|
window.setTimeout(function () {
|
||||||
|
$.ajax({
|
||||||
|
url: "/async/notify/get/",
|
||||||
|
data: {
|
||||||
|
last_chat_id: last_chat_id,
|
||||||
|
accessToken: accessToken,
|
||||||
|
poll_token: poll_token,
|
||||||
|
uid: uid
|
||||||
|
},
|
||||||
|
method: "POST"
|
||||||
|
}).done(function(data) {
|
||||||
|
successPolling(data);
|
||||||
|
//SUCCESS LOGIC
|
||||||
|
pollServer();
|
||||||
|
});
|
||||||
|
}, 1500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.pressEnter = function(fn) {
|
||||||
return this.each(function() {
|
return this.each(function() {
|
||||||
$(this).bind('enterPress', fn);
|
$(this).bind('enterPress', fn);
|
||||||
$(this).keyup(function(e){
|
$(this).keyup(function(e) {
|
||||||
if(e.keyCode == 13)
|
if(e.keyCode == 13) {
|
||||||
{
|
|
||||||
$(this).trigger("enterPress");
|
$(this).trigger("enterPress");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -34,41 +143,6 @@ function replyButtonClicked(obj) {
|
|||||||
$('#chat-message-input').val($('#chat-message-input').val() + " @" + username + "");
|
$('#chat-message-input').val($('#chat-message-input').val() + " @" + username + "");
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(function() {
|
|
||||||
let accessToken = $("api-tag").attr("data-access-token");
|
|
||||||
let uid = $("api-tag").attr("data-uid");
|
|
||||||
$.ajax({
|
|
||||||
url: "/async/notify/get/",
|
|
||||||
data: {
|
|
||||||
last_chat_id: last_chat_id,
|
|
||||||
accessToken: accessToken,
|
|
||||||
uid: uid
|
|
||||||
},
|
|
||||||
method: "GET"
|
|
||||||
}).done(function(data) {
|
|
||||||
console.log(data);
|
|
||||||
let onlineCount = data.onlineCount;
|
|
||||||
$(".chat-title").find("span").html(onlineCount + " online");
|
|
||||||
let messages = data.messages;
|
|
||||||
let users = data.users;
|
|
||||||
if( messages.length > 0 ) {
|
|
||||||
last_chat_id = messages[0].id;
|
|
||||||
}
|
|
||||||
for( let i = 0; i < messages.length; i++ ) {
|
|
||||||
let obj = messages[i];
|
|
||||||
let time = parseTime(obj.createdAt);
|
|
||||||
let username = findUser(users, obj.userId).username;
|
|
||||||
let userid = obj.userId;
|
|
||||||
let msgtext = obj.message;
|
|
||||||
let html = '<div class="chat-history-one"><div class="chat-history-info"><span class="time">'+time+'</span><ion-icon name="arrow-undo-outline" class="reply-button" data-userid="'+userid+'" data-username="'+username+'" onClick="replyButtonClicked(this)"></ion-icon></div><span><span class="chat-history-text chat-history-content-message"><span class="formatter"><a href="/profile/'+userid+'" class="chat-history-user"><span class="_nick">'+username+'</span></a><ion-icon name="remove-outline"></ion-icon><span>'+msgtext+'</span></span></span></span></div>';
|
|
||||||
$(".chat-history").append(html);
|
|
||||||
}
|
|
||||||
$("#chat_list").find(".chat-history").css("display", "");
|
|
||||||
$("#chat_list").find(".message-input").css("display", "");
|
|
||||||
$("#chat_list").find(".block-content").css("display", "none");
|
|
||||||
});
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$("#players-count-range").on("input", function() {
|
$("#players-count-range").on("input", function() {
|
||||||
$("label[for='players-count-range']").find("span").text($(this).val());
|
$("label[for='players-count-range']").find("span").text($(this).val());
|
||||||
@ -86,13 +160,6 @@ $(document).ready(function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: "/api/v1/games/list",
|
|
||||||
method: "GET"
|
|
||||||
}).done(function(data) {
|
|
||||||
console.log(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
// block-content
|
// block-content
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@ -114,6 +181,8 @@ $(document).ready(function() {
|
|||||||
let html = '<div class="chat-history-one"><div class="chat-history-info"><span class="time">'+time+'</span><ion-icon name="arrow-undo-outline" class="reply-button" data-userid="'+userid+'" data-username="'+username+'" onClick="replyButtonClicked(this)"></ion-icon></div><span><span class="chat-history-text chat-history-content-message"><span class="formatter"><a href="/profile/'+userid+'" class="chat-history-user"><span class="_nick">'+username+'</span></a><ion-icon name="remove-outline"></ion-icon><span>'+msgtext+'</span></span></span></span></div>';
|
let html = '<div class="chat-history-one"><div class="chat-history-info"><span class="time">'+time+'</span><ion-icon name="arrow-undo-outline" class="reply-button" data-userid="'+userid+'" data-username="'+username+'" onClick="replyButtonClicked(this)"></ion-icon></div><span><span class="chat-history-text chat-history-content-message"><span class="formatter"><a href="/profile/'+userid+'" class="chat-history-user"><span class="_nick">'+username+'</span></a><ion-icon name="remove-outline"></ion-icon><span>'+msgtext+'</span></span></span></span></div>';
|
||||||
$(".chat-history").append(html);
|
$(".chat-history").append(html);
|
||||||
}
|
}
|
||||||
|
var clh = $('#chat_list').find(".chat-history");
|
||||||
|
clh.scrollTop(clh.prop("scrollHeight"));
|
||||||
$("#chat_list").find(".chat-history").css("display", "");
|
$("#chat_list").find(".chat-history").css("display", "");
|
||||||
$("#chat_list").find(".message-input").css("display", "");
|
$("#chat_list").find(".message-input").css("display", "");
|
||||||
$("#chat_list").find(".block-content").css("display", "none");
|
$("#chat_list").find(".block-content").css("display", "none");
|
||||||
@ -140,10 +209,8 @@ $(document).ready(function() {
|
|||||||
$(".market").find("#market-carousel").css("display", "");
|
$(".market").find("#market-carousel").css("display", "");
|
||||||
});
|
});
|
||||||
|
|
||||||
/*$.ajax({
|
pollServer();
|
||||||
url: "/api/v1/games/list",
|
|
||||||
method: "GET"
|
$(".rooms-list").css("display", "");
|
||||||
}).done(function(data) {
|
$("#waiting_list").find(".block-content").css("display", "none");
|
||||||
console.log(data);
|
|
||||||
});*/
|
|
||||||
});
|
});
|
@ -2,406 +2,8 @@
|
|||||||
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||||
<head>
|
<head>
|
||||||
<th:block th:insert="~{fragments/head}"></th:block>
|
<th:block th:insert="~{fragments/head}"></th:block>
|
||||||
<style>
|
<link rel="stylesheet" href="/static/css/games.css"/>
|
||||||
.grid {
|
<api-tag th:data-access-token="${auth_obj.accessToken}" th:data-uid="${auth_obj.uid}" th:data-poll-token="${auth_obj.poll_token}"></api-tag>
|
||||||
display: grid !important;
|
|
||||||
grid-template-columns: repeat(12,1fr);
|
|
||||||
grid-column-gap: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-col-4 {
|
|
||||||
grid-column-end: span 4;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-col-8 {
|
|
||||||
grid-column-end: span 8;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.block {
|
|
||||||
display: block;
|
|
||||||
border-bottom: 2px solid rgba(0,0,0,.1);
|
|
||||||
border-radius: 5px;
|
|
||||||
padding-top: .1px;
|
|
||||||
padding-bottom: .1px;
|
|
||||||
width: 100%;
|
|
||||||
min-height: 1px;
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
width: 1000px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
font-size: 18px;
|
|
||||||
margin-top: 20px;
|
|
||||||
margin-right: 20px;
|
|
||||||
margin-left: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.block-content {
|
|
||||||
justify-content: center;
|
|
||||||
display: flex;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.market {
|
|
||||||
height: 160px;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.transparent-override {
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-glowing {
|
|
||||||
color: rgba(55, 188, 157, 1) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mission-one {
|
|
||||||
margin-top: 10px;
|
|
||||||
border-top: 1px solid #e9eaec;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mission-target>span {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mission-block>span {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress {
|
|
||||||
margin-top: 5px;
|
|
||||||
height: 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-bar {
|
|
||||||
background-color: rgba(55, 188, 157, 1) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mission-block, .mission-target {
|
|
||||||
font-size: 13px;
|
|
||||||
margin-top: 5px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mission-text {
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.friend-search {
|
|
||||||
margin: 20px;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-list-message {
|
|
||||||
text-align: center;
|
|
||||||
margin: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-list-message>p {
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title > span {
|
|
||||||
color: #a7adb5;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-history {
|
|
||||||
padding: 20px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
width: 100%;
|
|
||||||
height: 280px;
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: scroll;
|
|
||||||
word-wrap: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
#market-carousel {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.carousel-title-text {
|
|
||||||
font-size: 19px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.carousel-body-text {
|
|
||||||
margin-top: 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 20px;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.carousel-item-body {
|
|
||||||
padding: 0 70px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.carousel-item-background {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-history-one {
|
|
||||||
margin: 5px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-history-info {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-right: 5px;
|
|
||||||
color: #989aa4;
|
|
||||||
transform: translateY(1px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-history-user {
|
|
||||||
padding: 0 6px;
|
|
||||||
text-decoration: none;
|
|
||||||
background-color: #b9bac1;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-history-user>._nick {
|
|
||||||
color: #fff;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-history-text {
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-history-one>* {
|
|
||||||
font-size: 14px;
|
|
||||||
vertical-align: middle;
|
|
||||||
line-height: 21px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-history-info>.time {
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-input {
|
|
||||||
margin: 20px;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.games-room-one {
|
|
||||||
display: flex;
|
|
||||||
flex-flow: column nowrap;
|
|
||||||
position: relative;
|
|
||||||
border-top: 1px solid;
|
|
||||||
border-color: #e6e6e6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.games-room-one-body {
|
|
||||||
padding: 10px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.games-room-one-body-head {
|
|
||||||
display: flex;
|
|
||||||
flex-flow: row nowrap;
|
|
||||||
height: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.games-room-one-body-head-info {
|
|
||||||
flex-grow: 999;
|
|
||||||
display: flex;
|
|
||||||
flex-flow: row nowrap;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.games-room-one-body-members {
|
|
||||||
display: flex;
|
|
||||||
flex-flow: row nowrap;
|
|
||||||
margin-top: 13px;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.games-room-one-body-members-one {
|
|
||||||
position: relative;
|
|
||||||
margin: 0 5px;
|
|
||||||
width: calc(20% - 2 * 5px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.games-room-one-body-members-one-nick {
|
|
||||||
margin-top: 5px;
|
|
||||||
height: 21px;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 21px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.games-room-one-body-members-one-nick > a {
|
|
||||||
color: #656d78;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.games-room-one-body-members-one-nick > span {
|
|
||||||
color: #656d78;
|
|
||||||
font-size: 14px;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.games-room-one-body-members-one-avatar {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
position: relative;
|
|
||||||
margin: auto;
|
|
||||||
border-radius: 100%;
|
|
||||||
width: 75px;
|
|
||||||
height: 75px;
|
|
||||||
background: center/cover no-repeat;
|
|
||||||
font: 50px Ionicons;
|
|
||||||
}
|
|
||||||
|
|
||||||
.games-room-one-body-head-info > ._type > div {
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.games-room-one-body-head-info > ._with_wormhole > div {
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
._slot_join {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
#waiting_list > .title {
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
#waiting_list > .title > a {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.modal-open > :not(.modal) {
|
|
||||||
-webkit-filter: blur(3px);
|
|
||||||
-moz-filter: blur(3px);
|
|
||||||
-o-filter: blur(3px);
|
|
||||||
-ms-filter: blur(3px);
|
|
||||||
filter: blur(3px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-creation-modal-modes {
|
|
||||||
background-color: #f7f7f7;
|
|
||||||
flex-shrink: 0;
|
|
||||||
border-radius: 5px 0 0 5px;
|
|
||||||
padding: 10px 15px 10px 10px;
|
|
||||||
width: 250px;
|
|
||||||
overflow: hidden;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-creation-modal-block {
|
|
||||||
flex-shrink: 0;
|
|
||||||
position: relative;
|
|
||||||
left: -5px;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 20px 0;
|
|
||||||
width: 375px;
|
|
||||||
background-color: #fff;
|
|
||||||
box-shadow: 0 0 25px rgba(0,0,0,.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-creation-modal-body {
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
box-shadow: 0 0 100px rgba(0,0,0,.333);
|
|
||||||
border-radius: 5px;
|
|
||||||
width: 620px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-creation-modal-modes-one._regular._selected {
|
|
||||||
background: #8cc152;
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-creation-modal-modes-one._selected {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-creation-modal-modes-one {
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 10px 15px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-creation-modal-modes-one-title {
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 18px;
|
|
||||||
line-height: 21px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-creation-modal-modes-one-subtitle {
|
|
||||||
margin-top: 4px;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 15px;
|
|
||||||
opacity: .85;
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-creation-modal-block-title {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
font-weight: 600;
|
|
||||||
margin-top: 0;
|
|
||||||
font-size: 18px;
|
|
||||||
position: relative;
|
|
||||||
margin-left: 20px;
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-creation-modal-block-subtitle {
|
|
||||||
margin-right: 20px;
|
|
||||||
margin-left: 20px;
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
font-size: 16px;
|
|
||||||
position: relative;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-switch-game {
|
|
||||||
transform: scale(1.2);
|
|
||||||
margin-left: 3.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-check-input:checked {
|
|
||||||
background-color: #37bc9d;
|
|
||||||
border-color: #37bc9d;
|
|
||||||
}
|
|
||||||
|
|
||||||
#players-count-range, .players-range-value {
|
|
||||||
margin-left: 20px;
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-range::-webkit-slider-thumb {
|
|
||||||
background-color: #37bc9d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.reply-button {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<api-tag th:data-access-token="${auth_obj.accessToken}" th:data-uid="${auth_obj.uid}"></api-tag>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<th:block th:insert="~{fragments/navbar}"></th:block>
|
<th:block th:insert="~{fragments/navbar}"></th:block>
|
||||||
@ -425,7 +27,7 @@
|
|||||||
<label class="form-check-label" for="flexSwitchCheckDefault">Private room</label>
|
<label class="form-check-label" for="flexSwitchCheckDefault">Private room</label>
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; justify-content: center;">
|
<div style="display: flex; justify-content: center;">
|
||||||
<button class="btn btn-primary navbar-btn">
|
<button class="btn btn-primary navbar-btn" onClick="createRoom()">
|
||||||
<span>Start</span>
|
<span>Start</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -484,15 +86,15 @@
|
|||||||
<span class="visually-hidden">Loading...</span>
|
<span class="visually-hidden">Loading...</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--<div>
|
<div class="friends-online-list" style="display: none;">
|
||||||
<div class="friend-search">
|
<div class="friend-search">
|
||||||
<input type="text" class="friend-search-input form-control" placeholder="Search friends">
|
<input type="text" class="friend-search-input form-control" placeholder="Search friends">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="empty-list-message">
|
<!--<div class="empty-list-message">
|
||||||
<p>No friends online.</p>
|
<p>No friends online.</p>
|
||||||
</div>
|
</div>-->
|
||||||
</div>-->
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="g-col-8">
|
<div class="g-col-8">
|
||||||
@ -559,8 +161,8 @@
|
|||||||
<ion-icon name="dice-outline"></ion-icon>
|
<ion-icon name="dice-outline"></ion-icon>
|
||||||
<span>Create game</span>
|
<span>Create game</span>
|
||||||
</a></div>
|
</a></div>
|
||||||
<!--<div class="rooms-list">
|
<div class="rooms-list" style="display: none">
|
||||||
<div class="games-room-one">
|
<!--<div class="games-room-one">
|
||||||
<div class="games-room-one-body">
|
<div class="games-room-one-body">
|
||||||
<div class="games-room-one-body-head">
|
<div class="games-room-one-body-head">
|
||||||
<div class="games-room-one-body-head-info">
|
<div class="games-room-one-body-head-info">
|
||||||
@ -620,8 +222,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>-->
|
||||||
</div>-->
|
</div>
|
||||||
<div class="block-content">
|
<div class="block-content">
|
||||||
<div class="spinner-grow text-glowing" role="status">
|
<div class="spinner-grow text-glowing" role="status">
|
||||||
<span class="visually-hidden">Loading...</span>
|
<span class="visually-hidden">Loading...</span>
|
||||||
|
@ -2,118 +2,7 @@
|
|||||||
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||||
<head>
|
<head>
|
||||||
<th:block th:insert="~{fragments/head}"></th:block>
|
<th:block th:insert="~{fragments/head}"></th:block>
|
||||||
<style>
|
<link rel="stylesheet" href="/static/css/index.css">
|
||||||
.navbar-brand-custom {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-brand-custom:hover {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar {
|
|
||||||
background-color: #37bc9d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-outline-primary {
|
|
||||||
border-color: transparent;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background-color: rgba(255,255,255,.85);
|
|
||||||
color: #37bc9d;
|
|
||||||
border-color: rgba(255,255,255,.85);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary:hover {
|
|
||||||
background-color: #ffffff;
|
|
||||||
border-color: #ffffff;
|
|
||||||
color: #37bc9d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-outline-primary:hover {
|
|
||||||
background-color: rgba(255, 255, 255,0.25);
|
|
||||||
border-color: rgba(255, 255, 255,0.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-title {
|
|
||||||
font: 700 3.5em Montserrat;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-title-small {
|
|
||||||
margin-top: .7em;
|
|
||||||
font: 500 1.32em/1.4em Montserrat;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-billboard {
|
|
||||||
background-color: #37bc9d;
|
|
||||||
height: 700px;
|
|
||||||
text-align: center;
|
|
||||||
padding-top: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-button {
|
|
||||||
color: #5b5d67;
|
|
||||||
background-color: #fff;
|
|
||||||
border-color: #fff;
|
|
||||||
font: 600 1.5rem Montserrat;
|
|
||||||
padding: 0 0.9em;
|
|
||||||
height: 2.1em;
|
|
||||||
align-items: center;
|
|
||||||
display: inline-flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-button:hover {
|
|
||||||
color: #5b5d67;
|
|
||||||
background-color: rgba(255, 255, 255, 0.85);
|
|
||||||
border-color: rgba(255, 255, 255, 0.85);
|
|
||||||
font: 600 1.5rem Montserrat;
|
|
||||||
padding: 0 0.9em;
|
|
||||||
height: 2.1em;
|
|
||||||
align-items: center;
|
|
||||||
display: inline-flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-main-button {
|
|
||||||
margin-top: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-title-second {
|
|
||||||
margin-top: 1.25em;
|
|
||||||
margin-right: 0px;
|
|
||||||
margin-bottom: 1.25em;
|
|
||||||
margin-left: 0px;
|
|
||||||
font: 700 3.25em Montserrat;
|
|
||||||
color: #26272b;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.billboard-img {
|
|
||||||
box-shadow: 0 0 100px rgba(0,0,0,.33);
|
|
||||||
width: 900px;
|
|
||||||
overflow: hidden;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.billboard-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
margin-top: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
margin: 0 0 .4em;
|
|
||||||
font: 700 2em Montserrat;
|
|
||||||
}
|
|
||||||
|
|
||||||
.col_text {
|
|
||||||
font-size: 1.1em;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<th:block th:insert="~{fragments/navbar}"></th:block>
|
<th:block th:insert="~{fragments/navbar}"></th:block>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user