wasmclientgl

package
v0.0.0-...-e449b39 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 14, 2022 License: Apache-2.0 Imports: 62 Imported by: 0

Documentation

Overview

Package towerwebjsconn manage websocket connection to tower

Index

Constants

View Source
const (
	DisplayLineLimit = 70
	DstCellSize      = 64.0
	HelperSize       = DstCellSize * 32
	UnitTileZ        = DstCellSize / 16
)

Variables

View Source
var Key2Dir = map[string]way9type.Way9Type{
	"End":        way9type.SouthWest,
	"ArrowDown":  way9type.South,
	"PageDown":   way9type.SouthEast,
	"ArrowLeft":  way9type.West,
	"Clear":      way9type.Center,
	"ArrowRight": way9type.East,
	"Home":       way9type.NorthWest,
	"ArrowUp":    way9type.North,
	"PageUp":     way9type.NorthEast,
}
View Source
var ProcessRecvObjNotiFnMap = [...]func(recvobj interface{}, header c2t_packet.Header, body interface{}) error{
	c2t_idnoti.Invalid:        objRecvNotiFn_Invalid,
	c2t_idnoti.EnterTower:     objRecvNotiFn_EnterTower,
	c2t_idnoti.EnterFloor:     objRecvNotiFn_EnterFloor,
	c2t_idnoti.LeaveFloor:     objRecvNotiFn_LeaveFloor,
	c2t_idnoti.LeaveTower:     objRecvNotiFn_LeaveTower,
	c2t_idnoti.Ageing:         objRecvNotiFn_Ageing,
	c2t_idnoti.Death:          objRecvNotiFn_Death,
	c2t_idnoti.ReadyToRebirth: objRecvNotiFn_ReadyToRebirth,
	c2t_idnoti.Rebirthed:      objRecvNotiFn_Rebirthed,
	c2t_idnoti.Broadcast:      objRecvNotiFn_Broadcast,
	c2t_idnoti.VPObjList:      objRecvNotiFn_VPObjList,
	c2t_idnoti.VPTiles:        objRecvNotiFn_VPTiles,
	c2t_idnoti.FloorTiles:     objRecvNotiFn_FloorTiles,
	c2t_idnoti.FieldObjList:   objRecvNotiFn_FieldObjList,
	c2t_idnoti.FoundFieldObj:  objRecvNotiFn_FoundFieldObj,
	c2t_idnoti.ForgetFloor:    objRecvNotiFn_ForgetFloor,
	c2t_idnoti.ActivateTrap:   objRecvNotiFn_ActivateTrap,
}

Functions

func AddEventListener

func AddEventListener(
	dst js.Value,
	evt string,
	fn func(this js.Value, args []js.Value) interface{})

func CalcAroundPos

func CalcAroundPos(w, h, vpx, vpy, fx, fy int) (int, int)

make fx,fy around vpx, vpy

func CalcCurrentFrame

func CalcCurrentFrame(difftick int64, fps float64) int

func CalcRotateFrameProgress

func CalcRotateFrameProgress(frameProgress float64) float64

0~1 -> 0-> -pi -> 0 -> +pi

func CalcScaleFrameProgress

func CalcScaleFrameProgress(frameProgress float64, damage int) float64

0~1 -> 1->1.5->1->0.5->1

func CalcShiftDxDy

func CalcShiftDxDy(frameProgress float64) (int, int)

func CalcTile3DStepOn

func CalcTile3DStepOn(tl tile_flag.TileFlag) float64

func CalcTile3DVisibleTop

func CalcTile3DVisibleTop(tl tile_flag.TileFlag) float64

func CarryObj2StrColor

func CarryObj2StrColor(o *c2t_obj.CarryObjClientOnFloor) (string, string)

func Equiped2StrColor

func Equiped2StrColor(o *c2t_obj.EquipClient) (string, string)

func GetElementById

func GetElementById(id string) js.Value

func GetQuery

func GetQuery() url.Values

func InitPage

func InitPage()

call after pageload

func IsPowerOfTwo

func IsPowerOfTwo(i int) bool

func MakeAO3DGeo

func MakeAO3DGeo() js.Value

func MakeAO3DGeoByRune

func MakeAO3DGeoByRune(ftstr string) js.Value

func MakeArrowGeo

