我是RSocket世界的新手。 你能告诉我如何将消息从服务器发送到 javascript(Angular) 应用程序中的特定观察者吗?我正在创建多人吃豆人游戏,我必须将怪物位置从服务器发送到客户端。我想在其他地方执行此操作,然后是控制器。我知道如何在 spring 到 spring 应用程序中执行此操作,因为我们可以使用 RsocketRequester.route() 将消息发送到客户端的特定端点,但我不知道如何在 js 环境中创建类似的东西。更准确地说,我想在 websocket ( + STOMP) 中做同样的事情。这是示例:
在这里我有确切的端点。我可以使用 SimpleMessagingTemplate( 在每个地方) 发送消息,但是如何在 rsocket 中做类似的事情?客户端:
const ws = new SockJS(this.serverUrl);
this.stompClient = Stomp.over(ws);
this.state = new BehaviorSubject<SocketClientState>(SocketClientState.ATTEMPTING);
this.stompClient.connect({}, (frame) => {
this.stompClient.subscribe('/pacman/update/monster', (monster) => {
if (monster.body) {
this.monsterToUpdate.next(JSON.parse(monster.body));
}
});
// other code ...
this.state.next(SocketClientState.CONNECTED);
}, (error) => {
this.state.next(SocketClientState.ERROR);
});
在 RSocket (js) 中,请求看起来像这样,例如,只有当我们在控制器中处理请求时,我们才能轻松地从服务器订阅响应。(控制器知道将响应发送到哪里)
socket.requestStream({
data: {
'author': 'linustorvalds'
},
metadata: String.fromCharCode('tweets'.length) + 'tweets',
}).subscribe({
onComplete: () => console.log('complete'),
onError: error => {
console.log(error);
},
onNext: payload => {
console.log(payload.data);
},
onSubscribe: subscription => {
console.error('Subskrybuje')
subscription.request(2147483647);
},
});
服务器
@Service
public class GameObjectSender implements ISender {
private final SimpMessagingTemplate template;
public GameObjectSender(SimpMessagingTemplate template) {
this.template = template;
}
@Override
public void send(String destination, GameObject gameObject) {
// Here i want to send monster position using RScoket
this.template.convertAndSend(destination, gameObject);
}
@Override
public void sendWithTimestamp(String destination, GameObject gameObject) {
// Here i want to send monster position using RScoket
this.template.convertAndSend(destination, gameObject, Map.of("timestamp", System.currentTimeMillis()));
}
}
在这里,我可以使用 SimpMessagingTemplate 将消息发送到特定位置,例如“/pacman/update/monster”(js)。怪物的应用流程看起来像(在服务中创建 5 个线程,它们移动并将所有时间位置发送到客户端(GameObjectSender 在这里注入)):
服务器:
private void createMonsters() {
for (int i = 0; i < Game.NUMBER_OF_MONSTERS; i++) {
int[] position = positionSetterService.getStartPositionForFigure();
Game.getGame().getMonsters().add(new Monster(i, position[0], position[1], Direction.NONE));
new Thread(() -> {
int idMonster = Integer.parseInt(Thread.currentThread().getName());
logger.info("Stworzylem potwora o id: " + idMonster);
Monster monster = Game.getGame().getMonsters().get(idMonster);
while (true) {
try {
Thread.sleep(50);
move(monster);
} catch (InterruptedException e) {
logger.error("Przerwano watek potwora");
Thread.currentThread().interrupt();
}
}
}, String.valueOf(i)).start();
}
}
@Override
public void move(Monster monster) {
int[] position = chasePlayer(monster);
if (spriteCollisionService.checkCollisionWithMonsters(position[0], position[1])) {
position[0] = position[0] - (position[0] % 32) + 16;
position[1] = position[1] - (position[1] % 32) + 16;
}
monster.setPositionX(position[0]);
monster.setPositionY(position[1]);
Optional<Player> playerToRemove = spriteCollisionService.getPlayerWhoCollideWithMonster(position[0], position[1]);
if (playerToRemove.isPresent()) {
resetPreviousDirection();
logger.info("Monster wpada na Gracza i go zabija");
Game.getGame().getPlayers().remove(playerToRemove.get());
this.spriteSender.send("/pacman/remove/player", playerToRemove.get());
}
synchronized (Game.getGame().getMonsters()) {
Game.getGame().getMonsters().remove(monster);
Game.getGame().getMonsters().add(monster);
}
this.spriteSender.send("/pacman/update/monster", monster);
}