-
Notifications
You must be signed in to change notification settings - Fork 50
Expand file tree
/
Copy pathtic.pl
More file actions
executable file
·179 lines (150 loc) · 6.07 KB
/
tic.pl
File metadata and controls
executable file
·179 lines (150 loc) · 6.07 KB
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#!/usr/bin/perl
#############################
# Tic v0.8.1 #
# Created by Josh McDougall #
#############################
# The Ticker is a continuous daemon; it is good to run it within a
# screen/tmux session
# Set output to autoflush
$| = 1;
# use module
use DBI;
use DateTime;
### Capture configuration from environment
my ($pgport, $pghost, $pgdatabase, $pguser, $sleeptime) =
($ENV{"PGPORT"}, $ENV{"PGHOST"}, $ENV{"PGDATABASE"}, $ENV{"PGUSER"}, $ENV{"SCHEMAVERSESLEEP"});
if (length($pgdatabase) < 1) {
die "Database not specified via environment variable PGDATABASE\n";
}
if (length($pguser) < 1) {
die "Master user not specified via environment variable PGUSER\n";
}
if ($sleeptime < 1) {
print "No value provided for SCHEMAVERSESLEEP - using 60 to sleep 60s between rounds\n";
$sleeptime = 60;
}
my $masteruser = $pguser;
printf ("Schemaverse: Launching tic.pl\n");
$db_uri = "dbi:Pg:dbname=${pgdatabase}";
printf (" URI being used: %s\n", $db_uri);
printf (" PGPORT: %d PGHOST: %s PGDATABASE: %s PGUSER: %s\n", $pgport, $pghost, $pgdatabase, $pguser);
printf (" SCHEMAVERSESLEEP: %d \n", $sleeptime);
my $turn = 0;
while (1) {
$turn++;
my $tnow = DateTime->now(time_zone=>'local');
printf ("Processing turn %d, starting at %s\n", $turn, $tnow->datetime);
# Establish master database connection
my $master_connection = DBI->connect($db_uri, $masteruser);
$master_connection->do('SELECT ROUND_CONTROL();');
# Move the rest of the ships in whatever direction they have specified
my $sql = "
BEGIN WORK;
LOCK TABLE ship, ship_control IN EXCLUSIVE MODE;
SELECT MOVE_SHIPS();
COMMIT WORK;
";
$master_connection->do($sql);
# Retrieve Fleet Scripts and run them as the user they belong to
my $sql = "
SELECT
player.id as player_id,
player.username as username,
fleet.id as fleet_id,
player.error_channel as error_channel
FROM
fleet, player
WHERE
fleet.player_id=player.id
AND
fleet.enabled='t'
AND
fleet.runtime > '0 minutes'::interval
ORDER BY
player.username;
";
my $fleet_fail_event = $master_connection->prepare("INSERT INTO event(tic,action,player_id_1,referencing_id,descriptor_string) VALUES ((SELECT last_value FROM tic_seq),'FLEET_FAIL',?,?,?)");
my $rs = $master_connection->prepare($sql);
$rs->execute();
$temp_user = '';
my $fleetcount=0;
while (($player_id, $player_username, $fleet_id, $error_channel) = $rs->fetchrow()) {
$fleetcount++;
if ($temp_user ne $player_username)
{
if ($temp_user ne '')
{
$temp_connection->disconnect();
}
$temp_user = $player_username;
$temp_connection = DBI->connect($db_uri, $player_username);
$temp_connection->{PrintError} = 0;
$temp_connection->{RaiseError} = 1;
}
#$temp_connection->{application_name} = $fleet_id;
$temp_connection->do("SET application_name TO ${fleet_id}");
eval { $temp_connection->do("SELECT RUN_FLEET_SCRIPT(${fleet_id})"); };
if( $@ ) {
$temp_connection->do("NOTIFY ${error_channel}, 'Fleet script ${fleet_id} has failed to fully execute during the tic'; ");
# $fleet_fail_event->execute($player_id,$fleet_id,$@);
}
}
if ($temp_user ne '') {
$temp_connection->disconnect();
}
$rs->finish;
printf ("Processed %d fleet scripts\n", $fleetcount);
my $sql = "
BEGIN WORK;
LOCK TABLE ship, ship_control IN EXCLUSIVE MODE;
SELECT
CASE
WHEN ship_control.action = 'ATTACK' THEN ATTACK(ship.id, ship_control.action_target_id)::integer
WHEN ship_control.action = 'REPAIR' THEN REPAIR(ship.id, ship_control.action_target_id)::integer
WHEN ship_control.action = 'MINE' THEN MINE(ship.id, ship_control.action_target_id)::integer
ELSE NULL END
FROM
ship, ship_control
WHERE
ship.id = ship_control.ship_id
AND
ship_control.action IS NOT NULL
AND
ship_control.action_target_id IS NOT NULL
AND
ship.destroyed='f'
AND
ship.last_action_tic != (SELECT last_value FROM tic_seq);
COMMIT WORK; ";
$master_connection->do($sql);
$master_connection->do("lock table planet_miners;SELECT perform_mining();");
#dirty planet renewal hack
$master_connection->do("UPDATE planet SET fuel=fuel+1000000 WHERE id in (select id from planet where fuel < 10000000 order by RANDOM() LIMIT 5000);");
#future_health is dealt with
$master_connection->do("BEGIN WORK;
LOCK TABLE ship, ship_control IN EXCLUSIVE MODE;
create temp table t_ship_updates (id integer, current_health integer, future_health integer, max_health integer, last_living_tic integer, destroyed boolean, player_id integer);
insert into t_ship_updates (id, current_health, future_health, max_health, last_living_tic, destroyed, player_id)
select id, current_health, future_health, max_health, last_living_tic, destroyed, player_id
from ship;
UPDATE t_ship_updates SET current_health=max_health WHERE future_health >= max_health and current_health <> max_health;
UPDATE t_ship_updates SET current_health=future_health WHERE future_health between 0 and max_health and current_health <> max_health;
UPDATE t_ship_updates SET current_health=0 WHERE future_health < 0 and current_health <> 0;
UPDATE t_ship_updates SET last_living_tic=(SELECT last_value FROM tic_seq) WHERE current_health > 0;
UPDATE t_ship_updates SET destroyed='t' WHERE ((SELECT last_value FROM tic_seq)-last_living_tic)>GET_NUMERIC_VARIABLE('EXPLODED') and player_id > 0;
create index t_id on t_ship_updates (id);
update ship s
set current_health = (select current_health from t_ship_updates where id = s.id),
last_living_tic = (select last_living_tic from t_ship_updates where id = s.id),
destroyed = (select destroyed from t_ship_updates where id = s.id);
cluster ship_pkey on ship;
COMMIT WORK;");
$master_connection->do("vacuum ship;");
#Update some stats now and then
#$master_connection->do("insert into stat_log select * from current_stats WHERE mod(current_tic,5)=0;");
$master_connection->do("INSERT INTO event(player_id_1, action, tic, public) VALUES(0,'TIC',(SELECT last_value FROM tic_seq),'t')");
#Tic is increased to NEXTVAL
$master_connection->do("SELECT nextval('tic_seq')");
$master_connection->disconnect();
sleep($sleeptime);
}