func MakeArrowGeo() js.Value

func MakeDanger3DGeo

func MakeDanger3DGeo() js.Value

func MakeHelpInfoHTML

func MakeHelpInfoHTML() string

func MakeTitleTextGeometry

func MakeTitleTextGeometry(str string, size float64) js.Value

func NewCarryObj3DGeo

func NewCarryObj3DGeo(str string) js.Value

func NewFieldObjGeo

func NewFieldObjGeo(str string) js.Value

func NextPowerOf2

func NextPowerOf2(n int) int

func SetPosition

func SetPosition(jso js.Value, pos ...interface{})

func SoundByActResult

func SoundByActResult(ar *aoactreqrsp.ActReqRsp)

func ThreeJs

func ThreeJs() js.Value

func ThreeJsNew

func ThreeJsNew(name string, args ...interface{}) js.Value

Types

type ActiveObj3D

type ActiveObj3D struct {
	AOC       *c2t_obj.ActiveObjClient
	Co3d      [equipslottype.EquipSlotType_Count]*CarryObj3D
	Condition [condition.Condition_Count]*Condition3D
	Name      *Label3D
	Chat      *Label3D
	Mesh      js.Value
}

func NewActiveObj3D

func NewActiveObj3D(aoc *c2t_obj.ActiveObjClient) *ActiveObj3D

func (*ActiveObj3D) Dispose

func (ao3d *ActiveObj3D) Dispose()

func (*ActiveObj3D) ResetMatrix

func (ao3d *ActiveObj3D) ResetMatrix()

func (*ActiveObj3D) RotateX

func (ao3d *ActiveObj3D) RotateX(rad float64)

func (*ActiveObj3D) RotateY

func (ao3d *ActiveObj3D) RotateY(rad float64)

func (*ActiveObj3D) RotateZ

func (ao3d *ActiveObj3D) RotateZ(rad float64)

func (*ActiveObj3D) ScaleX

func (ao3d *ActiveObj3D) ScaleX(x float64)

func (*ActiveObj3D) ScaleY

func (ao3d *ActiveObj3D) ScaleY(y float64)

func (*ActiveObj3D) ScaleZ

func (ao3d *ActiveObj3D) ScaleZ(z float64)

func (*ActiveObj3D) SetFieldPosition

func (ao3d *ActiveObj3D) SetFieldPosition(fx, fy int, shX, shY, shZ float64)

func (*ActiveObj3D) UpdateAOC

func (ao3d *ActiveObj3D) UpdateAOC(newaoc *c2t_obj.ActiveObjClient) ([]js.Value, []js.Value)

return toaddmesh, toremove mesh

func (*ActiveObj3D) Visible

func (ao3d *ActiveObj3D) Visible(b bool)

type CarryObj3D

type CarryObj3D struct {
	Str     string
	Color   string
	GeoInfo GeoInfo
	Mesh    js.Value
}

func NewCarryObj3D

func NewCarryObj3D(str, color string) *CarryObj3D

func (*CarryObj3D) Dispose

func (aog *CarryObj3D) Dispose()

func (*CarryObj3D) RotateX

func (aog *CarryObj3D) RotateX(rad float64)

func (*CarryObj3D) RotateY

func (aog *CarryObj3D) RotateY(rad float64)

func (*CarryObj3D) RotateZ

func (aog *CarryObj3D) RotateZ(rad float64)

func (*CarryObj3D) SetFieldPosition

func (aog *CarryObj3D) SetFieldPosition(fx, fy int, shX, shY, shZ float64)

type ColorArrow3D

type ColorArrow3D struct {
	Dir      way9type.Way9Type
	ColorStr string
	GeoInfo  GeoInfo
	Mesh     js.Value
}

func NewColorArrow3D

func NewColorArrow3D(colorstr string) *ColorArrow3D

func (*ColorArrow3D) Dispose

func (aog *ColorArrow3D) Dispose()

func (*ColorArrow3D) RotateX

func (aog *ColorArrow3D) RotateX(rad float64)

func (*ColorArrow3D) RotateY

func (aog *ColorArrow3D) RotateY(rad float64)

func (*ColorArrow3D) RotateZ

func (aog *ColorArrow3D) RotateZ(rad float64)

func (*ColorArrow3D) SetDir

