Fixed an issue where unknown linedef and thing flags were lost when loading the map with the wrong game configuration, or switching between game configurations in the binary map formats. Fixes #1072

This commit is contained in:
biwa 2024-07-13 16:25:30 +02:00
parent e1ce00aa84
commit d115db6897
8 changed files with 121 additions and 53 deletions

View file

@ -2553,6 +2553,16 @@ namespace CodeImp.DoomBuilder
foreach(Thing t in General.Map.Map.Things) t.TranslateToUDMF();
}
// Make sure the raw flags are up to date
if (oldiotype == typeof(DoomMapSetIO) || oldiotype == typeof(HexenMapSetIO))
{
foreach (Thing t in General.Map.map.Things)
t.UpdateRawFlagsFromFlags();
foreach (Linedef ld in General.Map.Map.Linedefs)
ld.UpdateRawFlagsFromFlags();
}
config = new GameConfiguration(configinfo.Configuration); //mxd
configinfo.ApplyDefaults(config);
General.Editing.UpdateCurrentEditModes();
@ -2607,6 +2617,16 @@ namespace CodeImp.DoomBuilder
for(int i = 0; i < t.Args.Length; i++) t.Args[i] = 0;
}
// Make sure the flags dictionary is up to date with flags that did not exist in the old game configuration
if ((oldiotype == typeof(DoomMapSetIO) || oldiotype == typeof(HexenMapSetIO)) && (io is DoomMapSetIO || io is HexenMapSetIO))
{
foreach (Thing t in General.Map.Map.Things)
t.UpdateFlagsFromRawFlags();
foreach (Linedef ld in General.Map.Map.Linedefs)
ld.UpdateFlagsFromRawFlags();
}
map.UpdateCustomLinedefColors();
// Reload resources

View file

