summaryrefslogtreecommitdiffhomepage
path: root/server.rb
blob: 139ea9b69bb7bcad1317ba84b8ae46223b82f6ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
require 'socket'

class Player
  attr_accessor :color, :x, :y, :port

  def initialize(port, color)
    @port = port
    @color = color
    @x = 0
    @y = 0
  end
end
change = false
threads = []

# Ctrl-c will kill threads
at_exit do
  puts 'trapping'
  threads.each do |t|
    puts 'killing'
    Thread.kill t
  end
end

# this gurantees something you choose will not be executed more then 60 times a second
def once_per_frame
  last = Time.now
  while true
    yield
    now = Time.now
    _next = [last + (1 / 60), now].max
    sleep(_next - now)
    last = _next
  end
end

semaphore = Mutex.new

players = []

#Socket.do_not_reverse_lookup = true
s = UDPSocket.new
s.bind(nil, 4000)

#reciever
threads.push(Thread.new do
  loop do
    text, _sender = s.recvfrom(16)
    temp = text.split(' ')
    # if new connection
    # format: "0 #{port}"
    if temp[0] == '0'
      semaphore.synchronize do
        players.push Player.new(temp[1], 'red')#colors.delete(colors.sample))
        s.send("0 #{players.last.color}", 0, 'localhost', temp[1])
      end
    #else if player updating their position
    # format: "1 #{port} #{x}-#{y}"
    elsif temp[0] == '1'
      semaphore.synchronize do
        user = players.select { |player| player.port == temp[1] }
        # something changed, inform sender to send update
        if (user.first.x != temp[2].split('-')[0]) && (user.first.x != temp[2].split('-')[0])
          user.first.x = temp[2].split('-')[0]
          user.first.y = temp[2].split('-')[1]
          change = true
        end
      end
    end
  end
end)

#sender
threads.push(Thread.new do
  once_per_frame do
    semaphore.synchronize do
      # only if something changed should you send an update
      if change
        change = false
        players.each do |target|
          players.each do |player, _str|
            s.send("#{player.color}-#{player.x}-#{player.y}", 0, 'localhost', target.port)
          end
        end
      end
    end
  end
end)

#prevents threads of going to background
loop do
  sleep 2
end