ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/gde/GCE/ArchRef.pm
Revision: 1.10
Committed: Wed Dec 16 17:25:27 2009 UTC (14 years, 5 months ago) by elmex
Branch: MAIN
CVS Tags: HEAD
Changes since 1.9: +6 -0 lines
Log Message:
handle default move types correctly.

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 Deliantra;
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 $Deliantra::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 Deliantra::arch_attr $self->getarch;
52 }
53
54 sub archetype {
55 my ($self) = @_;
56
57 $Deliantra::ARCH{$self->getarch->{_name}} || $Deliantra::ARCH{empty_archetype};
58 }
59
60 sub picker_folder {
61 my ($self) = @_;
62 my $folder = $self->archetype->{editor_folder};
63 my @a = split /\//, $folder;
64 $a[0]
65 }
66
67 sub longname {
68 my ($self) = @_;
69
70 my $name = $self->get ('_name');
71 my $rname = $self->get ('name');
72 my $t = $self->type;
73
74 $name . ($rname ? " - $rname" : "") . " ($t->{name})"
75 }
76
77 sub field_value_is_default {
78 my ($self, $key, $val) = @_;
79 my $al_arch = $self->archetype;
80
81 # XXX: Was '... and $val', does this fix problems?
82 (defined ($al_arch->{$key}) && $al_arch->{$key} ne $val)
83 || (not (defined $al_arch->{$key}) and $val)
84 }
85
86 sub add_inv {
87 my ($self, $arch) = @_;
88 push @{$self->{arch}->{inventory}}, dclone (getarch $arch);
89
90 $self->{cb}->($self)
91 if defined $self->{cb};
92
93 $self->exec_change_cbs (qw/inventory/);
94 }
95
96 sub swap_inv {
97 my ($self, $swapidx, $ownidx) = @_;
98 my $inv = $self->getarch->{inventory};
99
100 ($inv->[$swapidx], $inv->[$ownidx])
101 = ($inv->[$ownidx], $inv->[$swapidx]);
102
103 $self->{cb}->($self)
104 if defined $self->{cb};
105
106 $self->exec_change_cbs (qw/inventory/);
107 }
108
109 sub get_inv_refs {
110 my ($self) = @_;
111
112 my $cb = sub {
113 $self->{cb}->($self)
114 if defined $self->{cb};
115
116 $self->exec_change_cbs (qw/inventory/);
117 };
118
119 [ map { GCE::ArchRef->new (arch => $_, source => 'inventory', cb => $cb) } @{$self->get ('inventory') || []} ]
120 }
121
122 sub replace_inv {
123 my ($self, $idx, $new) = @_;
124 splice @{$self->getarch->{'inventory'}}, $idx, 1, $new;
125
126 $self->{cb}->($self)
127 if defined $self->{cb};
128
129 $self->exec_change_cbs (qw/inventory/);
130 }
131
132 sub remove_inv {
133 my ($self, $idx) = @_;
134 splice @{$self->getarch->{'inventory'}}, $idx, 1;
135
136 $self->{cb}->($self)
137 if defined $self->{cb};
138
139 $self->exec_change_cbs (qw/inventory/);
140 }
141
142 sub reset_to_defaults {
143 my ($self) = @_;
144
145 my $arch = $self->getarch;
146 for (keys %$arch) {
147 delete $arch->{$_} if $_ ne '_name'
148 }
149
150 $self->{cb}->($self)
151 if defined $self->{cb};
152
153 $self->exec_change_cbs;
154 }
155
156 sub get {
157 my ($self, $key) = @_;
158 $self->getarch->{$key}
159 }
160
161 sub get_or_default {
162 my ($self, $key) = @_;
163 def ($self->get ($key), $self->archetype->{$key})
164 }
165
166 sub set_silent {
167 my ($self, $key, $value, $type) = @_;
168
169 my $arch = $self->getarch;
170 my $al_arch = $self->archetype;
171
172 if (ref $value) {
173 $arch->{$key} = $value;
174
175 } elsif (not defined $value) {
176 # this is introduced so that move types are correctly handled.
177 # but it also makes incredible sense to me to delete attributes with
178 # undef values!
179 delete $arch->{$key};
180
181 } else {
182 if (not defined $al_arch->{$key}) {
183 if ((not defined $value) || $value eq ''
184 || ($type eq 'bool' && $value eq '0')) {
185 # try to normalize
186 delete $arch->{$key};
187 } else {
188 # try to normalize
189 $arch->{$key} = $value;
190 }
191 } else {
192 if ($al_arch->{$key} ne $value) {
193 $arch->{$key} = $value;
194 } else {
195 # try to normalize
196 delete $arch->{$key};
197 }
198 }
199 }
200
201 $self->{cb}->($arch)
202 if defined $self->{cb};
203 }
204
205 sub set {
206 my ($self, $key, $value, $type) = @_;
207 $self->set_silent ($key, $value, $type);
208
209 $self->exec_change_cbs ($key);
210 }
211
212 sub remove_on_change {
213 my ($self, $key) = @_;
214 delete $self->{change_cbs}->{$key};
215 }
216
217 sub add_on_change {
218 my ($self, $key, $cb) = @_;
219 $self->{change_cbs}->{$key} = $cb;
220 }
221
222 sub exec_change_cbs {
223 my ($self, @a) = @_;
224 $_->($self, @a) for (values %{$self->{change_cbs}});
225 }
226
227 =head1 AUTHOR
228
229 Marc Lehmann <schmorp@schmorp.de>
230 http://home.schmorp.de/
231
232 Robin Redeker <elmex@ta-sa.org>
233 http://www.ta-sa.org/
234
235 =cut
236 1;