Stránka 1 z 1

ResourceCounter

Napsal: 27 srp 2010 03:43
od Mole Two
Experimentální resource counter jako byl v yoku s průhlednejma ikonkama

Testováno pouze na Windows 7 bez aera, dejte vědět jak kde (ne)funguje. Přepočítání trvá cca 16ms, při hodně velkém počtu updatů by to mohlo být i znát. Návrhy na zrychlení nebo pořešení problikávání při přepočtu klidně pište. Úplatky a sponzorské dary přijímám taky.

Screen: http://dl.dropbox.com/u/1799304/uo/reso ... ounter.png

Changelog:
27-08-2010 13:20: Fixed wrong packet usage
27-08-2010 13:07: Moar performance tweaks
27-08-2010 11:45: Performance update

Kód: Vybrat vše

//#define CONFIG_MODE

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using MulLib;
using Phoenix.Runtime;
using Phoenix.WorldData;
using Phoenix.Communication;
using System.Text;

namespace Phoenix.Scripts {
    public class CreateCharacter {
        [ClientMessageHandler(0x00)]
        public CallbackResult OnCreateCharacter( byte[] data, CallbackResult prevResult ) {
            byte[] bytes = Encoding.ASCII.GetBytes( "Kringelbert Fishtybuns" );

            Array.Copy( bytes, 0, data, 10, bytes.Length );

            return prevResult;
        }
    }

    [RuntimeObject]
    public class ResourceCounter : IDisposable {
        private const int GWLP_WNDPROC = -4;
        private const int BoxSpacing = 15;

        public ResourceCounter() {
            items = new List<IDrawable>() { 
                    new ItemInfo( "BM", 0x0F7B, 0x0000, new Rectangle( 6, -4, 30, SystemInformation.CaptionHeight - 2 ) ),
                    new ItemInfo( "BP", 0x0F7A, 0x0000, new Rectangle( 17, -7, 10, SystemInformation.CaptionHeight - 2 )  ),
                    new ItemInfo( "GC", 0x0F84, 0x0000, new Rectangle( 0, -5, 30, SystemInformation.CaptionHeight - 2 ) ),
                    new ItemInfo( "GS", 0x0F85, 0x0000, new Rectangle( 15, -3, 20, SystemInformation.CaptionHeight - 2 ) ),
                    new ItemInfo( "MR", 0x0F86, 0x0000, new Rectangle( 11, -3, 20, SystemInformation.CaptionHeight - 2 ) ),
                    new ItemInfo( "NS", 0x0F88, 0x0000, new Rectangle( 5, 1, 30, SystemInformation.CaptionHeight - 2 ) ),
                    new ItemInfo( "SA", 0x0F8C, 0x0000, new Rectangle( 9, -4, 30, SystemInformation.CaptionHeight - 2 ) ),
                    new ItemInfo( "SS", 0x0F8D, 0x0000, new Rectangle( 8, -3, 20, SystemInformation.CaptionHeight - 2 ) ),
                    new Separator( "|" ),
                    new ItemInfo( "Bloodspawn", 0x0F7C, 0x0000, new Rectangle( 8, -3, 17, SystemInformation.CaptionHeight - 2 ) ),
                    new ItemInfo( "Brimstone", 0x0F7F, 0x0000, new Rectangle( 17, -4, 15, SystemInformation.CaptionHeight - 2 ) ),
                    new ItemInfo( "Obsidian", 0x0F89, 0x0000,  new Rectangle( 7, -3, 25, SystemInformation.CaptionHeight - 2 ) ),
                    new ItemInfo( "Blackmoor", 0x0F79, 0x0000, new Rectangle( 16, -4, 20, SystemInformation.CaptionHeight - 2 ) ),
                    new ItemInfo( "Batwing", 0x0F78, 0x0000, new Rectangle( 14, -2, 16, SystemInformation.CaptionHeight - 2 ) ),
                    new ItemInfo( "Eye of Newt", 0x0F87, 0x0000, new Rectangle( 16, -7, 9, SystemInformation.CaptionHeight - 2 ) ),
                    new ItemInfo( "Vial of Blood", 0x0F7D, 0x0000, new Rectangle( 16, -1, 10, SystemInformation.CaptionHeight - 2 ) ),
                    new ItemInfo( "Bone", 0x0F7E, 0x0000,  new Rectangle( 16, -3, 23, SystemInformation.CaptionHeight - 2 ) ),
                    new Separator( "|" ),
                    new ItemInfo( "TMR", 0x0F09, 0x0003, new Rectangle( 9, -1, 15, SystemInformation.CaptionHeight - 2 ) ),
                    new ItemInfo( "GH", 0x0F0C, 0x0000, new Rectangle( 9, -1, 15, SystemInformation.CaptionHeight - 2 ) ),
                    new ItemInfo( "TR", 0x0F0B, 0x0000, new Rectangle( 9, -1, 15, SystemInformation.CaptionHeight - 2 ) ),
                    new Separator( "|" ),
                    new ItemInfo( "Bandage", 0x0E21, 0x0000, new Rectangle( 11, -2, 22, SystemInformation.CaptionHeight - 2) ),
                };

            Debug.WriteLine( "Installing wndproc hook", "ResourceCounter" );

            originalWndProc = NativeMethods.GetWindowLong( Client.HWND, GWLP_WNDPROC );
            if ( originalWndProc == IntPtr.Zero )
                throw new Win32Exception();

            wndProc = new WndProcDelegate( WndProc );

            if ( NativeMethods.SetWindowLong( Client.HWND, GWLP_WNDPROC, Marshal.GetFunctionPointerForDelegate( wndProc ) ) == IntPtr.Zero )
                throw new Win32Exception();

            RuntimeCore.UnregisteringAssembly += new UnregisteringAssemblyEventHandler( RuntimeCore_UnregisteringAssembly );

            Redraw();
        }
        ~ResourceCounter() {
            Dispose();
        }

