У меня есть проблема с дизайном / реализацией, которую я просто не могу обдумать.В настоящее время я работаю над текстовой игрой с несколькими игроками.Я вроде понимаю, как это работает для Player-to-Server, я имел в виду, что Server видит каждого игрока как одного и того же.
Я использую spring-boot 2, spring-web, thymeleaf, hibernate.
Я реализовал пользовательский UserDetails
, который возвращается после входа пользователя в систему.
@Entity
@Table(name = "USER")
public class User implements Serializable {
@Id
private long userId;
@Column(unique = true, nullable = false)
private String userName;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "playerStatsId")
private PlayerStats stats;
}
public class CurrentUserDetailsService implements UserDetailsService {
@Override
public CurrentUser loadUserByUsername(String userName) {
User user = this.accountRepository.findByUserName(userName)
.orElseThrow(() ->
new UsernameNotFoundException("User details not found with the provided username: " + userName));
return new CurrentUser(user);
}
}
public class CurrentUser implements UserDetails {
private static final long serialVersionUID = 1L;
private User user = new User();
public CurrentUser(User user) {
this.user = user;
}
public PlayerStats getPlayerStats() {
return this.user.getStats();
}
// removed the rest for brevity
}
Следовательно, в моем контроллере я могу сделать это, чтобы получить CurrentUser
.* Обратите внимание, что каждый пользователь также является игроком.
@GetMapping("/attackpage")
public String viewAttackPage(@AuthenticationPrincipal CurrentUser currentUser) {
// return the page view for list of attacks
return "someview";
}
Значение currentUser
будет отображаться для текущего пользователя (скажем, 1 или 2, 3 и т. Д.).Это прекрасно работает для большинства вещей, происходящих с самим собой, таких как покупка некоторых вещей, обновление профиля и так далее.Но чего я не могу получить или не знаю, как этого добиться, это , когда 2 игрока взаимодействуют .
Например, Игрок 1 атакует Игрока 2. Если я Игрок 1, я должен нажать «Атака» в представлении, выбрать Игрока 2 и отправить команду.Следовательно, в контроллере это будет что-то вроде этого.
@GetMapping("/attack")
public String launchAttack(@AuthenticationPrincipal CurrentUser currentUser, @RequestParam("playername") String player2) {
updatePlayerState(player2);
return "someview";
}
public void updatePlayerState(String player) {
User user = getUserByPlayername(player);
// perform some update to player state (say health, etc)
// update back to db?
}
Вот что действительно меня запутало.Как было показано ранее, когда каждый пользователь / игрок входит в систему, набор текущего состояния пользователя (игрока) будет извлечен из БД и сохранен «в памяти».Следовательно, когда Игрок 1 атакует Игрока 2,
Как «уведомить» или обновить Игрока 2, что статистика изменилась, и, таким образом, Игрок 2 должен вытянуть обновленную статистику из БД в память,
Как решить возможную проблему параллелизма здесь?Например, здоровье игрока 2 составляет 50 в БД.Затем игрок 2 выполняет некоторое действие (скажем, приобретает зелье здоровья + 30), которое затем обновляет базу данных (здоровье до 80).Однако непосредственно перед обновлением БД Player 1 уже запустил атаку и извлекает из БД состояние Player 2, где он вернет 50, поскольку БД еще не обновлен.Так что теперь любые изменения, сделанные в getUserByPlayername()
и обновлении БД, будут неверными, и все состояние проигрывателя будет «не синхронизировано».Я надеюсь, что здесь есть смысл.
Я понимаю, что в спящем режиме @Version
для оптимистической блокировки, но я не уверен, применимо ли это в этом случае.И будет ли Spring-Session полезен в таком случае?
Не следует ли хранить какие-либо данные в памяти при входе пользователя?Должен ли я всегда получать данные из БД только при выполнении какого-либо действия?Вроде когда viewProfile, то я вытаскиваю из accountRepository.или когда viewStats тогда я вытащил из statsRepository и так далее.
Направь меня в правильном направлении.Был бы признателен за любой конкретный пример рода, или какое-то видео / статьи.Если потребуется какая-либо дополнительная информация, дайте мне знать, и я постараюсь объяснить мой случай лучше.
Спасибо.