ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/gde/GCE/ArchRef.pm
Revision: 1.3
Committed: Tue Dec 5 15:21:51 2006 UTC (17 years, 6 months ago) by elmex
Branch: MAIN
Changes since 1.2: +8 -3 lines
Log Message:
handling undefined archetypes now more gracefully by defaulting
it's type to 'empty_archetype' and opening a error dialog to inform
the user about the inconsistent map.

File Contents

# Content
1 package GCE::ArchRef;
2 =head1 NAME
3
4 GCE::ArchRef - a intelligent reference to an arch instance on/in the map
5
6 =head1 SYNOPSIS
7
8 GCE::ArchRef->new (arch => <hashref>, cb => <changecb>)
9
10 =over 4
11
12 =cut
13
14 use Storable qw/dclone/;
15 use Crossfire;
16 use Carp;
17 use GCE::Util;
18
19 sub getarch {
20 my ($ar) = @_;
21
22 if (ref $ar eq 'GCE::ArchRef') {
23 return $ar->{arch}
24 } else {
25 return $ar
26 }
27 }
28
29 sub new {
30 my $class = shift;
31 my $self = { @_ };
32 bless $self, $class;
33
34 unless (defined $self->{arch}) {
35 Carp::confess ("arch not defined when making new ArchRef")
36 }
37 unless (defined $Crossfire::ARCH{$self->getarch->{_name}}) {
38 quick_msg (
39 $::MAINWIN,
40 "ERROR: No such archetype '" . ($self->getarch->{_name})
41 ."' replacing it's type with 'empty_archetype'.",
42 0
43 );
44 }
45
46 return $self;
47 }
48
49 sub type {
50 my ($self) = @_;
51 Crossfire::arch_attr $self->getarch;
52 }
53
54 sub archetype {
55 my ($self) = @_;
56
57 $Crossfire::ARCH{$self->getarch->{_name}} || $Crossfire::ARCH{empty_archetype};
58 }
59
60 sub longname {
61 my ($self) = @_;
62
63 my $name = $self->get ('_name');
64 my $rname = $self->get ('name');
65 my $t = $self->type;
66
67 $name . ($rname ? " - $rname" : "") . " ($t->{name})"
68 }
69
70 sub field_value_is_default {
71 my ($self, $key, $val) = @_;
72 my $al_arch = $self->archetype;
73
74 # XXX: Was '... and $val', does this fix problems?
75 (defined $al_arch->{$key} and $al_arch->{$key} ne $val)
76 || (not (defined $al_arch->{$key}) and $val)
77 }
78
79 sub add_inv {
80 my ($self, $arch) = @_;
81 push @{$self->{arch}->{inventory}}, dclone (getarch $arch);
82
83 $self->{cb}->($self)
84 if defined $self->{cb};
85
86 $self->exec_change_cbs (qw/inventory/);
87 }
88
89 sub swap_inv {
90 my ($self, $swapidx, $ownidx) = @_;
91 my $inv = $self->getarch->{inventory};
92
93 ($inv->[$swapidx], $inv->[$ownidx])
94 = ($inv->[$ownidx], $inv->[$swapidx]);
95
96 $self->{cb}->($self)
97 if defined $self->{cb};
98
99 $self->exec_change_cbs (qw/inventory/);
100 }
101
102 sub get_inv_refs {
103 my ($self) = @_;
104
105 my $cb = sub {
106 $self->{cb}->($self)
107 if defined $self->{cb};
108
109 $self->exec_change_cbs (qw/inventory/);
110 };
111
112 [ map { GCE::ArchRef->new (arch => $_, cb => $cb) } @{$self->get ('inventory') || []} ]
113 }
114
115 sub replace_inv {
116 my ($self, $idx, $new) = @_;
117 splice @{$self->getarch->{'inventory'}}, $idx, 1, $new;
118
119 $self->{cb}->($self)
120 if defined $self->{cb};
121
122 $self->exec_change_cbs (qw/inventory/);
123 }
124
125 sub remove_inv {
126 my ($self, $idx) = @_;
127 splice @{$self->getarch->{'inventory'}}, $idx, 1;
128
129 $self->{cb}->($self)
130 if defined $self->{cb};
131
132 $self->exec_change_cbs (qw/inventory/);
133 }
134
135 sub reset_to_defaults {
136 my ($self) = @_;
137
138 my $arch = $self->getarch;
139 for (keys %$arch) {
140 delete $arch->{$_} if $_ ne '_name'
141 }
142
143 $self->{cb}->($self)
144 if defined $self->{cb};
145
146 $self->exec_change_cbs;
147 }
148
149 sub get {
150 my ($self, $key) = @_;
151 $self->getarch->{$key}
152 }
153
154 sub get_or_default {
155 my ($self, $key) = @_;
156 def ($self->get ($key), $self->archetype->{$key})
157 }
158
159 sub set_silent {
160 my ($self, $key, $value) = @_;
161
162 my $arch = $self->getarch;
163 my $al_arch = $self->archetype;
164
165 if (ref $value) {
166 $arch->{$key} = $value;
167
168 } else {
169 if (not defined $al_arch->{$key}) {
170 if (not defined $value) {
171 # try to normalize
172 delete $arch->{$key};
173 } else {
174 # try to normalize
175 $arch->{$key} = $value;
176 }
177 } else {
178 if ($al_arch->{$key} ne $value) {
179 $arch->{$key} = $value;
180 } else {
181 # try to normalize
182 delete $arch->{$key};
183 }
184 }
185 }
186
187 $self->{cb}->($arch)
188 if defined $self->{cb};
189 }
190
191 sub set {
192 my ($self, $key, $value) = @_;
193 $self->set_silent ($key, $value);
194
195 $self->exec_change_cbs ($key);
196 }
197
198 sub remove_on_change {
199 my ($self, $key) = @_;
200 delete $self->{change_cbs}->{$key};
201 }
202
203 sub add_on_change {
204 my ($self, $key, $cb) = @_;
205 $self->{change_cbs}->{$key} = $cb;
206 }
207
208 sub exec_change_cbs {
209 my ($self, @a) = @_;
210 $_->($self, @a) for (values %{$self->{change_cbs}});
211 }
212
213 =head1 AUTHOR
214
215 Marc Lehmann <schmorp@schmorp.de>
216 http://home.schmorp.de/
217
218 Robin Redeker <elmex@ta-sa.org>
219 http://www.ta-sa.org/
220
221 =cut
222 1;