        private List<IDrawable> items;
        private WndProcDelegate wndProc;
        private IntPtr originalWndProc;

        public void Redraw() {
            if ( ( from t in items.OfType<ItemInfo>()
                   join i in World.Player.Backpack.AllItems on new {
                       t.Graphic,
                       t.Color
                   } equals new {
                       i.Graphic,
                       i.Color
                   } into x
                   from i in x.DefaultIfEmpty()
                   group i by t into r
                   select new {
                       Type = r.Key,
                       Amount = r.Sum( a => a != null ? a.Amount : 0 )
                   } ).Count( i => i.Type.Update( i.Amount ) ) > 0 ) {

                NativeMethods.SendMessage( Client.HWND, 0x85, IntPtr.Zero, IntPtr.Zero );
                if ( Marshal.GetLastWin32Error() != 0 )
                    throw new Win32Exception();
            }
        }

        [ServerMessageHandler( 0x33, Priority = CallbackPriority.Lowest )]
        public CallbackResult OnAddItemToContainer( byte[] data, CallbackResult prevResult ) {
            if ( data[ 1 ] == 0 )
                Redraw();

            return prevResult;
        }

        private IntPtr WndProc( IntPtr hwnd, uint uMsg, IntPtr wParam, IntPtr lParam ) {
            IntPtr result = NativeMethods.CallWindowProc( originalWndProc, hwnd, uMsg, wParam, lParam );

            switch ( uMsg ) {
                case 0x86: // WM_NCACTIVATE
                case 0x85: // WM_NCPAINT
                    DrawStuff( hwnd );
                    break;
            }

            return result;
        }

        private void DrawStuff( IntPtr hwnd ) {
            if ( !World.Player.Exist )
                return;

            IntPtr hDC = NativeMethods.GetWindowDC( hwnd );

            Rectangle windowRect = new Rectangle();
            if ( !NativeMethods.GetWindowRect( hwnd, ref windowRect ) )
                throw new Win32Exception();

            using ( Graphics graphics = Graphics.FromHdc( hDC ) ) {
                float totalWidth = -BoxSpacing;
                foreach ( IDrawable info in items )
                    totalWidth += info.Measure( graphics ) + BoxSpacing;

                PointF p = new Point( SystemInformation.FrameBorderSize );
                p.X += ( ( windowRect.Width - SystemInformation.CaptionHeight * 2 ) - totalWidth ) / 2;
                p.Y += 1;

                foreach ( IDrawable info in items )
                    p.X += info.Draw( graphics, p ) + BoxSpacing;
            }

            NativeMethods.ReleaseDC( hwnd, hDC );
        }

        #region Event handlers

        private void RuntimeCore_UnregisteringAssembly( object sender, UnregisteringAssemblyEventArgs e ) {
            Dispose();
        }

        #endregion

        #region IDisposable

        public void Dispose() {
            if ( originalWndProc == IntPtr.Zero )
                return;

            Debug.WriteLine( "Removing wndproc hook", "ResourceCounter" );
            if ( NativeMethods.SetWindowLong( Client.HWND, GWLP_WNDPROC, originalWndProc ) == IntPtr.Zero )
                throw new Win32Exception();

            GC.SuppressFinalize( this );
        }

        #endregion

        #region Delegates

        [UnmanagedFunctionPointer( CallingConvention.Winapi )]
        private delegate IntPtr WndProcDelegate( IntPtr hwnd, uint uMsg, IntPtr wParam, IntPtr lParam );

        #endregion

        #region Nested type: IDrawable

        private interface IDrawable {
            bool Update( int itemCount );
            float Measure( Graphics graphics );
            float Draw( Graphics graphics, PointF point );
        }

        #endregion

        #region Nested type: Separator

        private class Separator : IDrawable {
            public Separator( string text ) {
                Text = text;
            }

            private float textWidth;

            #region IDrawable