func (aog *ColorArrow3D) SetDir(dir way9type.Way9Type)

func (*ColorArrow3D) SetFieldPosition

func (aog *ColorArrow3D) SetFieldPosition(fx, fy int, shX, shY, shZ float64)

func (*ColorArrow3D) Visible

func (aog *ColorArrow3D) Visible(b bool)

type ColorBar3D

type ColorBar3D struct {
	ColorStr string
	GeoInfo  GeoInfo
	Mesh     js.Value
}

func NewColorBar3D

func NewColorBar3D(colorstr string) *ColorBar3D

func (*ColorBar3D) Dispose

func (aog *ColorBar3D) Dispose()

func (*ColorBar3D) ResetMatrix

func (aog *ColorBar3D) ResetMatrix()

func (*ColorBar3D) RotateX

func (aog *ColorBar3D) RotateX(rad float64)

func (*ColorBar3D) RotateY

func (aog *ColorBar3D) RotateY(rad float64)

func (*ColorBar3D) RotateZ

func (aog *ColorBar3D) RotateZ(rad float64)

func (*ColorBar3D) ScaleX

func (aog *ColorBar3D) ScaleX(x float64)

func (*ColorBar3D) ScaleY

func (aog *ColorBar3D) ScaleY(y float64)

func (*ColorBar3D) ScaleZ

func (aog *ColorBar3D) ScaleZ(z float64)

func (*ColorBar3D) SetFieldPosition

func (aog *ColorBar3D) SetFieldPosition(fx, fy int, shX, shY, shZ float64)

func (*ColorBar3D) SetWH

func (aog *ColorBar3D) SetWH(v, maxv int) (float64, float64)

type Condition3D

type Condition3D struct {
	Condition condition.Condition
	GeoInfo   GeoInfo
	Mesh      js.Value
}

func NewCondition3D

func NewCondition3D(cn condition.Condition) *Condition3D

func (*Condition3D) Dispose

func (cn3d *Condition3D) Dispose()

func (*Condition3D) ResetMatrix

func (cn3d *Condition3D) ResetMatrix()

func (*Condition3D) RotateX

func (cn3d *Condition3D) RotateX(rad float64)

func (*Condition3D) RotateY

func (cn3d *Condition3D) RotateY(rad float64)

func (*Condition3D) RotateZ

func (cn3d *Condition3D) RotateZ(rad float64)

func (*Condition3D) ScaleX

func (cn3d *Condition3D) ScaleX(x float64)

func (*Condition3D) ScaleY

func (cn3d *Condition3D) ScaleY(y float64)

func (*Condition3D) ScaleZ

func (cn3d *Condition3D) ScaleZ(z float64)

func (*Condition3D) SetFieldPosition

func (cn3d *Condition3D) SetFieldPosition(fx, fy int, shX, shY, shZ float64)

func (*Condition3D) Visible

func (cn3d *Condition3D) Visible(b bool)

type Cursor3D

type Cursor3D struct {
	GeoInfo GeoInfo
	Mesh    [3]js.Value
}

func NewCursor3D

func NewCursor3D() *Cursor3D

func (*Cursor3D) SetFieldPosition

func (aog *Cursor3D) SetFieldPosition(fx, fy int, tl tile_flag.TileFlag)

func (*Cursor3D) Visible

func (ao3d *Cursor3D) Visible(i int, b bool)

func (*Cursor3D) VisibleByTile

func (aog *Cursor3D) VisibleByTile(tl tile_flag.TileFlag)

type DangerObj3D

type DangerObj3D struct {
	Dao      *c2t_obj.DangerObjClient
	ColorStr string
	GeoInfo  GeoInfo
	Mesh     js.Value
}

func NewDangerObj3D

func NewDangerObj3D(Dao *c2t_obj.DangerObjClient) *DangerObj3D

func (*DangerObj3D) Dispose

func (dao3d *DangerObj3D) Dispose()

func (*DangerObj3D) RotateX

func (dao3d *DangerObj3D) RotateX(rad float64)

func (*DangerObj3D) RotateY

func (dao3d *DangerObj3D) RotateY(rad float64)

func (*DangerObj3D) RotateZ

func (dao3d *DangerObj3D) RotateZ(rad float64)

func (*DangerObj3D) ScaleX

func (dao3d *DangerObj3D) ScaleX(x float64)

