mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-23 04:32:50 -04:00
Move appropriate functions into UndoDrawOp and HighlightDrawOp, split UndoPhysicsDrawOp into separate file.
This commit is contained in:
parent
e09d1efddc
commit
1b86b30b4c
@ -1,99 +0,0 @@
|
||||
/*
|
||||
Copyright 2015 MCGalaxy
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCGalaxy.Maths;
|
||||
|
||||
namespace MCGalaxy.Undo {
|
||||
|
||||
/// <summary> Retrieves and saves undo data in a particular format. </summary>
|
||||
/// <remarks> Note most formats only support retrieving undo data. </remarks>
|
||||
public abstract partial class UndoFormat {
|
||||
|
||||
public static void DoUndo(string target, ref bool found, UndoFormatArgs args) {
|
||||
List<string> files = GetUndoFiles(target);
|
||||
if (files.Count == 0) return;
|
||||
found = true;
|
||||
|
||||
foreach (string file in files) {
|
||||
using (Stream s = File.OpenRead(file)) {
|
||||
DoUndo(s, GetFormat(file), args);
|
||||
if (args.Stop) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DoUndo(Stream s, UndoFormat format, UndoFormatArgs args) {
|
||||
Level lvl = args.Player == null ? null : args.Player.level;
|
||||
string lastMap = null;
|
||||
Vec3S32 min = args.Min, max = args.Max;
|
||||
DrawOpBlock block;
|
||||
|
||||
foreach (UndoFormatEntry P in format.GetEntries(s, args)) {
|
||||
if (P.LevelName != lastMap) lvl = LevelInfo.FindExact(P.LevelName);
|
||||
if (lvl == null || P.Time > args.End) continue;
|
||||
if (P.X < min.X || P.Y < min.Y || P.Z < min.Z) continue;
|
||||
if (P.X > max.X || P.Y > max.Y || P.Z > max.Z) continue;
|
||||
|
||||
byte lvlBlock = lvl.GetTile(P.X, P.Y, P.Z);
|
||||
if (lvlBlock == P.NewBlock.BlockID || Block.Convert(lvlBlock) == Block.water
|
||||
|| Block.Convert(lvlBlock) == Block.lava || lvlBlock == Block.grass) {
|
||||
|
||||
block.X = P.X; block.Y = P.Y; block.Z = P.Z;
|
||||
block.Block = P.Block;
|
||||
args.Output(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void DoHighlight(string target, ref bool found, UndoFormatArgs args) {
|
||||
List<string> files = GetUndoFiles(target);
|
||||
if (files.Count == 0) return;
|
||||
found = true;
|
||||
|
||||
foreach (string file in files) {
|
||||
using (Stream s = File.OpenRead(file)) {
|
||||
DoHighlight(s, GetFormat(file), args);
|
||||
if (args.Stop) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DoHighlight(Stream s, UndoFormat format, UndoFormatArgs args) {
|
||||
Level lvl = args.Player.level;
|
||||
Vec3S32 min = args.Min, max = args.Max;
|
||||
DrawOpBlock block;
|
||||
|
||||
foreach (UndoFormatEntry P in format.GetEntries(s, args)) {
|
||||
ExtBlock old = P.Block, newBlock = P.NewBlock;
|
||||
if (P.X < min.X || P.Y < min.Y || P.Z < min.Z) continue;
|
||||
if (P.X > max.X || P.Y > max.Y || P.Z > max.Z) continue;
|
||||
|
||||
block.Block = (newBlock.BlockID == Block.air
|
||||
|| Block.Convert(old.BlockID) == Block.water || old.BlockID == Block.waterstill
|
||||
|| Block.Convert(old.BlockID) == Block.lava || old.BlockID == Block.lavastill)
|
||||
? args.DeleteHighlight : args.PlaceHighlight;
|
||||
|
||||
block.X = P.X; block.Y = P.Y; block.Z = P.Z;
|
||||
args.Output(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -38,7 +38,7 @@ namespace MCGalaxy.Undo {
|
||||
public static UndoFormat NewFormat = new UndoFormatCBin();
|
||||
|
||||
/// <summary> Enumerates through all the entries in the undo file. </summary>
|
||||
protected abstract IEnumerable<UndoFormatEntry> GetEntries(Stream s, UndoFormatArgs args);
|
||||
public abstract IEnumerable<UndoFormatEntry> GetEntries(Stream s, UndoFormatArgs args);
|
||||
|
||||
/// <summary> File extension of undo files in this format. </summary>
|
||||
protected abstract string Ext { get; }
|
||||
@ -81,7 +81,7 @@ namespace MCGalaxy.Undo {
|
||||
return files;
|
||||
}
|
||||
|
||||
static UndoFormat GetFormat(string file) {
|
||||
public static UndoFormat GetFormat(string file) {
|
||||
if (file.EndsWith(TxtFormat.Ext)) return TxtFormat;
|
||||
if (file.EndsWith(BinFormat.Ext)) return BinFormat;
|
||||
if (file.EndsWith(NewFormat.Ext)) return NewFormat;
|
||||
@ -110,36 +110,13 @@ namespace MCGalaxy.Undo {
|
||||
|
||||
/// <summary> Whether the format has finished retrieving undo data,
|
||||
/// due to finding an entry before the start range. </summary>
|
||||
public bool Stop;
|
||||
|
||||
/// <summary> Block to highlight placements with. </summary>
|
||||
public ExtBlock PlaceHighlight = (ExtBlock)Block.green;
|
||||
|
||||
/// <summary> Block to highlight deletions with. </summary>
|
||||
public ExtBlock DeleteHighlight = (ExtBlock)Block.red;
|
||||
|
||||
public bool Stop;
|
||||
|
||||
/// <summary> First instance in time that undo data should be retrieved back to. </summary>
|
||||
internal readonly DateTime Start;
|
||||
|
||||
/// <summary> Last instance in time that undo data should be retrieved up to. </summary>
|
||||
internal readonly DateTime End;
|
||||
|
||||
/// <summary> Minimum coordinate of region to process blocks within. </summary>
|
||||
internal readonly Vec3S32 Min;
|
||||
|
||||
/// <summary> Minimum coordinate of region to process blocks within. </summary>
|
||||
internal readonly Vec3S32 Max;
|
||||
|
||||
/// <summary> Action invoked for each block processed. </summary>
|
||||
internal Action<DrawOpBlock> Output;
|
||||
|
||||
public UndoFormatArgs(Player p, DateTime start, DateTime end,
|
||||
Vec3S32 min, Vec3S32 max, Action<DrawOpBlock> output) {
|
||||
Player = p;
|
||||
Start = start; End = end;
|
||||
Min = min; Max = max;
|
||||
Output = output;
|
||||
public UndoFormatArgs(Player p, DateTime start) {
|
||||
Player = p; Start = start;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ namespace MCGalaxy.Undo {
|
||||
protected override string Ext { get { return ".unbin"; } }
|
||||
const int entrySize = 12;
|
||||
|
||||
protected override IEnumerable<UndoFormatEntry> GetEntries(Stream s, UndoFormatArgs args) {
|
||||
public override IEnumerable<UndoFormatEntry> GetEntries(Stream s, UndoFormatArgs args) {
|
||||
List<ChunkHeader> list = new List<ChunkHeader>();
|
||||
UndoFormatEntry pos;
|
||||
bool super = Player.IsSuper(args.Player);
|
||||
|
@ -28,7 +28,7 @@ namespace MCGalaxy.Undo {
|
||||
protected override string Ext { get { return ".uncbin"; } }
|
||||
const int entrySize = 8;
|
||||
|
||||
protected override IEnumerable<UndoFormatEntry> GetEntries(Stream s, UndoFormatArgs args) {
|
||||
public override IEnumerable<UndoFormatEntry> GetEntries(Stream s, UndoFormatArgs args) {
|
||||
List<ChunkHeader> list = new List<ChunkHeader>();
|
||||
UndoFormatEntry pos;
|
||||
bool super = Player.IsSuper(args.Player);
|
||||
|
@ -27,7 +27,7 @@ namespace MCGalaxy.Undo {
|
||||
|
||||
protected override string Ext { get { return ".undo"; } }
|
||||
|
||||
protected override IEnumerable<UndoFormatEntry> GetEntries(Stream s, UndoFormatArgs args) {
|
||||
public override IEnumerable<UndoFormatEntry> GetEntries(Stream s, UndoFormatArgs args) {
|
||||
UndoFormatEntry pos = default(UndoFormatEntry);
|
||||
string[] lines = new StreamReader(s).ReadToEnd().SplitSpaces();
|
||||
Player p = args.Player;
|
||||
|
@ -16,6 +16,8 @@
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCGalaxy.DB;
|
||||
using MCGalaxy.Drawing.Brushes;
|
||||
using MCGalaxy.Maths;
|
||||
@ -65,10 +67,8 @@ namespace MCGalaxy.Drawing.Ops {
|
||||
}
|
||||
}
|
||||
|
||||
UndoFormatArgs args = new UndoFormatArgs(Player, Start, DateTime.MaxValue, Min, Max, output);
|
||||
args.PlaceHighlight = PlaceHighlight;
|
||||
args.DeleteHighlight = DeleteHighlight;
|
||||
UndoFormat.DoHighlight(who.ToLower(), ref found, args);
|
||||
UndoFormatArgs args = new UndoFormatArgs(Player, Start);
|
||||
DoOldHighlight(args);
|
||||
}
|
||||
|
||||
Action<DrawOpBlock> output;
|
||||
@ -93,5 +93,37 @@ namespace MCGalaxy.Drawing.Ops {
|
||||
output(Place((ushort)x, (ushort)y, (ushort)z, highlight));
|
||||
found = true;
|
||||
}
|
||||
|
||||
|
||||
void DoOldHighlight(UndoFormatArgs args) {
|
||||
List<string> files = UndoFormat.GetUndoFiles(who.ToLower());
|
||||
if (files.Count == 0) return;
|
||||
found = true;
|
||||
|
||||
foreach (string file in files) {
|
||||
using (Stream s = File.OpenRead(file)) {
|
||||
DoOldHighlight(s, UndoFormat.GetFormat(file), args);
|
||||
if (args.Stop) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoOldHighlight(Stream s, UndoFormat format, UndoFormatArgs args) {
|
||||
DrawOpBlock block;
|
||||
|
||||
foreach (UndoFormatEntry P in format.GetEntries(s, args)) {
|
||||
ExtBlock old = P.Block, newBlock = P.NewBlock;
|
||||
if (P.X < Min.X || P.Y < Min.Y || P.Z < Min.Z) continue;
|
||||
if (P.X > Max.X || P.Y > Max.Y || P.Z > Max.Z) continue;
|
||||
|
||||
block.Block = (newBlock.BlockID == Block.air
|
||||
|| Block.Convert(old.BlockID) == Block.water || old.BlockID == Block.waterstill
|
||||
|| Block.Convert(old.BlockID) == Block.lava || old.BlockID == Block.lavastill)
|
||||
? DeleteHighlight : PlaceHighlight;
|
||||
|
||||
block.X = P.X; block.Y = P.Y; block.Z = P.Z;
|
||||
output(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,11 +16,12 @@
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using MCGalaxy.Blocks.Physics;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCGalaxy.DB;
|
||||
using MCGalaxy.Drawing.Brushes;
|
||||
using MCGalaxy.Maths;
|
||||
using MCGalaxy.Undo;
|
||||
using MCGalaxy.Maths;
|
||||
|
||||
namespace MCGalaxy.Drawing.Ops {
|
||||
|
||||
@ -69,9 +70,9 @@ namespace MCGalaxy.Drawing.Ops {
|
||||
if (BlockDBReadLock != null) BlockDBReadLock.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
UndoFormatArgs args = new UndoFormatArgs(Player, Start, End, Min, Max, output);
|
||||
UndoFormat.DoUndo(who.ToLower(), ref found, args);
|
||||
|
||||
UndoFormatArgs args = new UndoFormatArgs(Player, Start);
|
||||
DoOldUndo(args);
|
||||
}
|
||||
|
||||
Action<DrawOpBlock> output;
|
||||
@ -90,57 +91,41 @@ namespace MCGalaxy.Drawing.Ops {
|
||||
output(Place((ushort)x, (ushort)y, (ushort)z, block));
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
public class UndoPhysicsDrawOp : DrawOp {
|
||||
public override string Name { get { return "UndoPhysics"; } }
|
||||
public override bool AffectedByTransform { get { return false; } }
|
||||
|
||||
internal DateTime Start;
|
||||
|
||||
public override long BlocksAffected(Level lvl, Vec3S32[] marks) { return -1; }
|
||||
|
||||
public override void Perform(Vec3S32[] marks, Brush brush, Action<DrawOpBlock> output) {
|
||||
if (Level.UndoBuffer.Count != Server.physUndo) {
|
||||
int count = Level.currentUndo;
|
||||
for (int i = count; i >= 0; i--) {
|
||||
try {
|
||||
if (!CheckBlockPhysics(Player, Level, i)) break;
|
||||
} catch { }
|
||||
}
|
||||
} else {
|
||||
int count = Level.currentUndo;
|
||||
for (int i = count; i >= 0; i--) {
|
||||
try {
|
||||
if (!CheckBlockPhysics(Player, Level, i)) break;
|
||||
} catch { }
|
||||
}
|
||||
for (int i = Level.UndoBuffer.Count - 1; i > count; i--) {
|
||||
try {
|
||||
if (!CheckBlockPhysics(Player, Level, i)) break;
|
||||
} catch { }
|
||||
void DoOldUndo(UndoFormatArgs args) {
|
||||
List<string> files = UndoFormat.GetUndoFiles(who.ToLower());
|
||||
if (files.Count == 0) return;
|
||||
found = true;
|
||||
|
||||
foreach (string file in files) {
|
||||
using (Stream s = File.OpenRead(file)) {
|
||||
DoOldUndo(s, UndoFormat.GetFormat(file), args);
|
||||
if (args.Stop) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckBlockPhysics(Player p, Level lvl, int i) {
|
||||
Level.UndoPos undo = lvl.UndoBuffer[i];
|
||||
byte b = lvl.GetTile(undo.index);
|
||||
DateTime time = Server.StartTime.AddTicks((undo.flags >> 2) * TimeSpan.TicksPerSecond);
|
||||
if (time < Start) return false;
|
||||
void DoOldUndo(Stream s, UndoFormat format, UndoFormatArgs args) {
|
||||
Level lvl = args.Player == null ? null : args.Player.level;
|
||||
string lastMap = null;
|
||||
DrawOpBlock block;
|
||||
|
||||
byte newType = (undo.flags & 2) != 0 ? Block.custom_block : undo.newRaw;
|
||||
if (b == newType || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) {
|
||||
ushort x, y, z;
|
||||
lvl.IntToPos(undo.index, out x, out y, out z);
|
||||
int undoIndex = lvl.currentUndo;
|
||||
lvl.currentUndo = i;
|
||||
lvl.currentUndo = undoIndex;
|
||||
foreach (UndoFormatEntry P in format.GetEntries(s, args)) {
|
||||
if (P.LevelName != lastMap) lvl = LevelInfo.FindExact(P.LevelName);
|
||||
if (lvl == null || P.Time > End) continue;
|
||||
if (P.X < Min.X || P.Y < Min.Y || P.Z < Min.Z) continue;
|
||||
if (P.X > Max.X || P.Y > Max.Y || P.Z > Max.Z) continue;
|
||||
|
||||
ExtBlock oldBlock = ExtBlock.FromRaw(undo.oldRaw, (undo.flags & 1) != 0);
|
||||
lvl.Blockchange(x, y, z, oldBlock, true, default(PhysicsArgs), false);
|
||||
byte lvlBlock = lvl.GetTile(P.X, P.Y, P.Z);
|
||||
if (lvlBlock == P.NewBlock.BlockID || Block.Convert(lvlBlock) == Block.water
|
||||
|| Block.Convert(lvlBlock) == Block.lava || lvlBlock == Block.grass) {
|
||||
|
||||
block.X = P.X; block.Y = P.Y; block.Z = P.Z;
|
||||
block.Block = P.Block;
|
||||
output(block);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
76
MCGalaxy/Drawing/DrawOps/UndoPhysicsDrawOp.cs
Normal file
76
MCGalaxy/Drawing/DrawOps/UndoPhysicsDrawOp.cs
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
Copyright 2015 MCGalaxy
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using MCGalaxy.Blocks.Physics;
|
||||
using MCGalaxy.Drawing.Brushes;
|
||||
using MCGalaxy.Maths;
|
||||
|
||||
namespace MCGalaxy.Drawing.Ops {
|
||||
|
||||
public class UndoPhysicsDrawOp : DrawOp {
|
||||
public override string Name { get { return "UndoPhysics"; } }
|
||||
public override bool AffectedByTransform { get { return false; } }
|
||||
|
||||
internal DateTime Start;
|
||||
|
||||
public override long BlocksAffected(Level lvl, Vec3S32[] marks) { return -1; }
|
||||
|
||||
public override void Perform(Vec3S32[] marks, Brush brush, Action<DrawOpBlock> output) {
|
||||
if (Level.UndoBuffer.Count != Server.physUndo) {
|
||||
int count = Level.currentUndo;
|
||||
for (int i = count; i >= 0; i--) {
|
||||
try {
|
||||
if (!CheckBlockPhysics(Player, Level, i)) break;
|
||||
} catch { }
|
||||
}
|
||||
} else {
|
||||
int count = Level.currentUndo;
|
||||
for (int i = count; i >= 0; i--) {
|
||||
try {
|
||||
if (!CheckBlockPhysics(Player, Level, i)) break;
|
||||
} catch { }
|
||||
}
|
||||
for (int i = Level.UndoBuffer.Count - 1; i > count; i--) {
|
||||
try {
|
||||
if (!CheckBlockPhysics(Player, Level, i)) break;
|
||||
} catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckBlockPhysics(Player p, Level lvl, int i) {
|
||||
Level.UndoPos undo = lvl.UndoBuffer[i];
|
||||
byte b = lvl.GetTile(undo.index);
|
||||
DateTime time = Server.StartTime.AddTicks((undo.flags >> 2) * TimeSpan.TicksPerSecond);
|
||||
if (time < Start) return false;
|
||||
|
||||
byte newType = (undo.flags & 2) != 0 ? Block.custom_block : undo.newRaw;
|
||||
if (b == newType || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) {
|
||||
ushort x, y, z;
|
||||
lvl.IntToPos(undo.index, out x, out y, out z);
|
||||
int undoIndex = lvl.currentUndo;
|
||||
lvl.currentUndo = i;
|
||||
lvl.currentUndo = undoIndex;
|
||||
|
||||
ExtBlock oldBlock = ExtBlock.FromRaw(undo.oldRaw, (undo.flags & 1) != 0);
|
||||
lvl.Blockchange(x, y, z, oldBlock, true, default(PhysicsArgs), false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -451,6 +451,7 @@
|
||||
<Compile Include="Drawing\DrawOps\TreeDrawOp.cs" />
|
||||
<Compile Include="Drawing\DrawOps\TriangleDrawOp.cs" />
|
||||
<Compile Include="Drawing\DrawOps\UndoDrawOp.cs" />
|
||||
<Compile Include="Drawing\DrawOps\UndoPhysicsDrawOp.cs" />
|
||||
<Compile Include="Drawing\DrawOps\WriteDrawOp.cs" />
|
||||
<Compile Include="Drawing\Flip.cs" />
|
||||
<Compile Include="Drawing\Image\ImagePalette.cs" />
|
||||
@ -586,7 +587,6 @@
|
||||
<Compile Include="Player\PlayerInfo.cs" />
|
||||
<Compile Include="Player\SpamChecker.cs" />
|
||||
<Compile Include="Player\TabList.cs" />
|
||||
<Compile Include="Database\Undo\UndoFormat.Helpers.cs" />
|
||||
<Compile Include="Database\Undo\UndoFormatCBin.cs" />
|
||||
<Compile Include="Player\Warp.cs" />
|
||||
<Compile Include="Database\Undo\UndoFormat.cs" />
|
||||
@ -652,7 +652,6 @@
|
||||
<Compile Include="sharkbite.thresher\ConnectionArgs.cs" />
|
||||
<Compile Include="sharkbite.thresher\Delegates.cs" />
|
||||
<Compile Include="sharkbite.thresher\Enums.cs" />
|
||||
<Compile Include="sharkbite.thresher\Identd.cs" />
|
||||
<Compile Include="sharkbite.thresher\Listener.cs" />
|
||||
<Compile Include="sharkbite.thresher\NameGenerator.cs" />
|
||||
<Compile Include="sharkbite.thresher\ReplyCode.cs" />
|
||||
|
@ -1,151 +0,0 @@
|
||||
/*
|
||||
* Thresher IRC client library
|
||||
* Copyright (C) 2002 Aaron Hunter <thresher@sharkbite.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* See the gpl.txt file located in the top-level-directory of
|
||||
* the archive of this library for complete text of license.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
|
||||
|
||||
namespace Sharkbite.Irc
|
||||
{
|
||||
/// <summary>
|
||||
/// An Ident daemon is still used by some IRC networks for
|
||||
/// authentication. It is a simple service which when queried
|
||||
/// by a remote system returns a username. The server is controlled via static
|
||||
/// methods all of which are Thread safe.
|
||||
/// </summary>
|
||||
public sealed class Identd
|
||||
{
|
||||
private static TcpListener listener;
|
||||
private static bool running;
|
||||
private static object lockObject;
|
||||
private static string username;
|
||||
private const string Reply = " : USERID : UNIX : ";
|
||||
private const int IdentdPort = 113;
|
||||
|
||||
static Identd()
|
||||
{
|
||||
running = false;
|
||||
lockObject = new object();
|
||||
}
|
||||
|
||||
//Declare constructor private so it cannot be instatiated.
|
||||
private Identd() {}
|
||||
|
||||
/// <summary>
|
||||
/// The Identd server will start listening for queries
|
||||
/// in its own thread. It can be stopped by calling
|
||||
/// <see cref="Identd.Stop"/>.
|
||||
/// </summary>
|
||||
/// <param name="userName">Should be the same username as the one used
|
||||
/// in the ConnectionArgs object when establishing a connection.</param>
|
||||
/// <exception cref="Exception">If the server has already been started.</exception>
|
||||
public static void Start( string userName )
|
||||
{
|
||||
lock( lockObject )
|
||||
{
|
||||
if( running )
|
||||
{
|
||||
throw new Exception("Identd already started.");
|
||||
}
|
||||
running = true;
|
||||
username = userName;
|
||||
Thread socketThread = new Thread( new ThreadStart( Identd.Run ) );
|
||||
socketThread.Name = "Identd";
|
||||
socketThread.Start();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Check if the Identd server is running
|
||||
/// </summary>
|
||||
/// <returns>True if it is running</returns>
|
||||
public static bool IsRunning()
|
||||
{
|
||||
lock( lockObject )
|
||||
{
|
||||
return running;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Stop the Identd server and close the thread.
|
||||
/// </summary>
|
||||
public static void Stop()
|
||||
{
|
||||
lock( lockObject )
|
||||
{
|
||||
if( running )
|
||||
{
|
||||
listener.Stop();
|
||||
Debug.WriteLineIf( Rfc2812Util.IrcTrace.TraceInfo,"[" + Thread.CurrentThread.Name +"] Identd::Stop()");
|
||||
listener = null;
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void Run()
|
||||
{
|
||||
Debug.WriteLineIf( Rfc2812Util.IrcTrace.TraceInfo,"[" + Thread.CurrentThread.Name +"] Identd::Run()");
|
||||
try
|
||||
{
|
||||
listener = new TcpListener( IPAddress.Any, IdentdPort );
|
||||
listener.Start();
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
TcpClient client = listener.AcceptTcpClient();
|
||||
//Read query
|
||||
StreamReader reader = new StreamReader(client.GetStream() );
|
||||
string line = reader.ReadLine();
|
||||
Debug.WriteLineIf( Rfc2812Util.IrcTrace.TraceVerbose,"[" + Thread.CurrentThread.Name +"] Identd::Run() received=" + line);
|
||||
|
||||
//Send back reply
|
||||
StreamWriter writer = new StreamWriter( client.GetStream() );
|
||||
writer.WriteLine( line.Trim() + Reply + username );
|
||||
writer.Flush();
|
||||
|
||||
//Close connection with client
|
||||
client.Close();
|
||||
}
|
||||
catch( IOException ioe )
|
||||
{
|
||||
Debug.WriteLineIf( Rfc2812Util.IrcTrace.TraceWarning,"[" + Thread.CurrentThread.Name +"] Identd::Run() exception=" + ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( Exception )
|
||||
{
|
||||
Debug.WriteLineIf( Rfc2812Util.IrcTrace.TraceInfo,"[" + Thread.CurrentThread.Name +"] Identd::Run() Identd stopped");
|
||||
}
|
||||
finally
|
||||
{
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user