            public bool Update( int itemCount ) {
                return false;
            }

            public virtual float Measure( Graphics graphics ) {
                textWidth = graphics.MeasureString( Text, SystemFonts.CaptionFont ).Width;
                return textWidth;
            }

            public virtual float Draw( Graphics graphics, PointF point ) {
                graphics.DrawString( Text, SystemFonts.CaptionFont, SystemBrushes.ActiveCaptionText, point );
                return textWidth;
            }

            #endregion

            #region Public properties

            public string Text {
                get;
                private set;
            }

            #endregion
        }

        #endregion

        #region Nested type: ItemInfo

        private class ItemInfo : IDrawable {
            public ItemInfo( string name, Graphic graphic, UOColor color, Rectangle iconBounds ) {
                Name = name;
                Graphic = graphic;
                Color = color;
                this.iconBounds = iconBounds;

                prevAmount = -1;

                Bitmap = DataFiles.Art.Items.Get( graphic );

                if ( color.IsConstant && color != 0x0000 ) {
                    HueEntry hue = DataFiles.Hues.Get( color );
                    if ( hue != null )
                        Dyes.RecolorFull( hue, Bitmap );
                }
            }

            private Rectangle iconBounds;
            private string text;
            private float textWidth;
            private int prevAmount;

            #region IDrawable

            public bool Update( int amount ) {
                if ( prevAmount == amount )
                    return false;

                text = ": " + amount;
                prevAmount = amount;
                return true;
            }

            public float Measure( Graphics graphics ) {
                textWidth = graphics.MeasureString( text, SystemFonts.CaptionFont ).Width;

                return iconBounds.Width + textWidth;
            }

            public float Draw( Graphics graphics, PointF point ) {
#if CONFIG_MODE
                graphics.DrawRectangle( Pens.Azure, point.X, point.Y, iconBounds.Width, iconBounds.Height );
#endif

                graphics.DrawImage( Bitmap, point.X, point.Y, iconBounds, GraphicsUnit.Pixel );
                point.X += iconBounds.Width;

                point.Y = SystemInformation.FrameBorderSize.Height + ( SystemInformation.CaptionHeight - SystemFonts.CaptionFont.Height ) / 2 - 1;
                graphics.DrawString( text, SystemFonts.CaptionFont, SystemBrushes.ActiveCaptionText, point );

                return iconBounds.Width + textWidth;
            }

            #endregion

            #region Public properties

            public string Name {
                get;
                private set;
            }

            public Graphic Graphic {
                get;
                private set;
            }

            public UOColor Color {
                get;
                private set;
            }

            public Bitmap Bitmap {
                get;
                private set;
            }

            #endregion
        }

        #endregion

        #region Native methods

        private static class NativeMethods {

            [DllImport( "user32.dll" )]
            public static extern IntPtr CallWindowProc( IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam );

            [DllImport( "user32.dll", SetLastError = true )]
            public static extern IntPtr SetWindowLong( IntPtr hWnd, int nIndex, IntPtr dwNewLong );

            [DllImport( "user32.dll", SetLastError = true )]
            public static extern IntPtr GetWindowLong( IntPtr hWnd, int nIndex );

            [DllImport( "user32.dll", SetLastError = true )]
            public static extern IntPtr GetWindowDC( IntPtr hWnd );

            [DllImport( "user32.dll" )]
            public static extern int ReleaseDC( IntPtr hWnd, IntPtr hDC );

            [DllImport( "user32.dll" )]
            public static extern bool GetWindowRect( IntPtr hWnd, ref Rectangle lpRect );

            [DllImport( "user32.dll" )]
            public static extern bool UpdateWindow( IntPtr hWnd );

            [DllImport( "user32.dll" )]
            public static extern bool InvalidateRect( IntPtr hWnd, ref Rectangle lpRect, bool bErase );

            [DllImport( "user32.dll", SetLastError = true )]
            public static extern IntPtr SendMessage( IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam );
        }

        #endregion
    }
}

Re: ResourceCounter

Napsal: 13 úno 2011 22:06
od Johny Matovic
uh ehm ..Akoze sa to spusta? :oops:

Re: ResourceCounter

Napsal: 24 črc 2011 12:40
od Atalia
taky se mi to nepodrařilo zprovoznit

Re: ResourceCounter

Napsal: 22 úno 2012 00:18
od Smoce
Funguje i na XP, ale blbne to i na WIN 7 , i Vistách, záleží fakt na tom, jaké frameworky máte ..

Re: ResourceCounter

Napsal: 22 úno 2012 11:33
od Protokoll
screen :arrow: 404

Re: ResourceCounter

Napsal: 22 úno 2012 11:39
od Smoce
Mám upravený vzhled u XP , takže to je trošku rozjeté ..

Obrázek

Re: ResourceCounter

Napsal: 26 úno 2017 14:56
od Johny Matovic
Ma toto niekto sfunkcnene na win 10?;p