func (*DangerObj3D) ScaleY

func (dao3d *DangerObj3D) ScaleY(y float64)

func (*DangerObj3D) ScaleZ

func (dao3d *DangerObj3D) ScaleZ(z float64)

func (*DangerObj3D) SetFieldPosition

func (dao3d *DangerObj3D) SetFieldPosition(fx, fy int, shX, shY, shZ float64)

func (*DangerObj3D) Visible

func (dao3d *DangerObj3D) Visible(b bool)

type FOKey

type FOKey struct {
	ActType     fieldobjacttype.FieldObjActType
	DisplayType fieldobjdisplaytype.FieldObjDisplayType
}

type FieldObj3D

type FieldObj3D struct {
	ActType     fieldobjacttype.FieldObjActType
	DisplayType fieldobjdisplaytype.FieldObjDisplayType
	Label       *Label3D
	GeoInfo     GeoInfo
	Mesh        js.Value
}

func (*FieldObj3D) RotateX

func (aog *FieldObj3D) RotateX(rad float64)

func (*FieldObj3D) RotateY

func (aog *FieldObj3D) RotateY(rad float64)

func (*FieldObj3D) RotateZ

func (aog *FieldObj3D) RotateZ(rad float64)

func (*FieldObj3D) SetFieldPosition

func (aog *FieldObj3D) SetFieldPosition(fx, fy int, shZ float64)

type GameScene

type GameScene struct {

	// player ao bars
	HP *ColorBar3D
	SP *ColorBar3D
	AP *ColorBar3D
	// contains filtered or unexported fields
}

func NewGameScene

func NewGameScene() *GameScene

func (*GameScene) ClearMovePath

func (vp *GameScene) ClearMovePath()

func (*GameScene) FindRayCastingFxFy

func (vp *GameScene) FindRayCastingFxFy(jsMouse js.Value) (int, int)

func (*GameScene) ProcessNotiVPTiles

func (vp *GameScene) ProcessNotiVPTiles(
	cf *clientfloor.ClientFloor,
	taNoti *c2t_obj.NotiVPTiles_data,
	olNoti *c2t_obj.NotiVPObjList_data,
	path2dst [][2]int,
) error

process noti vptiles viewport x,y changed == need scroll

func (*GameScene) Resize

func (vp *GameScene) Resize(w, h float64)

func (*GameScene) UpdateFloorViewFrame

func (vp *GameScene) UpdateFloorViewFrame(
	cf *clientfloor.ClientFloor, vpx, vpy int, envBias bias.Bias)

floorview frame update

func (*GameScene) UpdatePlayViewFrame

func (vp *GameScene) UpdatePlayViewFrame(
	cf *clientfloor.ClientFloor,
	frameProgress float64,
	scrollDir way9type.Way9Type,
	taNoti *c2t_obj.NotiVPTiles_data,
	olNoti *c2t_obj.NotiVPObjList_data,
	lastOLNoti *c2t_obj.NotiVPObjList_data,
	envBias bias.Bias,
)

playview frame update

func (*GameScene) UpdatePlayerAO

update hp,ap,sp bar movearrow for player ao

func (*GameScene) Zoom

func (vp *GameScene) Zoom(zoom int)

type GeoInfo

type GeoInfo struct {
	Min [3]float64
	Max [3]float64
	Len [3]float64
}

func GetGeoInfo

func GetGeoInfo(geo js.Value) GeoInfo

type Label3D

type Label3D struct {
	Str     string
	Cnv     js.Value
	Ctx     js.Value
	Tex     js.Value
	GeoInfo GeoInfo
	Mesh    js.Value
}

func NewLabel3D

func NewLabel3D(str string) *Label3D

func (*Label3D) Dispose

func (aog *Label3D) Dispose()

func (*Label3D) RotateX

func (aog *Label3D) RotateX(rad float64)

func (*Label3D) RotateY

func (aog *Label3D) RotateY(rad float64)

func (*Label3D) RotateZ

func (aog *Label3D) RotateZ(rad float64)

func (*Label3D) SetFieldPosition

func (aog *Label3D) SetFieldPosition(fx, fy int, shX, shY, shZ float64)

type PoolCarryObj3DGeo

type PoolCarryObj3DGeo struct {
	// contains filtered or unexported fields
}