@ -248,7 +248,7 @@ namespace CodeImp.DoomBuilder.IO
Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
if(l != null)
{
l.Update(stringflags, 0, tags, special, args);
l.Update(stringflags, 0, 0, tags, special, args);
l.UpdateCache();
// Add custom fields
@ -381,7 +381,7 @@ namespace CodeImp.DoomBuilder.IO
Thing t = map.CreateThing();
if(t != null)
{
t.Update(type, x, y, height, angledeg, pitch, roll, scaleX, scaleY, stringflags, tag, special, args);
t.Update(type, x, y, height, angledeg, pitch, roll, scaleX, scaleY, stringflags, 0, tag, special, args);
// Add custom fields
t.Fields.BeforeFieldsChange();

View file

@ -141,19 +141,18 @@ namespace CodeImp.DoomBuilder.IO
int y = reader.ReadInt16();
int angle = reader.ReadInt16();
int type = reader.ReadUInt16();
int flags = reader.ReadUInt16();
ushort flags = reader.ReadUInt16();
// Make string flags
Dictionary<string, bool> stringflags = new Dictionary<string, bool>(StringComparer.Ordinal);
foreach(KeyValuePair<string, string> f in manager.Config.ThingFlags)
{
int fnum;
if(int.TryParse(f.Key, out fnum)) stringflags[f.Key] = ((flags & fnum) == fnum);
if (int.TryParse(f.Key, out int fnum)) stringflags[f.Key] = ((flags & fnum) == fnum);
}
// Create new item
Thing t = map.CreateThing();
t.Update(type, x, y, 0, angle, 0, 0, 1.0f, 1.0f, stringflags, 0, 0, new int[Thing.NUM_ARGS]);
t.Update(type, x, y, 0, angle, 0, 0, 1.0f, 1.0f, stringflags, flags, 0, 0, new int[Thing.NUM_ARGS]);
}
// Done
@ -299,7 +298,7 @@ namespace CodeImp.DoomBuilder.IO
// Read properties from stream
int v1 = readline.ReadUInt16();
int v2 = readline.ReadUInt16();
int flags = readline.ReadUInt16();
ushort flags = readline.ReadUInt16();
int action = readline.ReadUInt16();
int tag = readline.ReadUInt16();
int s1 = readline.ReadUInt16();
@ -320,7 +319,7 @@ namespace CodeImp.DoomBuilder.IO
if(Vector2D.ManhattanDistance(vertexlink[v1].Position, vertexlink[v2].Position) > 0.0001f)
{
Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
l.Update(stringflags, 0, new List<int> { tag }, action, new int[Linedef.NUM_ARGS]);
l.Update(stringflags, flags, 0, new List<int> { tag }, action, new int[Linedef.NUM_ARGS]);
l.UpdateCache();
string thigh, tmid, tlow;
@ -440,20 +439,14 @@ namespace CodeImp.DoomBuilder.IO
// Go for all things
foreach(Thing t in map.Things)
{
// Convert flags
int flags = 0;
foreach(KeyValuePair<string, bool> f in t.Flags)
{
int fnum;
if(f.Value && int.TryParse(f.Key, out fnum)) flags |= fnum;
}
t.UpdateRawFlagsFromFlags();
// Write properties to stream
writer.Write((Int16)t.Position.x);
writer.Write((Int16)t.Position.y);
writer.Write((Int16)t.AngleDoom);
writer.Write((UInt16)t.Type);
writer.Write((UInt16)flags);
writer.Write(t.RawFlags);
}
// Find insert position and remove old lump
@ -505,18 +498,12 @@ namespace CodeImp.DoomBuilder.IO
// Go for all lines
foreach(Linedef l in map.Linedefs)
{
// Convert flags
int flags = 0;
foreach(KeyValuePair<string, bool> f in l.Flags)
{
int fnum;
if(f.Value && int.TryParse(f.Key, out fnum)) flags |= fnum;
}
l.UpdateRawFlagsFromFlags();
// Write properties to stream
writer.Write((UInt16)vertexids[l.Start]);
writer.Write((UInt16)vertexids[l.End]);
writer.Write((UInt16)flags);
writer.Write(l.RawFlags);
writer.Write((UInt16)l.Action);
writer.Write((UInt16)l.Tag);

View file

@ -143,7 +143,7 @@ namespace CodeImp.DoomBuilder.IO
int z = reader.ReadInt16();
int angle = reader.ReadInt16();
int type = reader.ReadUInt16();
int flags = reader.ReadUInt16();
ushort flags = reader.ReadUInt16();
int action = reader.ReadByte();
args[0] = reader.ReadByte();
args[1] = reader.ReadByte();
@ -155,13 +155,12 @@ namespace CodeImp.DoomBuilder.IO
Dictionary<string, bool> stringflags = new Dictionary<string, bool>(StringComparer.Ordinal);
foreach(KeyValuePair<string, string> f in manager.Config.ThingFlags)
{
int fnum;
if(int.TryParse(f.Key, out fnum)) stringflags[f.Key] = ((flags & fnum) == fnum);
if (int.TryParse(f.Key, out int fnum)) stringflags[f.Key] = ((flags & fnum) == fnum);
}
// Create new item
Thing t = map.CreateThing();
t.Update(type, x, y, z, angle, 0, 0, 1.0f, 1.0f, stringflags, tag, action, args);
t.Update(type, x, y, z, angle, 0, 0, 1.0f, 1.0f, stringflags, flags, tag, action, args);
}
// Done
@ -309,7 +308,7 @@ namespace CodeImp.DoomBuilder.IO
// Read properties from stream
int v1 = readline.ReadUInt16();
int v2 = readline.ReadUInt16();
int flags = readline.ReadUInt16();
ushort flags = readline.ReadUInt16();
int action = readline.ReadByte();
args[0] = readline.ReadByte();
args[1] = readline.ReadByte();
@ -334,7 +333,7 @@ namespace CodeImp.DoomBuilder.IO
if(Vector2D.ManhattanDistance(vertexlink[v1].Position, vertexlink[v2].Position) > 0.0001f)
{
Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
l.Update(stringflags, (flags & manager.Config.LinedefActivationsFilter), new List<int> { 0 }, action, args);
l.Update(stringflags, flags, (flags & manager.Config.LinedefActivationsFilter), new List<int> { 0 }, action, args);
l.UpdateCache();
Sidedef s;
@ -454,15 +453,8 @@ namespace CodeImp.DoomBuilder.IO
// Go for all things
foreach(Thing t in map.Things)
{
// Convert flags
int flags = 0;
foreach(KeyValuePair<string, bool> f in t.Flags)
{
int fnum;
if(f.Value && int.TryParse(f.Key, out fnum)) flags |= fnum;
}
t.UpdateRawFlagsFromFlags();
// Write properties to stream
// Write properties to stream
writer.Write((UInt16)t.Tag);
writer.Write((Int16)t.Position.x);
@ -470,7 +462,7 @@ namespace CodeImp.DoomBuilder.IO
writer.Write((Int16)t.Position.z);
writer.Write((Int16)t.AngleDoom);
writer.Write((UInt16)t.Type);
writer.Write((UInt16)flags);
writer.Write(t.RawFlags);
writer.Write((Byte)t.Action);
writer.Write((Byte)t.Args[0]);
writer.Write((Byte)t.Args[1]);
@ -526,16 +518,11 @@ namespace CodeImp.DoomBuilder.IO
// Go for all lines
foreach(Linedef l in map.Linedefs)
{
// Convert flags
int flags = 0;
foreach(KeyValuePair<string, bool> f in l.Flags)
{
int fnum;
if(f.Value && int.TryParse(f.Key, out fnum)) flags |= fnum;
}
l.UpdateRawFlagsFromFlags();
ushort flags = l.RawFlags;
// Add activates to flags
flags |= (l.Activate & manager.Config.LinedefActivationsFilter);
flags |= (ushort)(l.Activate & manager.Config.LinedefActivationsFilter);
// Write properties to stream
writer.Write((UInt16)vertexids[l.Start]);

View file

@ -220,7 +220,7 @@ namespace CodeImp.DoomBuilder.IO
Thing t = map.CreateThing();
if(t != null)
{
t.Update(type, x, y, height, angledeg, pitch, roll, scaleX, scaleY, stringflags, tag, special, args);
t.Update(type, x, y, height, angledeg, pitch, roll, scaleX, scaleY, stringflags, 0, tag, special, args);
// Custom fields
ReadCustomFields(c, t, "thing");
@ -302,7 +302,7 @@ namespace CodeImp.DoomBuilder.IO
Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
if(l != null)
{
l.Update(stringflags, 0, tags, special, args);
l.Update(stringflags, 0, 0,tags, special, args);
l.UpdateCache();
// Custom fields

View file

@ -67,6 +67,7 @@ namespace CodeImp.DoomBuilder.Map
// Properties
private Dictionary<string, bool> flags;
private ushort rawflags; // The actual flags bitmap that also might include unknown flags
private int action;
private int activate;
private List<int> tags; //mxd
@ -91,6 +92,7 @@ namespace CodeImp.DoomBuilder.Map
public Sidedef Back { get { return back; } }
public Line2D Line { get { return new Line2D(start.Position, end.Position); } }
internal Dictionary<string, bool> Flags { get { return flags; } }
public ushort RawFlags { get { return rawflags; } }
public int Action { get { return action; } set { BeforePropsChange(); action = value; UpdateColorPreset(); } }
public int Activate { get { return activate; } set { BeforePropsChange(); activate = value; UpdateColorPreset(); } }
@ -309,6 +311,7 @@ namespace CodeImp.DoomBuilder.Map
l.action = action;
l.args = (int[])args.Clone();
l.flags = new Dictionary<string, bool>(flags);
l.rawflags = rawflags;
l.tags = new List<int>(tags); //mxd
l.updateneeded = true;
l.activate = activate;
@ -316,7 +319,40 @@ namespace CodeImp.DoomBuilder.Map
l.UpdateColorPreset();//mxd
base.CopyPropertiesTo(l);
}
/// <summary>
/// Updates the raw flag bit map from the flags dictionary. Has to be called before the flags in the game config changed. Has to be called in conjunction with UpdateFlagsFromRawFlags.
/// </summary>
internal void UpdateRawFlagsFromFlags()
{
foreach (KeyValuePair<string, bool> f in flags)
{
if (ushort.TryParse(f.Key, out ushort fnum))
{
// Set bit to 0
rawflags &= (ushort)~fnum;
// Set bit if necessary
if (f.Value)
rawflags |= fnum;
}
}
}
/// <summary>
/// Updates the flags dictionary from the raw flags. Has to be called after the flags in the game config changed. Has to be called in conjunction with UpdateRawFlagsFromFlags.
/// </summary>
internal void UpdateFlagsFromRawFlags()
{
foreach (string fname in General.Map.Config.LinedefFlags.Keys)
{
if (ushort.TryParse(fname, out ushort fnum))
{
flags[fname] = (rawflags & fnum) == fnum;
}
}
}
// This attaches a sidedef on the front
internal void AttachFront(Sidedef s)
{
@ -1391,12 +1427,13 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Changes
// This updates all properties
public void Update(Dictionary<string, bool> flags, int activate, List<int> tags, int action, int[] args)
public void Update(Dictionary<string, bool> flags, ushort rawflags, int activate, List<int> tags, int action, int[] args)
{
BeforePropsChange();
// Apply changes
this.flags = new Dictionary<string, bool>(flags);
this.rawflags = rawflags;
this.tags = new List<int>(tags); //mxd
this.activate = activate;
this.action = action;

View file

@ -62,6 +62,7 @@ namespace CodeImp.DoomBuilder.Map
private int angledoom; // Angle as entered / stored in file
private double anglerad; // Angle in radians
private Dictionary<string, bool> flags;
private ushort rawflags; // The actual flags bitmap that also might include unknown flags
private int tag;
private int action;
private int[] args;
@ -110,6 +111,7 @@ namespace CodeImp.DoomBuilder.Map
public double Angle { get { return anglerad; } }
public int AngleDoom { get { return angledoom; } }
internal Dictionary<string, bool> Flags { get { return flags; } }
public ushort RawFlags { get { return rawflags; } }
public int Action { get { return action; } set { BeforePropsChange(); action = value; } }
public int[] Args { get { return args; } }
public float Size { get { return size; } }
@ -248,6 +250,7 @@ namespace CodeImp.DoomBuilder.Map
t.spritescale = spritescale; //mxd
t.pos = pos;
t.flags = new Dictionary<string,bool>(flags);
t.rawflags = rawflags;
t.tag = tag;
t.action = action;
t.args = (int[])args.Clone();
@ -263,6 +266,39 @@ namespace CodeImp.DoomBuilder.Map
base.CopyPropertiesTo(t);
}
/// <summary>
/// Updates the raw flag bit map from the flags dictionary. Has to be called before the flags in the game config changed. Has to be called in conjunction with UpdateFlagsFromRawFlags.
/// </summary>
internal void UpdateRawFlagsFromFlags()
{
foreach (KeyValuePair<string, bool> f in flags)
{
if (ushort.TryParse(f.Key, out ushort fnum))
{
// Set bit to 0
rawflags &= (ushort)~fnum;
// Set bit if necessary
if (f.Value)
rawflags |= fnum;
}
}
}
/// <summary>
/// Updates the flags dictionary from the raw flags. Has to be called after the flags in the game config changed. Has to be called in conjunction with UpdateRawFlagsFromFlags.
/// </summary>
internal void UpdateFlagsFromRawFlags()
{
foreach (string fname in General.Map.Config.ThingFlags.Keys)
{
if (ushort.TryParse(fname, out ushort fnum))
{
flags[fname] = (rawflags & fnum) == fnum;
}
}
}
// This determines which sector the thing is in and links it
public void DetermineSector()
{
@ -544,7 +580,7 @@ namespace CodeImp.DoomBuilder.Map
// This updates all properties
// NOTE: This does not update sector! (call DetermineSector)
public void Update(int type, double x, double y, double zoffset, int angle, int pitch, int roll, double scaleX, double scaleY,
Dictionary<string, bool> flags, int tag, int action, int[] args)
Dictionary<string, bool> flags, ushort rawflags, int tag, int action, int[] args)
{
// Apply changes
this.type = type;
@ -555,6 +591,7 @@ namespace CodeImp.DoomBuilder.Map
this.scaleX = (scaleX == 0 ? 1.0f : scaleX); //mxd
this.scaleY = (scaleY == 0 ? 1.0f : scaleY); //mxd
this.flags = new Dictionary<string, bool>(flags);
this.rawflags = rawflags;
this.tag = tag;
this.action = action;
this.args = new int[NUM_ARGS];

View file

@ -228,7 +228,7 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode
{
// We need to update the linedef's args, but we can't do it directly because otherwise their state will not be saved for the undo snapshot,
// so we're using the linedef's update method
sd.Line.Update(sd.Line.GetFlags(), sd.Line.Activate, sd.Line.Tags, sd.Line.Action, new int[] { sd.Line.Args[0], type, flags, alpha, sd.Line.Args[4] });
sd.Line.Update(sd.Line.GetFlags(), sd.Line.RawFlags, sd.Line.Activate, sd.Line.Tags, sd.Line.Action, new int[] { sd.Line.Args[0], type, flags, alpha, sd.Line.Args[4] });
}
}
}