ch.rasc.wampspring.demo.various.snake.SnakeService.java Source code

Java tutorial

Introduction

Here is the source code for ch.rasc.wampspring.demo.various.snake.SnakeService.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package ch.rasc.wampspring.demo.various.snake;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import ch.rasc.wampspring.EventMessenger;
import ch.rasc.wampspring.annotation.WampCallListener;
import ch.rasc.wampspring.annotation.WampSubscribeListener;
import ch.rasc.wampspring.annotation.WampUnsubscribeListener;

/**
 * Sets up the timer for the multi-player snake game WebSocket example.
 */
@Service
public class SnakeService {

    private final ConcurrentHashMap<Integer, Snake> snakes = new ConcurrentHashMap<>();

    private final EventMessenger eventMessenger;

    private Timer gameTimer;

    private final SnakeId currentSnakeId;

    @Autowired
    public SnakeService(SnakeId currentSnakeId, EventMessenger eventMessenger) {
        this.eventMessenger = eventMessenger;
        this.currentSnakeId = currentSnakeId;
    }

    @WampSubscribeListener(value = "snake", replyTo = "snake")
    public synchronized SnakeMessage addSnake() {
        Snake newSnake = new Snake(this.currentSnakeId);
        if (this.snakes.isEmpty()) {
            startTimer();
        }
        this.snakes.put(newSnake.getId(), newSnake);

        return SnakeMessage.createJoinMessage(createJoinData());
    }

    @WampUnsubscribeListener(value = "snake", replyTo = "snake")
    public synchronized SnakeMessage removeSnake() {
        try {
            Integer snakeId = this.currentSnakeId.getId();
            if (snakeId != null) {
                this.snakes.remove(snakeId);
                if (this.snakes.isEmpty()) {
                    if (this.gameTimer != null) {
                        this.gameTimer.cancel();
                        this.gameTimer = null;
                    }
                }

                return SnakeMessage.createLeaveMessage(snakeId);
            }
        } catch (BeanCreationException e) {
            // A websocket session was destroyed from another example
            // The other example does not have the scope snakeId in it's session
            // so a call to currentSnakeId.getId() throws an error
        }

        return null;
    }

    public void startTimer() {
        this.gameTimer = new Timer(SnakeService.class.getSimpleName() + " Timer");
        this.gameTimer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                tick();

            }
        }, 100, 100);
    }

    public void tick() {
        Collection<Snake> allSnakes = getSnakes();
        List<Map<String, Object>> updateData = new ArrayList<>();
        for (Snake snake : allSnakes) {
            snake.update(allSnakes, this.eventMessenger);

            Map<String, Object> locationsData = snake.getLocationsData();
            if (locationsData != null) {
                updateData.add(locationsData);
            }
        }

        if (!updateData.isEmpty()) {
            this.eventMessenger.sendToAll("snake", SnakeMessage.createUpdateMessage(updateData));
        }
    }

    private Collection<Snake> getSnakes() {
        return Collections.unmodifiableCollection(this.snakes.values());
    }

    public List<Map<String, Object>> createJoinData() {
        List<Map<String, Object>> result = new ArrayList<>();
        for (Snake snake : getSnakes()) {
            Map<String, Object> es = new HashMap<>();
            es.put("id", snake.getId());
            es.put("color", snake.getHexColor());
            result.add(es);
        }
        return result;
    }

    @WampCallListener
    public void changeDirection(String message) {
        Snake snake = this.snakes.get(this.currentSnakeId.getId());
        if (snake != null) {
            if ("west".equals(message)) {
                snake.setDirection(Direction.WEST);
            } else if ("north".equals(message)) {
                snake.setDirection(Direction.NORTH);
            } else if ("east".equals(message)) {
                snake.setDirection(Direction.EAST);
            } else if ("south".equals(message)) {
                snake.setDirection(Direction.SOUTH);
            }
        }
    }

}