func NewPoolCarryObj3DGeo

func NewPoolCarryObj3DGeo() *PoolCarryObj3DGeo

func (*PoolCarryObj3DGeo) Get

func (p *PoolCarryObj3DGeo) Get(str string) js.Value

func (*PoolCarryObj3DGeo) Put

func (p *PoolCarryObj3DGeo) Put(geo js.Value, str string)

func (*PoolCarryObj3DGeo) String

func (p *PoolCarryObj3DGeo) String() string

type PoolColorArrow3D

type PoolColorArrow3D struct {
	// contains filtered or unexported fields
}

func NewPoolColorArrow3D

func NewPoolColorArrow3D() *PoolColorArrow3D

func (*PoolColorArrow3D) Get

func (p *PoolColorArrow3D) Get(colorstr string) *ColorArrow3D

func (*PoolColorArrow3D) Put

func (p *PoolColorArrow3D) Put(pb *ColorArrow3D)

func (*PoolColorArrow3D) String

func (p *PoolColorArrow3D) String() string

type PoolColorBar3D

type PoolColorBar3D struct {
	// contains filtered or unexported fields
}

func NewPoolColorBar3D

func NewPoolColorBar3D() *PoolColorBar3D

func (*PoolColorBar3D) Get

func (p *PoolColorBar3D) Get(colorstr string) *ColorBar3D

func (*PoolColorBar3D) Put

func (p *PoolColorBar3D) Put(pb *ColorBar3D)

func (*PoolColorBar3D) String

func (p *PoolColorBar3D) String() string

type PoolColorMaterial

type PoolColorMaterial struct {
	// contains filtered or unexported fields
}

func NewPoolColorMaterial

func NewPoolColorMaterial() *PoolColorMaterial

func (*PoolColorMaterial) Get

func (p *PoolColorMaterial) Get(color string) js.Value

func (*PoolColorMaterial) Put

func (p *PoolColorMaterial) Put(pb js.Value)

func (*PoolColorMaterial) String

func (p *PoolColorMaterial) String() string

type PoolCondition3D

type PoolCondition3D struct {
	// contains filtered or unexported fields
}

func NewPoolCondition3D

func NewPoolCondition3D() *PoolCondition3D

func (*PoolCondition3D) Get

func (*PoolCondition3D) Put

func (p *PoolCondition3D) Put(pb *Condition3D)

func (*PoolCondition3D) String

func (p *PoolCondition3D) String() string

type PoolDangerObj3D

type PoolDangerObj3D struct {
	// contains filtered or unexported fields
}

func NewPoolDangerObj3D

func NewPoolDangerObj3D() *PoolDangerObj3D

func (*PoolDangerObj3D) Get

func (*PoolDangerObj3D) Put

func (p *PoolDangerObj3D) Put(pb *DangerObj3D)

func (*PoolDangerObj3D) String

func (p *PoolDangerObj3D) String() string

type PoolFieldObj3D

type PoolFieldObj3D struct {
	// contains filtered or unexported fields
}

func NewPoolFieldObj3D

func NewPoolFieldObj3D() *PoolFieldObj3D

func (*PoolFieldObj3D) Get

func (*PoolFieldObj3D) Put

func (p *PoolFieldObj3D) Put(pb *FieldObj3D)

func (*PoolFieldObj3D) String

func (p *PoolFieldObj3D) String() string

type PoolLabel3D

type PoolLabel3D struct {
	// contains filtered or unexported fields
}

func NewPoolLabel3D

func NewPoolLabel3D() *PoolLabel3D

func (*PoolLabel3D) Get

func (p *PoolLabel3D) Get(str string) *Label3D

func (*PoolLabel3D) Put

func (p *PoolLabel3D) Put(pb *Label3D)

func (*PoolLabel3D) String

func (p *PoolLabel3D) String() string

type RaycastPlane

type RaycastPlane struct {
	Mesh js.Value
}

func NewRaycastPlane

func NewRaycastPlane() *RaycastPlane

func (*RaycastPlane) MoveCenterTo

func (pl *RaycastPlane) MoveCenterTo(fx, fy int)

type ShiftInfo

type ShiftInfo struct {
	X float64
	Y float64
	Z float64
}

func CarryObjClientOnFloor2DrawInfo

func CarryObjClientOnFloor2DrawInfo(
	co *c2t_obj.CarryObjClientOnFloor) ShiftInfo

type Tile3D

type Tile3D struct {
	// for texture tile
	SrcW     int
	SrcH     int
	SrcCnv   js.Value
	SrcWrapX func(int) int
	SrcWrapY func(int) int

	Cnv     js.Value
	Ctx     js.Value
	Tex     js.Value
	Mat     js.Value
	Geo     js.Value
	GeoInfo GeoInfo
	Tile    tile.Tile
}

func NewTile3D_BoxTexture

func NewTile3D_BoxTexture(tl tile.Tile, opacity float64) *Tile3D

func NewTile3D_Door

func NewTile3D_Door(opacity float64) *Tile3D

func NewTile3D_OctCylinderTexture

func NewTile3D_OctCylinderTexture(tl tile.Tile, opacity float64) *Tile3D

func NewTile3D_Tree

func NewTile3D_Tree(opacity float64) *Tile3D

func (*Tile3D) Dispose

func (aog *Tile3D) Dispose()

func (*Tile3D) DrawTexture

func (t3d *Tile3D) DrawTexture(srcx, srcy int)

func (*Tile3D) MakePosVector3

func (aog *Tile3D) MakePosVector3(fx, fy int) js.Value

func (*Tile3D) MakeSrcDark

func (aog *Tile3D) MakeSrcDark() *Tile3D

type TitleScene

type TitleScene struct {
	// contains filtered or unexported fields
}

func NewTitleScene

func NewTitleScene() *TitleScene

func (*TitleScene) Resize

func (ts *TitleScene) Resize(w, h float64)

type WasmClient

type WasmClient struct {

	// app info
	DoClose func()

	NotiMessage canvastext.CanvasTextList

	KeyboardPressedMap *jskeypressmap.KeyPressMap
	Path2dst           [][2]int
	ClientColtrolMode  clientcontroltype.ClientControlType

	AOUUID2AOClient       map[string]*c2t_obj.ActiveObjClient
	CaObjUUID2CaObjClient map[string]interface{}
	FloorInfoList         []*c2t_obj.FloorInfo
	CurrentFloor          *clientfloor.ClientFloor

	ServerJitter         *actjitter.ActJitter
	PingDur              time.Duration
	ServerClientTimeDiff time.Duration
	ClientJitter         *actjitter.ActJitter

	// from user input
	KeyDir   way9type.Way9Type
	MouseDir way9type.Way9Type

	OverLoadRate float64
	HPdiff       int
	SPdiff       int

	DispInterDur *intervalduration.IntervalDuration
	// contains filtered or unexported fields
}

func (*WasmClient) ActionResult2String

func (app *WasmClient) ActionResult2String(ar *aoactreqrsp.ActReqRsp) string

func (*WasmClient) Cleanup

func (app *WasmClient) Cleanup()

func (*WasmClient) DisplayTextInfo

func (app *WasmClient) DisplayTextInfo()

func (*WasmClient) GetEnvBias

func (app *WasmClient) GetEnvBias() bias.Bias

func (*WasmClient) GetPlayerActiveObjClient

func (app *WasmClient) GetPlayerActiveObjClient() *c2t_obj.ActiveObjClient

func (*WasmClient) GetPlayerXY

func (app *WasmClient) GetPlayerXY() (int, int)

func (*WasmClient) MakeNotiMessage

func (app *WasmClient) MakeNotiMessage() string

func (*WasmClient) NetInit

func (app *WasmClient) NetInit(ctx context.Context) error

func (*WasmClient) ReqWithRspFn

func (app *WasmClient) ReqWithRspFn(cmd c2t_idcmd.CommandID, body interface{},
	fn c2t_pid2rspfn.HandleRspFn) error

func (*WasmClient) ReqWithRspFnWithAuth

func (app *WasmClient) ReqWithRspFnWithAuth(cmd c2t_idcmd.CommandID, body interface{},
	fn c2t_pid2rspfn.HandleRspFn) error

func (*WasmClient) ResizeCanvas

func (app *WasmClient) ResizeCanvas()

func (*WasmClient) ServerTime

func (app *WasmClient) ServerTime() time.Time

func (*WasmClient) TowerBias

func (app *WasmClient) TowerBias() bias.Bias

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL